> > 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?
No, but the environment must encapsulate symbols _and_ values, not just
values. Just a list of values doesn't make an environment.
> > 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.
This is not what I'm talking about.
What I mean is to separate the _activation_ of an environment from its
_execution_. In PicoLisp, the call to 'job' (the activation of the
environment) can be in a library, not only the definition.
Only this makes it possible, for example, to store code fragments like
(foo X Y) as event handlers, button actions or update managers in GUI
components. The library (i.e. the 'form' function) maintains
environments in all forms and dialogs, and activates them as necessary
before running those handlers and actions in the form's context.
SYMBOL-MACROLET can't do that. It always encapsulates the environment's
activation _and_ the code body. And your defmacro'd 'job' must therefor
expand in the application domain.
To bring it to the point: First class environments are _useless_ if you
cannot separate activation and execution. If activation and execution
are in the same place, you can as well just pass a list of values
(without the symbols) and use 'let' or function application to bind them
to the symbols locally.
This explains perhaps why they are not an issue in other programming
languages. At least not in lexically scoped languages.
I think I have to write an article in the PicoLisp Wiki to explain all
> > 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.
You are right. I'm always surprised (since the times I cooperated with
COBOL programmers) how some people prefer verbose code, but I should not
judge about it.
Still, most of that verbosity is inherent in CL, and you can't avoid it.
So it was more the taste of the original language designers.
> (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
Right. But now you avoided the issue of variable bindings all together,
so that we cannot talk of an "environment" here any longer. And, as
ever, it doesn't separate the activation and execution of the
As far as the RosettaCode task is concerned (which doesn't need that
separation), this would be the cleanest solution so far.
But it also confirms my initial statement, that proper first class
environments (handling creation, activation and execution independently)
cannot be done with pure lexical binding.