[plt-scheme] Re: trying not to use eval - in a define-syntax
On Tuesday, October 29, 2002, at 09:49 PM, Jim Witte wrote:
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
>>> I want to take the value from a variable and use it as a procedure
>>> name, and have it be evaluated. I remember running across some
>>> advice in a text that using eval was *BAD*, but I am stumped on how
>
> I want to make a 'foreach' syntax which would function like map,
> except that it would (1) go in order (instead of arbitrary), (2) pass
> in the reference for each element the function is currently
> processing, and (3) be able to pass in an arbirary number of 'static'
> variables that don't change from one invocation to the other: So I
> could do something like this silly example:
>
> (define add-index-and-constant
> (lambda (el i a)
> (+ el i a)))
>
> (foreach with-vars add-index-and-constant '(1 2 3 4) '(10))
> --> (10 13 15 17)
The first element of this should be eleven, right?
If I understand you correctly, you don't need a macro at all.
First, your "with-vars" construct is subsumed by lambda. That is, if I
want to take your 'add-index-and-constant' and produce a function like
it that always gets 10 as its third argument, I can just write (lambda
(el i) (add-index-and-constant el i 10)). If you want to generalize
this, you can write a 'with-vars' function that takes a closure and a
list of arguments, and produces a closure which appends those arguments
to the ones passed in. The code is clearer than the english here:
(define with-vars
(lambda (fn static-arg-list)
(lambda args
(apply fn (append args static-arg-list)))))
As for the index argument, you can add this in a similar way, just by
writing a function. I'm calling it indexed-map rather than
indexed-for-each because (unlike a for-each) it returns the list of
results:
(define indexed-for-each
(lambda args
(when (< (length args) 2)
(error 'indexed-for-each "indexed for-each requires at least two
arguments. Given: ~v" (length args)))
(apply map (append args (list (build-list (length (cadr
args))(lambda (x) x)))))))
; Does it work?:
(define (add-index-and-constant el i a)
(+ el i a))
(indexed-for-each (with-vars add-index-and-constant '(10)) '(1 2 3 4))
=> (11 13 15 17)
Voila! and you get the multiple-args stuff for free.
In many languages, this might require a macro, because of the variable
numbers of arguments. This is a nice example of Scheme's strength; you
don't need to dip into the macro layer to solve this problem.
Hope this helps,
john clements