unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* srfi-1 map!
@ 2003-11-11  0:32 Kevin Ryde
  2003-11-11 14:58 ` a circular dilemma . #0# (was Re: srfi-1 map!) Stephen Compall
  0 siblings, 1 reply; 5+ messages in thread
From: Kevin Ryde @ 2003-11-11  0:32 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 194 bytes --]

I've been finding it a bit annoying that map can handle long lists but
map! can't.

        * srfi-1.scm (map!): Define as an alias for map, previous definition
        was not tail-recursive.


[-- Attachment #2: srfi-1.scm.mapx.diff --]
[-- Type: text/plain, Size: 702 bytes --]

--- srfi-1.scm.~1.29.~	1970-01-01 10:00:01.000000000 +1000
+++ srfi-1.scm	2003-11-11 10:28:35.000000000 +1000
@@ -572,22 +572,8 @@
 	'()
 	(append! (apply f (map1 car l)) (lp (map1 cdr l)))))))
 
-(define (map! f list1 . rest)
-  (if (null? rest)
-    (let lp ((l list1))
-      (if (null? l)
-	'()
-	(begin
-	  (set-car! l (f (car l)))
-	  (set-cdr! l (lp (cdr l)))
-	  l)))
-    (let lp ((l (cons list1 rest)) (res list1))
-      (if (any1 null? l)
-	'()
-	(begin
-	  (set-car! res (apply f (map1 car l)))
-	  (set-cdr! res (lp (map1 cdr l) (cdr res)))
-	  res)))))
+;; OPTIMIZE-ME: Re-use cons cells of given list(s)
+(define map! map)
 
 (define (pair-for-each f clist1 . rest)
   (if (null? rest)

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* a circular dilemma . #0# (was Re: srfi-1 map!)
  2003-11-11  0:32 srfi-1 map! Kevin Ryde
@ 2003-11-11 14:58 ` Stephen Compall
  2003-11-14 19:28   ` Kevin Ryde
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Compall @ 2003-11-11 14:58 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> writes:

> I've been finding it a bit annoying that map can handle long lists
> but map! can't.

You're right, that is annoying.  So annoying, I wrote a new version,
and ran into some problems with circular lists.

Here is the first version.  I suppose I should have used any1 instead
of the two hand-rollings, but I saw it too late.  On the same note,
you have to bring map1, an internal from srfi-1.scm, into scope.

;;see if any list in LISTLIST has only one element
(define (any-alone? listlist)
  (cond
   ((null? listlist) #f)
   ((null? (cdar listlist)) #t)
   (else (any-alone? (cdr listlist)))))

(define (s11-map! f list1 . rest)
  ;; First, make sure list1 is not empty, and rest contains no empty
  ;; lists.
  (if (or (null? list1)
          (let lp ((lists rest))
            (cond
             ((null? lists) #f)
             ((null? (car lists)) #t)
             (else (lp (cdr lists))))))
      ;; BTW, I'm going to return list1.
      (set! list1 '())
    ;; OK, all cars are conses, with real elements to callback with
    (let nextelem ((clist1 list1) (crest rest))
      (set-car! clist1 (apply f (car clist1) (map1 car crest)))
      ;; Will that be true on the next round?
      (if (or (null? (cdr clist1)) (any-alone? crest))
          ;; If not, cut the list off here
          (set-cdr! clist1 '())
        (nextelem (cdr clist1) (map1 cdr crest)))))
  list1)

Which worked wonderfully for all sorts, even with circulars in REST,
until I started setting circulars to LIST1 with "longer" (that is,
those with more cons cells) but proper lists.

guile> (define mylist (circular-list 1 2 3 4))
guile> mylist
(1 2 3 4 . #0#)
guile> (map + mylist '(0 0 0 0 0 0))
(1 2 3 4 1 2)
guile> (s11-map! + mylist '(0 0 0 0 0 0))
(1 2)

The problem is, of course, even larger when your function returns
something other than its first argument.

So I modified it like so:

(define (s11-map! f list1 . rest)
  ;; First, make sure LIST1 is not empty, and rest contains no empty
  ;; lists.
  (if (or (null? list1)
          (let lp ((lists rest))
            (cond
             ((null? lists) #f)
             ((null? (car lists)) #t)
             (else (lp (cdr lists))))))
      ;; BTW, I'm going to return LIST1.
      (set! list1 '())
    ;; OK, all cars are conses, with real elements to callback with
    (let nextelem ((clist1 list1) (crest rest))
      (set-car! clist1 (apply f (car clist1) (map1 car crest)))
      (cond
       ;; circular LIST1...append new cells instead
       ((eq? (cdr clist1) list1)
        (set-cdr! clist1 (apply map f list1 (map1 cdr crest))))
       ;; rest of system handles circulars in REST just fine
       ;; If no more elements, cut LIST1 off here
       ((or (null? (cdr clist1)) (any-alone? crest))
        (set-cdr! clist1 '()))
       (else
        (nextelem (cdr clist1) (map1 cdr crest))))))
  list1)

Of course, this doesn't compensate for the circular list being a
sublist of LIST1 (e.g. (cons* -1 0 (circular-list 1 2 3 4))), but at
least produces a list of the proper length.

guile> mylist
(1 2 3 4 . #0#)
guile> (s11-map! + mylist '(0 0 0 0 0 0))
(1 2 3 4 1 2)
guile> mylist
(1 2 3 4 1 2)

But the values!

guile> (set! mylist (circular-list 1 2 3 4))
guile> (s11-map! + mylist '(1 1 1 1 1 1))
(2 3 4 5 3 4)
guile> (map + (circular-list 1 2 3 4) '(1 1 1 1 1 1))
(2 3 4 5 2 3)

Well, that isn't good!  And of course:

guile> (set! mylist (cons* 1 2 (circular-list 3 4 5 6)))
guile> (map + mylist '(1 1 1 1 1 1 1 1))
(2 3 4 5 6 7 4 5)
guile> (s11-map! + mylist '(1 1 1 1 1 1 1 1))
(2 3 5 6)

Which is the same problem the original had.

So, is there any way out of this problem, other than to dump the
second version (which is needlessly more complicated, I now think),
and shunt any call where LIST1 doesn't meet list? to map?  Or just
live with "undefined behavior" given by the silly (IMHO) case of
having a circular as LIST1 where a list in REST has more cells?  Or
what?

Did I mention I like [my] original version better?  Yeah.

--
Stephen Compall or s11 or sirian

Logic is a pretty flower that smells bad.

SCUD missile cybercash Kosovo Ermes New World Order ASPIC KGB
government munitions satellite imagery investigation csystems
fissionable e-cash MIT-LL


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: a circular dilemma . #0# (was Re: srfi-1 map!)
  2003-11-11 14:58 ` a circular dilemma . #0# (was Re: srfi-1 map!) Stephen Compall
