Skip to content

Instantly share code, notes, and snippets.

@ltbringer
Last active April 14, 2019 20:48
Show Gist options
  • Save ltbringer/b59cf491ce80a9fc6fe0e2aaaf07c7fa to your computer and use it in GitHub Desktop.
Save ltbringer/b59cf491ce80a9fc6fe0e2aaaf07c7fa to your computer and use it in GitHub Desktop.
Common Lisp: Easy macro introduction
;; =============================================================
;; A file simulator is used to create an example problem
;; that helps demonstrate the use of macros in common lisp
;; =============================================================
;; Interfaces to file I/Os expose methods like
;; `open`, `close`, `read`
;; not closing a file can lead to issues where the machine runs
;; out of memory, or unreliable state of the file
;; (due to unwanted side-effects)
;;
;; ------------------------------------
;; try {
;; file = File("/path/to/file").open()
;; data = file.read()
;; } catch (...) {
;; ...
;; } finally {
;; file.close()
;; }
;; ------------------------------------
;;
;; The above pseudo-code is therefore a common pattern,
;; luckily languages provide syntactic sugar for the same
;; for example, Python's `with`
;;
;; ------------------------------------
;; with open("path/to/file", "mode") as f:
;; data = f.read()
;; ------------------------------------
;;
;; A clearer syntax which even closes the file for us
;; Let's imagine that such syntax is not available in clisp
;; and create the same using clisp macros
(defclass file-sim ()
;; -bytes: An array of bits in the file
;; -state: "open" if the file can be read / "closed" if the file is closed
((bytes
:initarg :bytes)
(state
:initarg :state)))
(defmethod open-file ((file file-sim))
;; method to change the state of the file
(print "open")
(setf (slot-value file 'state) "open"))
(defmethod read-file ((file file-sim))
;; method to read the bytes in the file
(cond
;; Check the state of the file
((equal (slot-value file 'state) "open") (print (slot-value file 'bytes)))
((equal (slot-value file 'state) "closed") "Use the open-file method on the file before reading")))
(defmethod close-file ((file file-sim))
;; method to change the state of the file to "closed"
(print "closed")
(setf (slot-value file 'state) "closed"))
;; =============================================================
;; To do the same using a function we would write something like
;; ------------------------------------
;; (defun (file)
;; (progn
;; (open-file file)
;; (read-file file)
;; (close-file file)))
;; ------------------------------------
;; To create a macro that outputs this particular function's
;; code, we can use the (`)[backticks] to create the
;; template and fill in the variables using (,)[comma]
;; @body allows us to add in any method other than `read-file`
;; =============================================================
(defmacro with (file &body body)
`(progn
(open-file ,file)
,@body
(close-file ,file)))
;; =============================================================
;; Now we can use this macro like:
;; ------------------------------------
;; (with *test-file*
;; (read-file *test-file*))
;; ------------------------------------
;; =============================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment