PageRenderTime 60ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/seminari/2015/Introduzione al LISP/1-macros.lisp

https://bitbucket.org/gulp_pisa/repo_gulp
Lisp | 181 lines | 73 code | 62 blank | 46 comment | 2 complexity | 0c08dff1a12e8e5e2ba64343e6915080 MD5 | raw file
  1. ;; esempio di DSL: cl-who, un linguaggio per generare HTML
  2. (ql:quickload :cl-who)
  3. (use-package :cl-who)
  4. ;; client http
  5. (ql:quickload "drakma")
  6. ;; server web - classico
  7. (ql:quickload "hunchentoot")
  8. ;; server web - nuovo
  9. ;; apt-get install libev4 libuv0.10
  10. (ql:quickload "woo")
  11. (with-html-output (o *standard-output* :indent t)
  12. (:html
  13. (:head
  14. (:title "Google"))
  15. (:body
  16. (loop repeat 3 do
  17. (htm
  18. (:a :href "http://www.google.com/"
  19. "Google"))))))
  20. (print
  21. (with-html-output-to-string (o)
  22. (:table
  23. (:tr
  24. (:td (esc "Hello, World! <>"))))))
  25. ;; come si creano i DSL? estendendo il linguaggio
  26. ;; come si estende il linguaggio? con le macro
  27. ;; cosa sono le macro? funzioni invocate durante la compilazione,
  28. ;; che scrivono codice
  29. ;; come si rappresenta il codice Lisp? con una lista
  30. ;; le macro di solito manipolano liste
  31. (+ 1 2)
  32. '(+ 1 2)
  33. (list '+ 1 2)
  34. ;; altro uso dei symbol: nelle liste che contengono codice
  35. (list 'square 7)
  36. '(square 7)
  37. '(+ x y))
  38. (list '+ 'x 'y))
  39. ;; proviamo a leggere un file Lisp come lista!
  40. (defparameter *path* "/home/max/common-lisp/lisp-intro/0-hello-world.lisp")
  41. (defparameter *in* (open *path*))
  42. ;; ripetere...
  43. (read *in*)
  44. (loop while (print (read *in* nil)))
  45. (close *in*)
  46. ;; la lista vuota e' NIL, la stessa costante che significa anche FALSO.
  47. (list)
  48. ;; eval non e' quasi mai necessario...
  49. ;; ma e' utile per provare a manipolare il codice Lisp
  50. ;; sotto forma di lista
  51. (eval '(+ 1 2))
  52. (eval '(square 7))
  53. ;; le funzioni e macro per manipolare le liste sono oltre un centinaio
  54. (defvar *l* (list 4 5 6))
  55. (first *l*)
  56. (rest *l*)
  57. (setf (first *l*) -4)
  58. (setf (second *l*) -5)
  59. ;; car = first
  60. ;; cdr = rest
  61. *l*
  62. (push 3 *l*) ;; (setf *l* (append '(3) *l*))
  63. (pop *l*)
  64. (defun symbolic-add (x y)
  65. (list '+ x y))
  66. (defun symbolic-add (x y)
  67. ;; sbagliato...
  68. '(+ x y))
  69. (defun symbolic-add (x y)
  70. ;; corretto. quasiquote
  71. `(+ ,x ,y))
  72. ;; le macro sono funzioni
  73. ;; da eseguire durante la compilazione
  74. (defmacro add (x y)
  75. `(+ ,x ,y))
  76. (add 2 3)
  77. (macroexpand '(add 2 3))
  78. (defmacro add (&rest args)
  79. `(+ ,@args))
  80. ;; usi possibili delle macro? illimitati... alcuni esempi:
  81. ;; acquisizione e rilascio di risorse (with-*)
  82. ;; loop-unrolling
  83. ;; specializzazione di funzioni
  84. ;; linguaggi specifici per generare HTML, XML, JSON, Javascript...
  85. ;; si parte dal codice che vogliamo generare: prima versione
  86. (let ((f (open *path*)))
  87. (read f)
  88. (close f))
  89. ;; seconda versione
  90. (let ((f (open *path*)))
  91. (unwind-protect ;; equivalente al try-finally di altri linguaggi
  92. (read f)
  93. (close f)))
  94. ;; e si trasforma in una macro
  95. (defmacro with-open-file% ((f filename &rest options) &body body)
  96. `(let ((,f (open ,filename ,@options)))
  97. (unwind-protect
  98. (progn ,@body)
  99. (close ,f))))
  100. (macroexpand
  101. '(with-open-file% (in *path*)
  102. (read in)))
  103. (with-open-file% (in *path*)
  104. (loop while (print (read in nil))))
  105. ;; with-pooled-db-connection
  106. ;; with-http-connection
  107. ;; with-lock
  108. ;; altri esempi?
  109. ;; attenzione a non cadere nell'approccio
  110. ;; "soluzione in cerca di un problema"
  111. ;; la domanda da farsi non e' "per cosa posso usare le macro?"
  112. ;; ma e' "ho questo problema, le macro possono aiutarmi?"
  113. (macroexpand '(and a b c))
  114. (macroexpand '(or a b c))
  115. ;; esempio: implementare AVERAGE
  116. ;; esempio: implementare AND e OR di due argomenti.
  117. ;; AND e' facile. Invece OR ha un problema: non e' igienico, serve (gensym)
  118. ;; esempio: implementare AND e OR di n argomenti
  119. ;; soluzioni degli esempi in 2-macros.lisp