@ 2003-11-14 19:28   ` Kevin Ryde
  2003-11-17 20:21     ` Stephen Compall
  0 siblings, 1 reply; 5+ messages in thread
From: Kevin Ryde @ 2003-11-14 19:28 UTC (permalink / raw)


Stephen Compall <s11@member.fsf.org> writes:
>
> (define (s11-map! f list1 . rest)

If you want to write some code, copying and adapting the current C
code would probably be much better.

> Or just
> live with "undefined behavior" given by the silly (IMHO) case of
> having a circular as LIST1 where a list in REST has more cells?

I see the spec calls for list2 etc to have at least as many elements
as list1.  Which I guess means list1 is finite (ie. non-circular) and
can be used to construct the return without further checking.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: a circular dilemma . #0# (was Re: srfi-1 map!)
  2003-11-14 19:28   ` Kevin Ryde
@ 2003-11-17 20:21     ` Stephen Compall
  2003-11-18 22:57       ` Kevin Ryde
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Compall @ 2003-11-17 20:21 UTC (permalink / raw)


Kevin Ryde <user42@zip.com.au> writes:

> If you want to write some code, copying and adapting the current C
> code would probably be much better.

Would this be added to libguile-srfi-srfi-1.so?  I just wrote it in
Scheme to go with the context; it was a function eliminated from
srfi-1.scm, eh?

> I see the spec calls for list2 etc to have at least as many elements
> as list1.  Which I guess means list1 is finite (ie. non-circular)
> and can be used to construct the return without further checking.

Ah, I misinterpreted this.  This makes my life much easier, now that I
know I am not pathetic and weak.  Thanks. :)

--
Stephen Compall or s11 or sirian

My method is to take the utmost trouble to find the right thing to say.
And then say it with the utmost levity.
		-- G.B. Shaw

chameleon man INSCOM Mantis Mena Geraldton Rule Psix offensive
information warfare North Korea Skipjack Aldergrove Rubin Echelon
Leuken-Baden counter intelligence bullion


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: a circular dilemma . #0# (was Re: srfi-1 map!)
  2003-11-17 20:21     ` Stephen Compall
@ 2003-11-18 22:57       ` Kevin Ryde
  0 siblings, 0 replies; 5+ messages in thread
From: Kevin Ryde @ 2003-11-18 22:57 UTC (permalink / raw)
  Cc: guile-devel

Stephen Compall <s11@member.fsf.org> writes:
>
> Would this be added to libguile-srfi-srfi-1.so?

srfi-1.c, which is where the current map lives.  Making aliases or
easy things may as well be done in the .scm.


_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-11-18 22:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-11  0:32 srfi-1 map! Kevin Ryde
2003-11-11 14:58 ` a circular dilemma . #0# (was Re: srfi-1 map!) Stephen Compall
2003-11-14 19:28   ` Kevin Ryde
2003-11-17 20:21     ` Stephen Compall
2003-11-18 22:57       ` Kevin Ryde

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).