newLISP Fan Club

Forum => Anything else we might add? => Topic started by: Dmi on May 01, 2006, 05:08:24 AM

Title: protecting macro
Post by: Dmi on May 01, 2006, 05:08:24 AM
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:
(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))
Title:
Post by: Lutz on May 01, 2006, 08:02:28 AM
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
Title:
Post by: rickyboy on May 01, 2006, 08:10:54 AM
Looks good to me -- the debugger indicates that this is safe enough:
> (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
Title:
Post by: Dmi on May 01, 2006, 11:17:40 AM
Thanks, Lutz!

8.8.6 has a great improvements!
Title:
Post by: rickyboy on May 03, 2006, 06:49:06 AM
Quote from: "Lutz"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:


(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.


(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
Title:
Post by: Lutz on May 03, 2006, 08:10:50 AM
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