[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: |
Tue, 04 Mar 2014 23:35:44 +0100 |
User-agent: |
Gnus/5.130007 (Ma Gnus v0.7) Emacs/24.3 (gnu/linux) |
Andy Wingo <address@hidden> skribis:
> On Sun 02 Mar 2014 22:27, address@hidden (Ludovic Courtès) writes:
[...]
>> I think an important difference you didn’t mention is that ‘list?’ does
>> its list traversal in C.
>
> That's true. Let's call the above version for-each*. Then we have
> for-each**, which is the same except it calls list*, which is:
>
> (define (list*? l)
> (let lp ((hare l) (tortoise l))
> (or (null? hare)
> (and (pair? hare)
> (let ((hare (cdr hare)))
> (or (null? hare)
> (and (pair? hare)
> (not (eq? tortoise hare))
> (lp (cdr hare) (cdr tortoise)))))))))
>
> Then we have:
>
> scheme@(guile-user)> (define l (iota 100000000))
> scheme@(guile-user)> ,time (for-each** (lambda (x) x) l)
> ;; 3.228201s real time, 3.223919s run time. 0.000000s spent in GC.
> scheme@(guile-user)> ,time (for-each* (lambda (x) x) l)
> ;; 2.356612s real time, 2.353496s run time. 0.000000s spent in GC.
> scheme@(guile-user)> ,time (for-each (lambda (x) x) l)
> ;; 3.142366s real time, 3.126806s run time. 0.000000s spent in GC.
>
> So the overhead of traversing the list twice is negligible in the worst
> case, and probably we still gain once the compiler gets better.
Yes.
>>> (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)))))
>
>> I’m OK with this implementation. I’ve never found myself iterating over
>> a list and modifying it concurrently.
>
> Yeah it's something that no one in their right mind does. But still we
> should have some kind of statement about what we guarantee -- currently
> the code is resilient to concurrent mutation, and we'd be relaxing that.
Right. R5 and R6 don’t say anything about that, but yes, we can add a
statement in the manual and NEWS to that effect.
I think the for-each change would be for 2.2, right?
>> 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.
>
> Brainstorming possibilities:
>
> * Deprecate set-car!/set-cdr! (replacement would be mutable cells in
> the car/cdr; currently called variables, but could be called boxes)
SRFI-111 boxes.
We should check a few existing packages and usage patterns before.
For instance, I suspect SCM_SETCAR/SCM_SETCDR are actually more
widespread than their Scheme counterparts, and probably much harder to
avoid. What can we do with them?
Another issue: what about elisp? It needs mutable pairs, but we don’t
want to have it use a disjoint type.
> * Introducing a #!lang facility, and having programs with #!lang make
> immutable pairs
Not really fan of the idea. :-)
Thanks,
Ludo’.