Get started Macros
Create a file named hello.lfe and type in:
(defmodule hello (import (from io (format 1)(format 2))) (export (start 0))) (defun start () (macrolet ((f (args `(format ,@args)))) (format '"Hello World~n") (f '"Hello Macro~n")))
$ erl -noshell -noinput -s lfe_boot start -pa ~/lfe/ebin Erlang R13B01 (erts-5.7.2) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false] LFE Shell V5.7.2 (abort with ^G) > (slurp '"hello.lfe") #(ok hello) > (: hello start) Hello World Hello Macro ok > (halt)
There are two ways to debug macros in the current system.
The first is to use the to_exp
option when compiling. This generates a source file with all macros expanded, just as it is passed into the compiler proper. So calling (c '"foo.lfe" '(to_exp))
will generate a file foo.expand with the expanded forms. This is a very heavy blunt instrument with very little control but it does show what the macros expand into.
The second is too use the macroexpand-1
, macroexpand
and macroexpand-all
builtin shell functions (see lfe_shell.txt). You first slurp in the file containing the macros and then explicitly expand expressions using the macros. This gives better control but can be a bit tedious.
As far as I know these are the only ways of debugging macros, but someone else may have arrived at a better solution. :-)
One strategy is to always aim for the simplest macro that will work.
(defmacro add100 (x) 100)
(defun start () (: lfe_io format '"~p~n" (list (add100 (+ 1 2)))) 100
(defmacro add100 (x) `(100 + ,x)) ; FAIL!
(defmacro add100 (x) `'(100 + ,x))
It will stop the evaluation at the quote, printing out:
(100 + (+ 1 2))
It should be (+ 100 (+ 1 2))
so I change the macro and remove the quote.
(defmacro add100 (x) `(+ 100 ,x)) 103
Success!
(defmodule codewalk (export (start 0))) (eval-when-compile (defun replace ((_ _ '()) '()) ((from to (head . tail)) (when (is_list head)) (cons (replace from to head) (replace from to tail))) ((from to (head . tail)) (cons (if (== head from) to head) (replace from to tail))))) ; Walks the syntax tree, replacing "self" with the function name. (defmacro adefun ((fn . (args . es)) (let ((new_es (replace 'self fn es))) `(defun ,fn ,args ,@new_es)))) ; A function that call it self without using its function name. (adefun countdown (x) (if (== x 0) '() (cons x (self (- x 1))))) ;> (countdown 10) ;(10 9 8 7 6 5 4 3 2 1)
Codewalking change the syntax tree.
Ref: http://www.catonmat.net/blog/derivation-of-ycombinator/
(defun y (le) (apply (lambda (f) (apply f (list f))) (list (lambda (f) (apply le (list (lambda (x) (apply (apply f (list f)) (list x))))))))) ; Calculate the length of a list. (apply (apply (fun y 1) (list (lambda (len) (lambda (li) (if (== li '()) 0 (+ 1 (apply len (list (tl li))))))))) (list '(a b c d))) ; 4
A Y combinator let anonymous function call itself. With the help of an argument, which is itself.