(setf a 0) (incf a) (macroexpand-1 '(incf a)) (macroexpand-1 '(pop x)) (macroexpand-1 '(defstruct starship (name nil) (condition 'green))) (defmacro simple-incf (a) (list 'setq a (list '+ a 1))) (simple-incf a) ;;; difference with a function (defun faulty-incf (a) (setq a (+ a 1))) (faulty-incf a) ;; for function call 'a is being evaluated to 10, and bound to a local variable ;; then we change value of that local variable, but external is not affected ;; ;; in macros, symbol a is not evaluated, and inserted into a lisp expression, ;; that ultimately changes value of the correct variable ;;; backquote, allows for dequoting with , `(hello ,a world! quoted (+ 10 1 2) unquoted ,(+ 10 1 2)) ;; exercise (defmacro set-mutual (a b) `(progn (setq ,a ',b) (setq ,b ',a))) (set-mutual yo hei) yo hei (set-mutual val1 val2) (defun f (x y) (showvar x) (showvar y) (* x y)) (defmacro showvar (x) `(format t "~&Value of ~S is ~S" ',x ,x)) (showvar yo) (f 15 4) ;;; Splicing with backquote (setf name 'fred) (setf address '(16 maple drive)) `(,name lives in ,address now) ; inserting ;; => (FRED LIVES IN (16 MAPLE DRIVE) NOW) `(,name lives in ,@address now) ; splicing ;; => (FRED LIVES IN 16 MAPLE DRIVE NOW) ;; example of usage (defmacro set-zero (&rest variables) `(progn ,@(mapcar #'(lambda (var) (list 'setf var 0)) variables) '(zeroed ,@variables))) (set-zero a b c d) (defmacro variable-chain (&rest variables) `(progn ,@(mapcar #'(lambda (first second) `(setq ,first ',second)) variables (rest variables)))) ;; i even like my solution more thatn one in the book, with DO (variable-chain a b c d) (setf my-test-variables '(a b c d)) (mapcar (lambda (first second) (setf first second)) my-test-variables (rest my-test-variables)) ;;; Compilation '(you can use #'compile and #'compile-file) (defun tedious-sqrt (n) (dotimes (i n) (if (> (* i i) n) (return i)))) (tedious-sqrt 17) (time (tedious-sqrt 100000000000000000)) ;;; &body lambda list keyword (defmacro whille (test &body body) `(do () ((not ,test)) ,@body)) (defvar i) (setf i 0) (whille (> 5 i) (format t "~&calculating and mutating i = ~S" i) (incf i)) ;;; well, i had warning, but things actually worked. ;; some editors treat &body differently ;; by specializing formatting / identing ;; and also signals to programmers intend, that's it's a lisp expresison ;;; DESCTRUCTURING inputs to macro (defmacro mix-and-match-1 (pair1 pair2) (let ((x1 (first pair1)) (y1 (second pair1)) (x2 (first pair2)) (y2 (second pair2))) `(list '(,x1 ,y1) '(,x1 ,y2) '(,x2 ,y1) '(,x2 ,y2)))) (mix-and-match-1 (fred wilma) (tony bony)) ;; but, we coult treat arguments as lists where we define marco (defmacro mix-and-match-2 ((x1 y1) (x2 y2)) `(list '(,x1 ,y1) '(,x1 ,y2) '(,x2 ,y1) '(,x2 ,y2))) (mix-and-match-2 (fred wilma) (tony bony)) ;; and what would happen if it wasn't exact match with list of 2 elements? (mix-and-match-2 (fred wilma caddy) (tony bony)) ;; it fails with some check error ;;; example in the book about macro DOVECTOR ;;; So, what's that about Dynamic scoping & Lexical scoping? ;; wow, i think I understand ;; step 1: get two variables, one lexical - fished, one dynamic - birds (setf fishes '(salmon trout)) (defvar birds) (setf birds '(eagle parrot)) (defun show-fishes () fishes) (show-fishes) (defun show-birds () birds) (show-birds) (defun see-lexical-scoping (fishes) `(local ,fishes and from #'show-fishes - ,(show-fishes))) (see-lexical-soping '(kilka akula)) (defun see-dynamic-scoping (birds) `(local ,birds and from #'show-birds - ,(show-birds))) (see-dynamic-scoping '(sova dyatel)) ;; when I called #'show-birds from inside #'see-dynamic-scoping ;; it didn't go to the top level for value of 'birds ;; the value for 'birds was taken from previous "redefinition" ;; i.e any time we enter a funtion that defined dynamicly scoped variable ;; value of that variable, until we return from the funtion, is taken from it #'defvar ; when something could be assigned #'defparameter ; settings, not assigned, to change reeval defparameter #'defconstant ; should never change ;;; use for special variable *print-base* ; if we override it as parameter for our function ; then FORMAT would pick up that value (defun print-in-base (*print-base* x) (format t "~&I'm printing ~D as ~S in base ~D" x x *print-base*)) ;; if I use ~S to print *print-base*, then 2 in base 2 is 10, 12 in base 12 is 10. lol (print-in-base 10 65) (print-in-base 2 65) (print-in-base 3 65) (print-in-base 12 22) ;; dynamic variable accepts changes from called functions, while scope that ;; rebound it is alive can be used to communicate information between parts of ;; system. that's quite complicated