Page 1 of 1

protecting macro

Posted: Mon May 01, 2006 12:08 pm
by Dmi
Lutz,
Is it a good trick to define a macro as a context default function?
Seems that this can protect internal macro's symbols from interferring with ones that will be passed into macro:

Code: Select all

(context 'push-end)
(set 'push-end
  (lambda-macro (_l_push _lst_push)
    "(push-end item list) - push item to the end of the list"
    (eval (list 'push (quote (eval _l_push)) _lst_push -1))))
(context MAIN)
;===================
> (push-end (list 2 3) _lst_push)
(2 3)
> _lst_push 
((2 3))

Posted: Mon May 01, 2006 3:02 pm
by Lutz
Yes, that is also mentioned in the Manual. This ways there is also no need for name conventions like underscore _

Later yoday I will release development version 8.8.6 which has a new 'letex': a combination of 'let' and 'expand'. This together with define-macro will give you full macro power and using the default function mechanism macros are hygienic, and you have finer control with the possibility to do macro-expansion with 'letex' independent from a function definition.

Lutz

Posted: Mon May 01, 2006 3:10 pm
by rickyboy
Looks good to me -- the debugger indicates that this is safe enough:

Code: Select all

> (debug (push-end (list 2 3) _lst_push))

-----

(define-macro (push-end:push-end push-end:_l_push push-end:_lst_push)
  "(push-end item list) - push item to the end of the list" 
  #(eval (list 'push (quote (eval push-end:_l_push)) push-end:_lst_push 
    -1))#)


[-> 3 ] s|tep n|ext c|ont q|uit > push-end:_lst_push
MAIN:_lst_push
Thanks for the tip! --Ricky

Posted: Mon May 01, 2006 6:17 pm
by Dmi
Thanks, Lutz!
8.8.6 has a great improvements!

Posted: Wed May 03, 2006 1:49 pm
by rickyboy
Lutz wrote:Later yoday I will release development version 8.8.6 which has a new 'letex': a combination of 'let' and 'expand'. This together with define-macro will give you full macro power and using the default function mechanism macros are hygienic, and you have finer control with the possibility to do macro-expansion with 'letex' independent from a function definition.
I don't know know exactly what you mean here; however, be forewarned that, even with the use of 'letex', there is still the possibility that one's macro could suffer from variable capture. For instance:

Code: Select all

(define-macro (testie simble)
  (letex (x 42 y simble)
    (list x y)))

> (set 'x 1)
1
> (testie 1)
(42 1)
> (testie x)
(42 42)
However, in the following instance, if we follow the method of Dmi, 'x' will not get captured.

Code: Select all

(context 'testie2)
(define-macro (testie2:testie2 simble)
  (letex (x 42 y simble)
    (list x y)))
(context MAIN)

> (set 'x 1)
1
> (testie2 x)
(42 1)
> (testie2 1)
(42 1)
In the manual, 'letex' does not claim "hygenicity", so we are OK. I just didn't want anyone to have the wrong idea about 'letex'. (Hint: I did.) --Rick

Posted: Wed May 03, 2006 3:10 pm
by Lutz
That is correct, the hygiene of the macros is guaranteed vie the 'context' mechanism or when using 'args' for passing parameters. The 'letex' funtion in itself works just like any other lambda expression localizing variables in a dynamic scope which is not higienic.

Lutz