Skip to content

Instantly share code, notes, and snippets.

@xuchunyang
Created March 25, 2015 09:52
Show Gist options
  • Save xuchunyang/57970843b4d4337c94e0 to your computer and use it in GitHub Desktop.
Save xuchunyang/57970843b4d4337c94e0 to your computer and use it in GitHub Desktop.
elisp-macro-demo.el
;;; Example 1
(defmacro inc (var)
(list 'setq var (list '1+ var)))
(macroexpand '(inc a))
==> (setq a (1+ a))
(defmacro inc2 (var1 var2)
(list 'progn (list 'inc var1) (list 'inc var2)))
(let ((a 1) (b 2))
(inc2 a b))
(macroexpand '(inc2 r s))
(progn (inc r) (inc s))
;;; Example 2
(defmacro multidefvar (&rest vars)
(let ((forms (mapcar (lambda (var) `(defvar ,var)) vars)))
`(progn ,@forms)))
(macroexpand '(multidefvar a b c d))
==> (progn (defvar a) (defvar b) (defvar c) (defvar d))
`(progn ,(list '1+ 2)
,(list '1- 23))
;;; Example 3
;;; (elisp) Argument Evaluation
(defmacro for2 (var from init to final do &rest body)
"Execute a simple for loop.
For example, (for i from 1 to 10 do (print i))."
(list 'let (list (list var init))
(cons 'while
(cons (list '<= var final)
(append body (list (list 'inc var)))))))
(for2 i from 1 to 3 do
(setq square (* i i))
(princ (format "\n%d %d" i square)))
1 1
2 4
3 9nil
(macroexpand '(for2 i from 1 to 3 do
(setq square (* i i))
(princ (format "\n%d %d" i square))))
==> (let ((i 1)) (while (<= i 3) (setq square (* i i)) (princ (format "
%d %d" i square)) (inc i)))
(defmacro for3 (var from init to final do &rest body)
"Execute a simple for loop.
For example, (for i from 1 to 10 do (print i))."
`(let ((,var ,init))
(while (<= ,var ,final)
,@body
(inc ,var))))
(for3 i from 1 to 3 do
(setq square (* i i))
(princ (format "\n%d %d" i square)))
1 1
2 4
3 9nil
(macroexpand '(for3 i from 1 to 3 do
(setq square (* i i))
(princ (format "\n%d %d" i square))))
===> (let ((i 1)) (while (<= i 3) (setq square (* i i)) (princ (format "
%d %d" i square)) (inc i)))
;;; Correctly expansion
(let ((i 1)
(max 3))
(while (<= i max)
(setq square (* i i))
(princ (format "\n%d %d" i square))
(inc i)))
1 1
2 4
3 9nil
(defmacro for4 (var from init to final do &rest body)
`(let ((,var ,init)
(max ,final))
(while (<= ,var max)
,@body
(inc ,var))))
;;; introduce a local variables
(defmacro for5 (var from init to final do &rest body)
(let ((tempvar (make-symbol "max")))
`(let ((,var ,init)
(,tempvar ,final))
(while (<= ,var ,tempvar)
,@body
(inc ,var)))))
(let ((max 0))
(for4 x from 0 to 3 do
(princ (format "\n[%d] %d %d" max x (* x x))))
(message "%d" max))
[3] 0 0
[3] 1 1
[3] 2 4
[3] 3 9"0"
(let ((max 0))
(for5 x from 0 to 3 do
(princ (format "\n[%d] %d %d" max x (* x x))))
(message "%d" max))
[0] 0 0
[0] 1 1
[0] 2 4
[0] 3 9"0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment