From: Pascal J. Bourguignon on
Pascal Costanza <pc(a)p-cos.net> writes:

> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>> On 14.3.2010 20:11, Eli Barzilay wrote:
>>
>> Excellent post, Eli. However, I'm interested
>> in this part:
>>
>>> One point that can help getting some enlightenment is that hygiene is
>>> a crucial aspect of these kind of language games -- and I'm talking
>>> about both sides of it: both the part that you solve in CL with a
>>> gensym, and the part that cannot be solved by a macro (where you want
>>> to avoid names in the result of macros from being captured by names
>>> that happen to be bound in the call site). The latter is usually
>>> dismissed by CLers as not being too important, yet it is IME even more
>>> important than the first one when you're dealing with creating a new
>>> language.
>>
>> It is not obvious to me that this second part
>> of hygiene, i.e. macros that use the values
>> of the symbols from macro definition environment,
>> not environment of use, is impossible in CL
>> macro systems without some package or namespaces.
>>
>> Why do you claim that, Eli? If answer is not simple,
>> do you have any reference with more detailed
>> discussion?
>>
>> Do CL-ers agree with Eli?
>
> What Eli says is correct, but only relevant when you use local macro
> definitions. A canonical example is this:
>
> (let ((x 1))
> (macrolet ((foo () 'x))
> (let ((x 2))
> (foo))))
>
> You have two variable bindings for x, and the expansion of foo will
> refer to the inner one, so this form will yield 2. If you want to keep
> the name x for both variable bindings, there is no way in Common Lisp
> to reliably rewrite the macro foo such that it unambiguously refers to
> the outer x, without adding some serious heavy machinery on top of
> Common Lisp.
>
> Of course, you could decide to rename one of the two variable bindings.
>
> For global macro definitions, packages are sufficient to protect you
> from such problems. (You still need to be careful, of course.)


I would argue that a macro that wants to capture (parts of) the lexical
environment, should have a &body parameter!

(let ((x 1))
(macrolet ((foo (&body body)
;; now we need to come to the specifics of the macro
;; your example, is somewhat tasteless...
;; If the point is to get the value of x
;; and be able to refer it in body we could
;; write:
`(flet ((get-the-x-in-foo-environment () x)
((setf get-the-x-in-foo-environment) (v) (setf x v)))
,@body)))
(foo
;; the body:
(let ((x 2))
(print (get-the-x-in-foo-environment))
(setf (get-the-x-in-foo-environment) 0))))
x)

prints: 1
--> 0




My argument is that writing:

(let ((x 2))
(foo))

to get an X from an outer scope is wrong, that we should write:

(with-outer-scope-x
(let ((x 2))
(outer-scope-x))) ; or something.

and that Common Lisp makes you write the right thing.


--
__Pascal Bourguignon__
From: Tim Bradshaw on
On 2010-03-26 22:09:39 +0000, Pascal J. Bourguignon said:

> Sure, assembler is fun too, but to write bigger than trivial programs,
> it's more fun to use lisp than assembler.

I'm not really sure that's true. I've written bigger than trivial
programs (not perhaps in image size but in
doing-quite-a-lot-of-fiddly-stuff size) in assembler and enjoyed it a
great deal.

From: Hugh Aguilar on
On Mar 26, 4:09 pm, p...(a)informatimago.com (Pascal J. Bourguignon)
wrote:
> But since you program mainly as a hobby, you could choose a pleasurable
> programming language and environment. I mean Lisp!
>
> Sure, assembler is fun too, but to write bigger than trivial programs,
> it's more fun to use lisp than assembler.

I lot of the hobby-type programs I write involve recursive descent
searches. Using assembler or Forth can turn hours into minutes. As an
example, in my novice Forth package I have a program that analyzes low-
draw poker probabilities by doing a complete traversal of every
possible poker hand. This provides much more accurate probabilities
than the Monte Carlo "analysis" programs that other people have
written. In SwiftForth the program executes in a couple of seconds. I
would be very dubious of any Scheme or Lisp system generating
comparable code --- what we Forth programmers refer to as "hella-
fast!" :-) My slide-rule program running under SwiftForth takes maybe
five seconds to generate all the files (it is recursive internally).
It might take five minutes under PLT Scheme, which is too long for an
interactive GUI program. I'm not worried though, because I can
generate the scales ahead of time and store them, rather than do the
work while the user is waiting.

My interest in PLT Scheme is actually the exact opposite of what you
said. I want to learn how to write GUI software so that my programs
look more "professional." Most non-technical people consider console
user-interface to be the hallmark of the amateur hobbyist.

The most likely outcome of all this is that I will use PLT Scheme for
generating GUI front-ends to programs written in assembly language or
Forth. Previously it was mentioned that PLT Scheme has a Pentium
assembler --- I will probably use that. I like Forth assemblers, so I
should like Lisp assemblers too. I mostly dislike traditional
assemblers such as MASM --- ugh!
From: Pascal Costanza on
On 26/03/2010 23:24, Pascal J. Bourguignon wrote:
> Pascal Costanza<pc(a)p-cos.net> writes:
>
>> On 25/03/2010 07:51, Kazimir Majorinc wrote:
>>> On 14.3.2010 20:11, Eli Barzilay wrote:
>>>
>>> Excellent post, Eli. However, I'm interested
>>> in this part:
>>>
>>>> One point that can help getting some enlightenment is that hygiene is
>>>> a crucial aspect of these kind of language games -- and I'm talking
>>>> about both sides of it: both the part that you solve in CL with a
>>>> gensym, and the part that cannot be solved by a macro (where you want
>>>> to avoid names in the result of macros from being captured by names
>>>> that happen to be bound in the call site). The latter is usually
>>>> dismissed by CLers as not being too important, yet it is IME even more
>>>> important than the first one when you're dealing with creating a new
>>>> language.
>>>
>>> It is not obvious to me that this second part
>>> of hygiene, i.e. macros that use the values
>>> of the symbols from macro definition environment,
>>> not environment of use, is impossible in CL
>>> macro systems without some package or namespaces.
>>>
>>> Why do you claim that, Eli? If answer is not simple,
>>> do you have any reference with more detailed
>>> discussion?
>>>
>>> Do CL-ers agree with Eli?
>>
>> What Eli says is correct, but only relevant when you use local macro
>> definitions. A canonical example is this:
>>
>> (let ((x 1))
>> (macrolet ((foo () 'x))
>> (let ((x 2))
>> (foo))))
>>
>> You have two variable bindings for x, and the expansion of foo will
>> refer to the inner one, so this form will yield 2. If you want to keep
>> the name x for both variable bindings, there is no way in Common Lisp
>> to reliably rewrite the macro foo such that it unambiguously refers to
>> the outer x, without adding some serious heavy machinery on top of
>> Common Lisp.
>>
>> Of course, you could decide to rename one of the two variable bindings.
>>
>> For global macro definitions, packages are sufficient to protect you
>> from such problems. (You still need to be careful, of course.)
>
>
> I would argue that a macro that wants to capture (parts of) the lexical
> environment, should have a&body parameter!
>
> (let ((x 1))
> (macrolet ((foo (&body body)
> ;; now we need to come to the specifics of the macro
> ;; your example, is somewhat tasteless...
> ;; If the point is to get the value of x
> ;; and be able to refer it in body we could
> ;; write:
> `(flet ((get-the-x-in-foo-environment () x)
> ((setf get-the-x-in-foo-environment) (v) (setf x v)))
> ,@body)))
> (foo
> ;; the body:
> (let ((x 2))
> (print (get-the-x-in-foo-environment))
> (setf (get-the-x-in-foo-environment) 0))))
> x)
>
> prints: 1
> --> 0
>
>
>
>
> My argument is that writing:
>
> (let ((x 2))
> (foo))
>
> to get an X from an outer scope is wrong, that we should write:
>
> (with-outer-scope-x
> (let ((x 2))
> (outer-scope-x))) ; or something.
>
> and that Common Lisp makes you write the right thing.

I think I would just rename one of the conflicting variables. ;)

Pascal

--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rob Warnock on
Kazimir Majorinc <email(a)false.false> wrote:
+---------------
| Is anyone aware of "natural" occurences of the s-expressions similar to
| (let((x ...))
| ...
| (let((x ...))
| ...
| ...))
| in any Lisp dialect?
+---------------

Sure! I do it all the time, especially when "x" is spelled "tmp"! ;-}

Even worse, when hurriedly transliterating C to CL,
I often find myself doing this bit of ghastliness:

(let* ((tmp ...)
(tmp ...expression_using_tmp...)
(tmp ...another_expression_using_tmp...)
(tmp ...you_get_the_picture...)
...)
...)

(*blush*)


-Rob

-----
Rob Warnock <rpw3(a)rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607