It evaluates
Start with something that cannot be mistaken for a trick.
(+ 1 2)
Definitions stick around. Every block on this page shares one image, so anything you define here is available further down.
(defun square (x) (* x x)) (square 12)
It really is Common Lisp
format is a language of its own. Here it spells a number out and
makes the noun agree with it — ~r and ~:p doing the work,
not the surrounding code.
(format nil "~r file~:p, ~r director~:@p" 3 1)
loop is another. This is one form.
(loop for i from 1 to 20
when (zerop (mod i 15)) collect i into fizzbuzz
else when (evenp i) sum i into evens
finally (return (list :multiples-of-15 fizzbuzz :sum-of-evens evens)))
Objects, and methods that do not belong to them
A method is not owned by a class. It is chosen by all of its arguments at once, which is why this works without either class knowing about the other.
(defclass square-m () ((side :initarg :side :reader side)))
(defclass circle () ((radius :initarg :radius :reader radius)))
(defgeneric fits-in-p (inner outer))
(defmethod fits-in-p ((inner square-m) (outer circle))
(<= (* (side inner) (sqrt 2)) (* 2 (radius outer))))
(defmethod fits-in-p ((inner circle) (outer square-m))
(<= (* 2 (radius inner)) (side outer)))
(list (fits-in-p (make-instance 'square-m :side 1) (make-instance 'circle :radius 1))
(fits-in-p (make-instance 'circle :radius 1) (make-instance 'square-m :side 1)))
Errors are not the end of the story
Signalling an error does not immediately unwind. The code that raised the problem can offer ways out, and the code that catches it picks one — while everything in between is still standing.
(defun parse-quantity (text)
(restart-case (or (parse-integer text :junk-allowed t)
(error "~s is not a number" text))
(use-value (v) :report "Supply a value to use instead." v)
(treat-as-zero () :report "Pretend it said zero." 0)))
(handler-bind ((error (lambda (c)
(declare (ignore c))
(invoke-restart 'treat-as-zero))))
(list (parse-quantity "17")
(parse-quantity "oops")))
Run this next one and look under the message: the error arrives carrying a list of the restarts that were available. That list is what a Lisp debugger shows you.
(parse-quantity "not a number at all")
The language is not finished
Macros run at compile time and write code. Here is one that adds a construct the standard does not have.
(defmacro while (test &body body)
`(loop (unless ,test (return)) ,@body))
(let ((n 1) (steps '()))
(while (< n 40)
(push n steps)
(setf n (* n 3)))
(nreverse steps))
And you can look at what it wrote.
(macroexpand-1 '(while (< n 40) (print n)))
Your turn
Empty. Type anything; Copy link turns whatever is in the box into a URL you can send to someone.
;; Anything you like. Ctrl+Enter runs it too.
(list (lisp-implementation-type)
(lisp-implementation-version)
(loop for s being the external-symbols of (find-package :cl) count 1))