Page 1 of 1

On Macros

Posted: Sat Apr 21, 2012 8:28 pm
by PapoAnaya
One post in comp.lang.lisp stated that "thou shall know macros to get thy mastery of ye LISP arcana", hence decided to explore macros for fun and amusement. Sadly here in the forum if you do a search on macro (or define macros) nothing shows up, hence decided to write a small post about macros.

(define-macro ) in newlisp creates functions in which the arguments are not evaluated. In lay person terms, f you have a variable x with a value of 10, and x is being passed to a macro, then "x" is the value that is obtained from the argument and not 10. You can look for fexpr in your favorite search engine for the details on implementation and how it differs from macro in common lisp. More details can also be found in the newlisp manual.

Well, this sounds nice and dandy, but what can you do with such thing.

I'm placing two examples of macros that come directly from the gnulisp manual. Only that they are implemented in newlisp (obviously :) ) It really does not have a lot of changes from the examples as written in the text.

The first one is an implementation of the "inc" function using macros:

Code: Select all

(define-macro (my-inc var)
  (eval (list 'setq var (list '+ 1 var) ))

(while (< i 10)
       (println (my-inc i))
The following must be noted:
  • The macro is building code that will be evaluated. In this case, it is building
    a list containing (setq i (+ 1 i))
  • For the macro to execute, the created expression must be evaluated. If you
    substitute eval with println, you'll see aforementioned code. This is handy to
    debug macros. An alternative of execution is to return the resultant list and
    modify it, but in this case, I wanted it only to execute; printing the numbers from 1 to 10.
The second example is a version of the for loop with syntactic sugar.

Code: Select all

(define-macro (mi-for var from init to final do body)
  (list 'let (list (list var init))
        (cons 'while (cons (list '<= var final)
                           (append (list body) (list (list 'inc var))))))) )

(mi-for i from 1 to 10 do
     (let ()
       (println i) )

  • As you can see, it's another variation of the same theme. In this case
    it is building a while loop that will execute 10 times the content of the
  • Being that the body is only one argument, it needs to be surrounded with a let
    function for all the statements to run.
  • Eval is used to execute the code within the macro, but if substituting the eval with a println, this is what is obtained.

Code: Select all

(let ((i 1)) 
 (while (<= i 10) 
  (let () 
   (println i)) 
  (inc i)))
This means that code can be built in a macro, returned from it and
executed later on in your code.

Hopefully this will help to those that are trying to understand these and hopefully find these examples useful.