(defun for (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(print ix)))
> (for 0 6 2 nil)
0
2
4
6
(defun for (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(eval fnc)))
>(for 0 8 2 '(print ix))
error: unbound variable - ix
Why??
I use Xlisp and it don't have the "(loop for..)".
Could anybody help me?
Thank You very much
Dave
"Dave" <·········@iol.it> wrote in message news:<························@twister2.libero.it>...
[snip]
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (eval fnc)))
>
> >(for 0 8 2 '(print ix))
> error: unbound variable - ix
>
> Why??
> I use Xlisp and it don't have the "(loop for..)".
> Could anybody help me?
> Thank You very much
>
> Dave
I'm terrible at explaining these things, but here goes: There are
two "evaluations" occuring. Once at your prompt, and once at your
(eval... statement. At the prompt the argument '(print ix) is
evaluated to (print ix). At this time it is not yet executed, but
it's value is discovered to be a list with the function print in the
first entry, and some unbound symbol ix in the second (because, at
that first prompt, ix is not yet defined). So, at the prompt, your
expression is evaluated to the command "print some unbound symbol".
When this is finally passed down to the call to (eval... Lisp does
not attempt to re-investigate that unbound symbol. Instead it
evaluates "print some unbound symbol". Thus your error.
A possible solution: double quote it. ''(print ix)
You want to be careful using eval, though. In most implementation it
is slow and operates outside of any lexical context. In xLisp, though,
you can optionally pass in a third argument which is the environment
in which to evaluate the expression, so that might help matters. But
I use eval rarely, and never in xLisp, so what do I know?
Hope this helps, and, moreover, that my explanation isn't wildly wrong
or undecipherable.
Chris Perkins
Media Lab, Inc.
P.S. Upon re-reading it might be thought that I'm suggesting that
there is a difference between execution and evaluation, but that's not
what I mean. I just mean it hasn't been evaluated a second time (yet).
"Chris Perkins" <········@medialab.com> wrote:
> I'm terrible at explaining these things, but here goes: There are
> two "evaluations" occuring. Once at your prompt, and once at your
> (eval... statement. At the prompt the argument '(print ix) is
> evaluated to (print ix). At this time it is not yet executed, but
> it's value is discovered to be a list with the function print in the
> first entry, and some unbound symbol ix in the second (because, at
> that first prompt, ix is not yet defined). So, at the prompt, your
> expression is evaluated to the command "print some unbound symbol".
> When this is finally passed down to the call to (eval... Lisp does
> not attempt to re-investigate that unbound symbol. Instead it
> evaluates "print some unbound symbol". Thus your error.
>
> A possible solution: double quote it. ''(print ix)
>
I have tried but it does not seems to work very well.
Xlisp>(for 0 8 2 ''(print ix))
XLisp>8
I'm using Xlisp-plus 3.04 with Common Lisp extensions, by Tom Almy.
Thanks you for all explanations.
Dave
On Tue, Aug 19, 2003 at 06:31:48PM -0700, Chris Perkins wrote:
> Hope this helps, and, moreover, that my explanation isn't wildly wrong
It is, I'm afraid to say.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
On Tue, Aug 19, 2003 at 10:15:28PM +0000, Dave wrote:
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (eval fnc)))
>
> >(for 0 8 2 '(print ix))
> error: unbound variable - ix
Naturally: using EVAL evaluates the code in a null lexical environment.
IX is a lexical variable.
What you REALLY want to do is this:
(defun %for (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(funcall fnc ix)))
(%for 0 8 2 (lambda (i) (print i)))
and then
(defmacro for ((var start stop &optional (step 1)) &body body)
`(%for ,start ,stop ,step (lambda (,var) ,@body)))
(for (i 0 8 2) (print i))
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
On Wed, Aug 20, 2003 at 08:29:03AM +0000, Dave wrote:
> "Matthew Danish" <·······@andrew.cmu.edu> wrote:
> > (defmacro for ((var start stop &optional (step 1)) &body body)
> > `(%for ,start ,stop ,step (lambda (,var) ,@body)))
> XLISP> error: bad formal argument list
As Chris pointed out, XLISP does not have as good a macro facility as
Common Lisp. I wrote the code in CL, since I don't know XLISP. I
assume you can adapt it to your own purposes.
--
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (eval fnc)))
>
> >(for 0 8 2 '(print ix))
> error: unbound variable - ix
>
> Why??
> I use Xlisp and it don't have the "(loop for..)".
The mistake you made is to assume that the lexical variable ix in your
function definition is the same as the (assumed dynamic) variable
named by the symbol ix in the argument '(print ix). See section
3.1.2.1.1 "Symbols as Forms" in the hyperspec, or read any decent book
on lisp.
It's difficult to tell from this example what you actually wanted to
achieve. How general do you want this to be?
CL-USER 3 > (defun for-print (start stop step)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(print ix)))
FOR-PRINT
CL-USER 4 > (for-print 0 8 2)
0
2
4
6
8
CL-USER 5 > (defun for-funcall (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(funcall fnc ix)))
FOR-FUNCALL
CL-USER 6 > (for-funcall 0 8 2 'print)
0
2
4
6
8
CL-USER 7 > (defmacro for-ugly (start stop step fnc)
`(do ((ix ,start (+ ix ,step)))
((>= ix ,stop) ix)
,fnc))
FOR-UGLY
CL-USER 8 > (for-ugly 0 8 2 (print ix))
0
2
4
6
8
CL-USER 9 > (defmacro for-better ((var start stop &optional (step 1))
&body body)
`(do ((,var ,start (+ ,var ,step)))
((>= ,var ,stop) ,var)
,@body))
FOR-BETTER
CL-USER 10 > (for-better (ix 0 8 2)
(print ix))
0
2
4
6
8
CL-USER 11 >
"Dave" <·········@iol.it> wrote in message news:<························@twister2.libero.it>...
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (eval fnc)))
>
> >(for 0 8 2 '(print ix))
> error: unbound variable - ix
>
> Why??
IX is a lexical variable, visible only textually inside the form it is
defined in. You can do two things: either pass a function to FOR:
(defun for (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(funcall fnc ix)))
(for 0 8 2 #'(lambda (i) (print i)))
or make FOR a macro:
(defmacro for (start stop step body-form)
(let ((start-var (gensym))
(stop-var (gensym))
(step-var (gensym)))
`(let ((,start-var ,start)
(,stop-var ,stop)
(,step-var ,step))
(do ((ix ,start-var (+ ix ,step-var)))
((>= ix ,stop-var) ix)
,body-form))))
(for 0 8 2 (print ix))
or better:
(defmacro for (var start stop step body-form)
(let ((start-var (gensym))
(stop-var (gensym))
(step-var (gensym)))
`(let ((,start-var ,start)
(,stop-var ,stop)
(,step-var ,step))
(do ((,var ,start-var (+ ,var ,step-var)))
((>= ,var ,stop-var) ,var)
,body-form))))
(for i 0 8 2 (print i))
You might be interested in this tutorial:
http://www.psg.com/~dlamkins/sl/contents.html
--
Regards,
Alexey Dejneka
Matthew Danish's reply was a good one, but unfortunately xLisp isn't
CommonLisp enough to support it. defmacro doesn't support
destructuring bind, there's no funcall...
Dave, are you using xLisp 3.0? Have you looked at the macros.lsp file
that comes with it? It has great examples of do, dotimes, dolist, and
other macros that loop and perform the powerful trick of intentional
variable capture.
Here is a version of for xLisp that will do what you want:
;; WARNING: this is not Common Lisp, but xLisp which is more like
Scheme.
;; Usage: (for (var start stop step [result]) BODY)
;; Example: (for (ix 0 8 2 (format #t "exited loop because ~A" ix))
(print ix))
(define-macro (for range &body body)
(let ((counterVar (car range))
(startVar (cadr range))
(stopVar (caddr range))
(stepVar (cadddr range))
(result (car (cddddr range)))
(loop (gensym)))
`(let ,loop ((,counterVar ,startVar))
(if (<= ,counterVar ,stopVar)
(begin
,@body
(,loop (+ ,counterVar 1)))
,result))))
Besides letting you pass in start, stop, and step, it is set up so
that the user of the (for macro can pass in the name of the variable
that they want to be used for the counter. This way, both the return
and body expressions can refer to that variable. The user of the
(for macro doesn't have to know anything about an internal variable
named "ix" - because the user provides that variable name for the
macro.
Hope this helps,
Chris Perkins
Media Lab, Inc.
"Chris Perkins" <········@medialab.com> wrote:
> Matthew Danish's reply was a good one, but unfortunately xLisp isn't
> CommonLisp enough to support it. defmacro doesn't support
> destructuring bind, there's no funcall...
>
> Dave, are you using xLisp 3.0? Have you looked at the macros.lsp file
> that comes with it? It has great examples of do, dotimes, dolist, and
> other macros that loop and perform the powerful trick of intentional
> variable capture.
>
>...[cut]...
>
I'm using Xlisp-plus 3.04 with Common Lisp extensions, by Tom Almy.
I had forgotten to say that I would have need of a method that functions
well with XLISP and CLISP.
Many of your examples have worked very well.
Thanks all!!
Dave
In article <························@twister2.libero.it>,
"Dave" <·········@iol.it> wrote:
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (print ix)))
>
> > (for 0 6 2 nil)
> 0
> 2
> 4
> 6
>
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (eval fnc)))
>
> >(for 0 8 2 '(print ix))
> error: unbound variable - ix
>
> Why??
> I use Xlisp and it don't have the "(loop for..)".
> Could anybody help me?
> Thank You very much
I don't know much about Xlisp but since I have heard it is similar to
Common Lisp, here are some guesses:
+ CL's eval is executed in the current dynamic environment and the null
lexical environment. Because fnc is lexically bound, eval doesn't see
its binding. You could try to bind fnc to a dynamic/special variable and
use eval with that variable.
+ Another option in CL would be to use progv for that case. At least I
can imagine that it could be used for that purpose. On the other hand, I
don't have enough knowledge about the actually intended use of progv.
Maybe some CL experts on this list can tell us more.
So, maybe Xlisp also has progv.
+ Then again, why don't you make fnc a real lambda expression, as
follows?
(defun for (start stop step fnc)
(do ((ix start (+ ix step)))
((>= ix stop) ix)
(funcall fnc ix)))
(for 0 8 2 (lambda (ix) (print ix)))
Again, this is CL.
If you think that the lambda expression is a bit too verbose, a macro
could help:
(defmacro for (start stop step &body body)
`(do ((ix ,start (+ ix ,step)))
((>= ix ,stop) ix)
,@body))
(for 0 8 2
(print ix))
However, note two things:
+ The macro above is a rough sketch. I haven't tested it, and especially
step and stop are not evaluated in the correct order (from left to
right).
+ It seems a little questionable to make the symbol ix visible in the
body. I think it would be better to let the user of the macro choose an
explicit name, like this: (for ix 0 8 2 ...)
I don't know if these remarks are of any help to you, but I hope so. ;)
Pascal
"Pascal Costanza" <········@web.de> wrote:
> + Then again, why don't you make fnc a real lambda expression, as
> follows?
>
> (defun for (start stop step fnc)
> (do ((ix start (+ ix step)))
> ((>= ix stop) ix)
> (funcall fnc ix)))
>
> (for 0 8 2 (lambda (ix) (print ix)))
It works fine.
> If you think that the lambda expression is a bit too verbose, a macro
> could help:
>
> (defmacro for (start stop step &body body)
> `(do ((ix ,start (+ ix ,step)))
> ((>= ix ,stop) ix)
> ,@body))
>
> (for 0 8 2
> (print ix))
>
I have tried but it does not seems to work..
XLisp> error: too few arguments
Thanks you for all explanations.
Dave