[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: for-each et al
From: |
Ludovic Courtès |
Subject: |
Re: for-each et al |
Date: |
Sun, 02 Mar 2014 22:27:52 +0100 |
User-agent: |
Gnus/5.130007 (Ma Gnus v0.7) Emacs/24.3 (gnu/linux) |
Hello!
Welcome back to email. ;-)
Andy Wingo <address@hidden> skribis:
> The current boot-9 for-each for one list argument is this nastiness:
>
> (define for-each
> (case-lambda
> ((f l)
> (let for-each1 ((hare l) (tortoise l))
> (if (pair? hare)
> (begin
> (f (car hare))
> (let ((hare (cdr hare)))
> (if (pair? hare)
> (begin
> (when (eq? tortoise hare)
> (scm-error 'wrong-type-arg "for-each" "Circular
> list: ~S"
> (list l) #f))
> (f (car hare))
> (for-each1 (cdr hare) (cdr tortoise)))
> (for-each1 hare tortoise))))
> (if (not (null? hare))
> (scm-error 'wrong-type-arg "for-each" "Not a list: ~S"
> (list l) #f)))))
> ...))
>
> Terrible. And it's slower than this:
>
> (lambda (f l)
> (unless (list? l)
> (scm-error 'wrong-type-arg "for-each" "Not a list: ~S" (list l) #f))
> (let for-each1 ((l l))
> (unless (null? l)
> (f (car l))
> (for-each1 (cdr l)))))
>
> So, pop quiz: what's the difference between the two?
I think an important difference you didn’t mention is that ‘list?’ does
its list traversal in C.
> Of course, there are different levels at which this problem can be
> solved. I think moving towards deprecation and removal of mutable pairs
> is probably a good idea, though it's really complicated and not really
> the point of this mail. OTOH I think it's reasonable to ask for a
> consensus opinion on this implementation of "for-each":
>
> (lambda (f l)
> (unless (list? l)
> (scm-error 'wrong-type-arg "for-each" "Not a list: ~S" (list l) #f))
> (let for-each1 ((l l))
> (unless (null? l)
> (f (car l))
> (for-each1 (cdr l)))))
>
> Is this a reasonable implementation? Are we OK with the possibility for
> infinite-loops or exceptions accessing the car/cdr of what might not be
> a pair? Alternately if we change the test to pair? are we OK with the
> possibility of the loop possibly ending silently before its time? How
> do we deal with this kind of bug -- what's our perspective?
I’m OK with this implementation. I’ve never found myself iterating over
a list and modifying it concurrently.
> My proposal would be that eventually, I don't know how, but Guile should
> remove all use of mutable pairs in its own code. There's not much
> set-car!/set-cdr! in Scheme so it's not that big of a deal. Therefore
> in light of that long-term goal, we should write library code as if
> pairs were immutable, and therefore the test-then-iterate example is
> fine code.
>
> WDYT?
I’m all in favor of immutable pairs. However, I expect that a lot of
code out there relies on it.
Moving set-car! and set-cdr! to a different module like in R6 may be a
good first (or second) step.
Thanks,
Ludo’.
- for-each et al, Andy Wingo, 2014/03/02
- Re: for-each et al,
Ludovic Courtès <=