Hi Alex,
> I just wanted to say that your "1st try" is not a solution to the
> task.
well, the task doesn't say that the environment must be represented as
an alist, or does it?
> As I said, I completely understood your code. SYMBOL-MACROLET is analog
> to 'job'.
No it is not, it allows me to implement job to work like in picolisp.
> This makes it impossible to abstract away the 'job' and put it into a
> library, as is the case in the PicoLisp GUI.
What do you mean? I wrote job as a separate defmacro, it's completely
self contained, it does the same thing as in picolisp and one can move
it into any file one wishes.
> SYMBOL-MACROLET is a way to _bypass_ the restrictions of lexical scope.
> It is in CL for the same reason as there are "special" (dynamically
> bound) variables: Such features are needed. But they are there to
> circumvent the lexical paradigm.
Yes. It is there to override the meaning of symbols that would
otherwise be understood to represent variables (lexical or special).
> But: Can you use closures with environments read from a database, or
> communicated across an RPC call?
Unlikely, not portably, only if the implementation somehow exposes that.
Or at least it is not normaly done. But for example, I can see the
closed over variables in debugger so maybe there would be a way of doing
that. But you can use SYMBOL-MACROLET to use custom environment, to
look up the values wherever you want.
> I didn't say there is any magic. It is just practical.
It is indeed:-D
> convenient. That's what it is all about in PicoLisp. Keep it simple! You
> can do everything in CL you can do in Pil, of course, but it usually
> looks bigger and uglier (check the other CL solutions in RosettaCode).
True, but that is not inherent feature of Common Lisp I think, it's more
related to the tastes of those programmers.
>> > With that, a Picolisp call like
>> >
>> > (job <environment>
>> > <body> )
>> >
>> > becomes to
>> >
>> > (funcall
>> > (job (var1 var2 var3 ...)
>> > <body> )
>> > <environment> )
>> >
>> > which does not really taste like simply executing some code body
>> > within an environment. This might explain why first class environments
>> > are not an issue in CL.
>>
>> You missed the most important part, the SYMBOL-MACROLET part. That
>> changes the meaning of the var1... symbols from "symbol representing a
>> variable" to "symbol representing access to something".
>
> That's picky. Syntacially, (job (var1 var2 var3 ...) is like 'let' or 'lambda'
>
> (let ((var1 <val1>) (var2 <val2>))
> <body> )
>
> (funcall (lambda (x y) (* x y)) <val1> <val2>)
No, that would not work because you could not modify the environment in
the <body> for the same reason it would not work in PicoLisp.
With the definition of job like this:
(defmacro job (env &body body)
(let ((x (gensym))
(args (find-free-variables body)))
`(let ((,x ,env))
(symbol-macrolet (,@(mapcar (lambda (y) `(,y (cdr (assoc ',y ,x))))
args))
,@body))))
code like this:
(job e
(format t "~4d" n)
(unless (= 1 n)
(incf cnt)
(setq n (if (= 1 (logand 1 n)) (1+ (* n 3)) (/ n 2)))))
would expand to something like:
(let ((#:G1234 e))
(format t "~4d" (cdr (assoc 'n e)))
(unless (= 1 (cdr (assoc 'n e)))
(incf (cdr (assoc 'cnt e)))
(setf (cdr (assoc 'n e))
(if (= 1 (logand 1 (cdr (assoc 'n e))))
(1+ (* (cdr (assoc 'n e)) 3))
(/ (cdr (assoc 'n e)) 2)))))
So in fact, there are no (lexical or special) variables n and cnt at
all.
Cheers,
Tomas
--
UNSUBSCRIBE: mailto:[email protected]?subject=Unsubscribe