Created
March 25, 2015 09:52
-
-
Save xuchunyang/57970843b4d4337c94e0 to your computer and use it in GitHub Desktop.
elisp-macro-demo.el
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; 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