[plt-scheme] Best practices when writing macros; avoid name shadowing?
Have you ever heard "hygienic macro" before? If not, google.
Chongkai
Grant Rettke wrote:
> Tonight I was working on a problem from
> _The_Scheme_Programming_Language_3rd_Edition,
> in particular Exercise 3.2.5 in
> http://www.scheme.com/tspl3/further.html#./further:h2.
>
> In this problem you goal is to augment a given version of `let` to
> handle `named let` using letrec.
>
> I worked on the problem and came up with solution that made sense and
> according to my rudimentary
> testing worked. The expanded code was what I expected to see, and that
> code did what I expected. When I checked
> the answer, it was wrong, but only by a bit, and I didn't understand
> why since it worked. The error was later demonstrated
> to me.
>
> Here is the source:
>
> (custom-let ([fun '(a b c)])
> (custom-let fun ([ls fun])
> (unless (null? ls)
> (printf "~s\n" (car ls))
> (fun (cdr ls)))))
>
> My wrong version of expanded code:
>
> ((lambda (fun)
> (letrec ([fun (lambda (ls)
> (unless (null? ls)
> (printf "~s\n" (car ls))
> (fun (cdr ls))))])
> (fun fun))) '(a b c))
>
> The correct way to expand the code:
>
> ((lambda (fun)
> ((letrec ((fun (lambda (ls)
> (unless (null? ls)
> (printf "~s\n" (car ls))
> (fun (cdr ls)))))) fun)
> fun)) '(a b c))
>
> I see the error, the function name in the letrec block shadows the
> name of the list in the enclosing lambda block.
>
> Is this a lesson that you learn writing macros, to be sure not to
> shadow variables in your expansion?
>
> There must be tons of hairy situations that folks who heavily utilize
> the macro system have to avoid!
>
> All thoughts appreciated on this one.
> _________________________________________________
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>