12
Метапрограммирование в CL "Lisp isn't a language, it's a building material." - Alan Kay Макросы Макросы чтения Макросы компилятора ...

CL metaprogramming

  • Upload
    dudarev

  • View
    911

  • Download
    0

Embed Size (px)

Citation preview

Page 1: CL metaprogramming

Метапрограммирование в CL

"Lisp isn't a language, it's a building material."- Alan Kay

● Макросы● Макросы чтения● Макросы компилятора● ...

Page 2: CL metaprogramming

Квазицитирование(defmacro nif (expr positive zero negative)

(let ((var (gensym)))`(let ((,var ,expr))

(cond((plusp ,var) ,positive)((zerop ,var) ,zero)(t ,negative)))))

(nif (- (* b b) (* 4 a c))210)

(LET ((#:G624 (- (* B B) (* 4 A C)))) (COND ((PLUSP #:G624) 2) ((ZEROP #:G624) 1) (T 0)))

Page 3: CL metaprogramming

Анафорические макросы(defmacro aif (condition then &optional else)

`(let ((it ,condition))(if it

,then,else)))

(aif (load-data))(pprint it)(print "No data loaded."))

awhen, awhile, aand, alambda...

(aand(load-data)(take-field it)(do-smth it))

Page 4: CL metaprogramming

Декораторы(defmacro defun/decorated ((&rest decorator) name (&rest params)

&body body)`(defun ,name (,@params)

(,@decorator(lambda () ,@body),@params)))

(defun decorator (x f &rest params)(format t "decorator ~A ~{~A ~}" x params)(funcall f))

(defun/decorated (decorator "smth")square (x)

(* x x))

Page 5: CL metaprogramming

Макросы пишут макросы: TCO(defun fact (n acc)

(if (zerop n)acc(fact (- n 1) (* n acc))))

(defmacro defun/tco (name (&rest params) &body body)`(defun ,name (,@params)

(macrolet ((,name (&rest args)`(progn

(psetq,@(mapcan (lambda (p v)

(list p v))',params args))

(go :label))))(tagbody

:label(return-from ,name (progn ,@body))))))

(defun/tco fact/tco (n acc)(if (zerop n)

acc(fact/tco (- n 1) (* n acc))))

Page 6: CL metaprogramming

EDSL

● CLOS (Common Lisp Object System)● ITERATE

(iter (for i from 1) (for a in some-list) (collect (cons i a)))

● ContextL (AOP)● Chtml-matcher

(<tbody nil (tr nil (<a ((name ?post-num))) (tr nil) (tr nil (?post-body <div ((id "post_message_?"))))))

Page 7: CL metaprogramming

Макросы чтения(set-dispatch-macro-character #\# #\$

#'(lambda (stream char arg)(parse-integer (coerce

(loopfor ch = (peek-char nil stream nil nil t)while (or (digit-char-p ch) (eql ch #\_))do (read-char stream t nil t)if (digit-char-p ch)

collect ch)'string))))

#$1_000_000

Page 8: CL metaprogramming

Макросы чтения(let ((foo 1)) #Uhttp://www.example.com/widget/{foo}/parts)

"http://www.example.com/widget/1/parts"

(uri-template-bind (#Uhttp://www.example.com/{part}/{number})"http://www.example.com/widget/1"

(list part (parse-integer number) %uri-host))

("widget" 1 "www.example.com")

Page 9: CL metaprogramming

Макросы чтения(set-dispatch-macro-character #\# #\/

(lambda (stream char arg)(let ((pattern (coerce

(loopfor ch = (read-char stream t nil t)until (eql ch #\/)collect ch)

'string)))`(lambda (&rest args)

(apply #'cl-ppcre:scan ,pattern args)))))

(#/[a-z]+/ str)

((lambda (&rest args)(apply #'cl-ppcre:scan "[a-z]+" args)) str)

(cl-ppcre:scan "[a-z]+" str)

Page 10: CL metaprogramming

Макросы компилятора(format stream control-string arg1...)

(funcall (formatter control-string) stream arg1 ...)

(lambda (stream &rest arguments)(apply #'format stream control-string arguments))

(formatter "Hello, ~A")

(LAMBDA (STREAM #:FORMAT-ARG633)(WRITE-STRING "Hello, " STREAM)(PRINC #:FORMAT-ARG633 STREAM))

(formatter "~{~A~%~}")

(LAMBDA (STREAM #:FORMAT-ARG636)(LET ((ARGS #:FORMAT-ARG636))

(LOOP(WHEN (NULL ARGS) (RETURN))(PRINC (POP ARGS) STREAM)

(TERPRI STREAM))))

Page 11: CL metaprogramming

Макросы компилятораCL-PPCRE

(define-compiler-macro scan (&whole form&environment envregex target-string&rest rest)

(cond((constantp regex env)

`(scan (load-time-value (create-scanner ,regex)) ,target-string ,@rest))(t form)))

Page 12: CL metaprogramming

Ссылки● Paul Graham «On Lisp» http://www.paulgraham.com/onlisp.html● Doug Hoyte «LOL» http://letoverlambda.com/● CL-PPCRE http://weitz.de/cl-ppcre/● Iterate http://common-lisp.net/project/iterate/● ContextL http://common-lisp.net/project/closer/contextl.html● chtml-matcher http://common-lisp.net/project/chtml-matcher/● uri-template http://common-lisp.net/project/uri-template/