From: Pascal J. Bourguignon on 26 Mar 2010 18:24 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 26 Mar 2010 19:18 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 29 Mar 2010 16:01 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 30 Mar 2010 07:32 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 30 Mar 2010 21:16
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 |