chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Binding identifiers with set!


From: Bruce Hoult
Subject: Re: [Chicken-users] Binding identifiers with set!
Date: 14 Oct 2003 15:15:53 +1300

On Tue, 2003-10-14 at 12:53, felix wrote:
> On 14 Oct 2003 12:08:01 +1300, Bruce Hoult <address@hidden> wrote:
> 
> >
> > I think that would be immensely better than the current behaviour, but
> > not ideal.  Consider something like:
> >
> > (let ((l '((a . 1) (b . 2) (c . 3) (d . 4))))
> > (define elt (caddr l))
> > (define key (car elt))
> > (define val (cdr elt))
> > (print "key=" key " val=" val))
> >
> >
> > => key=c val=3
> >
> >
> > At the moment this works, albeit by polluting the global namespace.
> 
> Actually this expands into:
> 
> (let ((l0 '((a . 1) (b . 2) (c . 3) (d . 4))))
>   (let ((elt1 (##core#undefined))
>         (key2 (##core#undefined))
>         (val3 (##core#undefined)))
>     (let ((t4 (set! elt1 (caddr l0))))
>       (let ((t5 (set! key2 (car elt1))))
>         (let ((t6 (set! val3 (cdr elt1))))
>           (print '"key=" key2 '" val=" val3))))))
> 

Sorry, change my example to include some random thing after the let:

(let ((l '((a . 1) (b . 2) (c . 3) (d . 4))))
  (print "got here!")
  (define elt (caddr l))
  (define key (car elt))
  (define val (cdr elt))
  (print "key=" key " val=" val))

At the moment this creates/modifies three global variables.

So under your proposed change I expect it would be:

(let ((l0 '((a . 1) (b . 2) (c . 3) (d . 4))))
 (print "got here!")
 (let ((elt1 (##core#undefined))
       (key2 (##core#undefined))
       (val3 (##core#undefined)))
   (let ((t4 (set! elt1 (caddr l0))))
     (let ((t5 (set! key2 (car elt1))))
       (let ((t6 (set! val3 (cdr elt1))))
         (print '"key=" key2 '" val=" val3))))))

I guess that seems pretty good to me.  It's not *quite* as efficient as
perhaps possible, but does have useful semantics if you guarantee and
document the evaluation order.  And it retains letrec's virtue of
allowing the declaration of mutually-recursive functions.  Or
self-recursive ones, if you make even a single internal "define" create
the binding and then set! it.

Of course it depends on the user not giving the -strict-letrec flag!

Perhaps your creative implementation of letrec should be documented
under deviations (enhancements?) from the standard, and not just under
the chicken/csc/csi flags?  I guess it's a compatible enhancement.  R5RS
says "[in a letrec] it must be possible to evaluate each <init> without
assigning or referring to the value of any <variable>.  If this
restriction is violated then it is an error."  That means Chicken can
implement it any way that it wants -- can e.g. define and document the
evaluation order -- but *programs* that depend on it are non-portable. 
It is compatible because strict R5RS code will still work fine.


I vote for this plan.


-- 
Bruce Hoult <address@hidden>





reply via email to

[Prev in Thread] Current Thread [Next in Thread]