Back Original

Hyperpolyglot Lisp: Common Lisp, Racket, Clojure, Emacs Lisp

ca side-by-side reference sheet

grammar and execution | variables and expressions | arithmetic and logic | strings | regular expressions | dates and time | lists | fixed-length arrays | dictionaries | user-defined types | functions | execution control | exceptions | streams | emacs buffers | files | directories | processes and environment | libraries and namespaces | objects | lisp macros | reflection | java interop

common lisp racket clojure emacs lisp
version used SBCL 1.2 Racket 6.1 Clojure 1.6 Emacs 24.5
show version $ sbcl --version $ racket --version displayed by repl on startup $ emacs --version
grammar and execution
common lisp racket clojure emacs lisp
compiler $ raco make module.rkt M-x byte-compile-file
standalone executable (sb-ext:save-lisp-and-die $ mzc —exe executable file
interpreter $ sbcl --script foo.lisp $ racket -r foo.racket specify full path to clojure jar:
shebang #!/usr/bin/env sbcl --script #!/usr/bin/env racket --script specify full path to clojure jar: #!/usr/bin/env emacs --script
repl $ sbcl $ racket $ java -jar /PATH/TO/clojure.jar M-x ielm
command line program $ racket -e '(+ 1 1)'
word separator whitespace whitespace whitespace and commas whitespace
end-of-line comment (+ 1 1) ; adding (+ 1 1) ; adding (+ 1 1) ; adding (+ 1 1) ; adding
multiple line comment (+ 1 #| adding |# 1) (+ 1 #| adding |# 1)
variables and expressions
common lisp racket clojure emacs lisp
identifier case insensitive, cannot start with digit case sensitive, cannot start with digit case sensitive, cannot start with digit case sensitive, cannot start with digit
quoted identifier (setq |white space symbol| 3) (define |white space symbol| 3) none none
local variable ; parallel assignment: ; parallel assignment: (let [x 3 y 4] ; parallel assignment:
global variable (defparameter *x* 3) (define x 3) (def x 3) (set 'x 3)
remove variable (makunbound 'x) (namespace-undefine-variable! 'x) (ns-unmap *ns* 'x) (makunbound 'x)
null nil '() null '() ; same value as null in Java: nil '()
null test (null x) (null? x) (nil? x) (null x)
identifier as value 'x 'x 'x 'x
identifier test (symbolp 'x) (symbol? 'x) (symbol? 'x) (symbolp 'x)
identifier equality test (eq 'x 'x) (eq? 'x 'x) (= 'x 'x) (eq 'x 'x)
non-referential identifier :foo #:foo :foo :foo
identifier attributes (set 'x 13) none ; value must be instance of clojure.lang.IObj: (set 'x 13)
arithmetic and logic
common lisp racket clojure emacs lisp
true and false t nil #t #f true false t nil
falsehoods nil () #f false false nil nil ()
logical operators (or (not t) (and t nil)) (or (not #t) (and #t #f)) (or (not true) (and true false)) (or (not t) (and t nil))
relational operators = /= < > <= >= = none < > <= >= = not= < > <= >= = /= < > <= >=
min and max (min 1 2 3) (min 1 2 3) (min 1 2 3) (min 1 2 3)
numeric predicates numberp integerp number? integer? number? integer? numberp integerp
arithmetic operators + - * / mod + - * / modulo + - * / mod + - * / %
integer division (truncate 7 3) (quotient 7 3) (quot 7 3) (/ 7 3)
integer division by zero division-by-zero error division by zero error arith-error
float division rational: rational: rational: integer quotient:
float division by zero division-by-zero error -1.0e+INF, -0.0e+NaN, or 1.0e+INF
power (expt 2 32) (expt 2 32) returns float: (expt 2 32)
sqrt (sqrt 2) (sqrt 2) (Math/sqrt 2) (sqrt 2)
sqrt -1 #c(0.0 1.0) 0+1i (Math/sqrt -1): NaN -0.0e+NaN
transcendental functions exp log sin cos tan asin acos atan atan exp log sin cos tan asin acos atan atan Math/exp Math/log Math/sin Math/cos Math/tan Math/asin Math/acos Math/atan Math/atan2 exp log sin cos tan asin acos atan atan
float truncation return two values, first is integer: return floats: return integers: truncate round ceiling floor
absolute value abs signum abs Math/abs Math/signum abs signum
integer overflow none; arbitrary-precision integers none; arbitrary-precision integers clojure.lang.Numbers.throwIntOverflow exception
float overflow floating-point-overflow error not literals:
rational construction (/ 3 7) (/ 3 7) (/ 3 7)
rational decomposition (numerator 3/7) (numerator 3/7) (numerator 3/7) none none
complex construction #c(1 2) 1+2i none none
complex decomposition (realpart #c(1 2)) (real-part 1+2i) none none none
random number (random 100) (random 100) (def rnd (java.util.Random.)) (random 100)
random seed (setq *random-state* (random-seed 17)
bit operators ash left shift when 2nd argument positive logand logior logxor lognot arithmetic-shift left shift when 2nd argument positive bitwise-and bitwise-ior bitwise-xor bitwise-not bit-shift-left bit-shift-right bit-and bit-or bit-xor bit-not lsh left shift when 2nd argument positive logand logior logxor lognot
binary, octal, and hex literals #b101010 #b101010
radix (format nil "~7r" 42)
strings
common lisp racket clojure emacs lisp
string test (stringp "foo") (string? "foo") (string? "foo") (stringp "foo")
string literal "foo bar" "foo bar" "foo bar" "foo bar"
newline in literal yes yes yes yes
literal escapes \" \\ \t \n \r \" \\ \ooo \uhhhh \b \t \n \f \r \" \\ \ooo \uhhhh \b \t \n \f \r \" \\ \ooo \uhhhh \xh - \xhhhhhh \C-x \M-x
constructor (string #\f #\o #\o) (string ?f ?o ?o)
format string (format nil "~a: ~a ~,2f" "Foo" 7 13.457) (format "~a ~a ~a" "Foo" 7 13.457) (String/format "%s: %d %.2f" (format "%s: %d %.2f" "Foo" 7 13.457)
format specifiers ~a    any type, human readable ~a    any type, human readable
compare strings (string= "foo" "bar") (string=? "foo" "bar") (.equals "foo" "bar") (string= "foo" "bar")
concatenate (concatenate 'string "foo " "bar " "bar") (string-append "foo " "bar " "baz") (str "foo " "bar " "baz") (concat "foo " "bar " "baz")
replicate make-string 3 :initial-element #\f) (make-string 3 #\f) (String. (into-array (make-string 3 ?f)
translate case (string-downcase "FOO") (string-downcase "FOO") (.toLowerCase "FOO") (downcase "FOO")
capitalize ; "Foo Bar": ; "Foo Bar":
trim (string-trim (require srfi/13/string) (.trim " foo ") none; see notes for an implementation
pad (format nil "~10a" "foo")
number to string (concatenate 'string (string-append (str "Value: " 8) (concat
string to number (+ 7 (parse-integer "12")) (+ 7 (string->number "12")) (+ 7 (Integer/parseInt "12")) (+ 7 (string-to-number "12"))
split (cl-ppcre:split (regexp-split #rx"[ \n\t]+" (seq (split-string "foo bar baz")
string join (reduce (string-join (reduce #(str %1 " " %2) (reduce
length (length "foo") (string-length "foo") (.length "foo") (length "foo")
index of substring (search "bar" "foo bar") racket: (.indexOf "foo bar" "bar") (search "bar" "foo bar")
extract substring (subseq "foo bar" 4 7) (substring "foo bar" 4 7) (.substring "foo bar" 4 7) (substring "foo bar" 4 7)
character literal #\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\rubout #\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\nul #\vtab #\alarm #\esc #\delete \a \newline \space \backspace \tab ? \formfeed \return ? ?a ?\b ?\t ?\n ?\f ?\r ?\" ?\\ ?\ooo ?\uhhhh ?\xh - ?\xhhhhhh ?\C-x ?\M-x
test characters (characterp #\x) (char? #\x) (char? \x) (characterp ?x)
chr and ord (code-char 97) (integer->char 97) (char 97)
to array of characters ; list:
character lookup (char "foo" 0) (string-ref "foo" 0) (.charAt "foo" 0) (aref "foo" 0)
regular expressions
common lisp racket clojure emacs lisp
literal use a string: posix extended: #"\b\d{5}\b"
character class abbrevations . \d \D \s \S \w \W regexp: . \d \D \s \S \w \W . \w \W \ca \cl \cg \Ca \Cl \Cg \sx
anchors ^ $ \b \B regexp: ^ $ \A \b \B \G \z \Z ^ $ \b \B
match test (ql:quickload "cl-ppcre") (regexp-match #rx"bar" "foo bar") (re-find #"bar" "foo bar") (string-match "bar" "foo bar")
case insensitive match test (regexp-match #px"(?i:lorem)" "Lorem") (re-find #"(?i:lorem)" "Lorem")
substitution (cl-ppcre:regex-replace "[^l]l" (regexp-replace #rx"el" (.replaceFirst "hello" "[^l]l" "XX") ?
group capture (match (regexp-match (let [[_ yr mn dy]
scan (re-seq #"\w+" "dolor sit amet")
backreference in match and substitution (regexp-match #px"(\\w+) \\1" "do do")
dates and time
common lisp racket clojure emacs lisp
broken-down datetime type No dedicated type; a list of 9 values is used:
current datetime (get-decoded-time) (require racket/date) (def dt (new java.util.Date)) (current-time)
current unix epoch gray|; seconds since Jan 1, 1900:## (current-seconds) (/ (System/currentTimeMillis) 1000.0) (float-time)
unix epoch to broken-down datetime (decode-universal-time (seconds->date (current-seconds)) (def dt (new java.util.Date (seconds-to-time (float-time))
broken-down datetime to unix epoch (encode-universal-time 0 22 10 31 5 2015) (require racket/date) (/ (.getTime (new java.util.Date)) 1000.0) (multiple-value-bind (b s)
format datetime (def s "yyyy-MM-dd HH:mm:ss") (format-time-string
parse datetime (require (prefix-in s19. srfi/19)) (def s "yyyy-MM-dd HH:mm:ss")
date parts (multiple-value-bind (date-year (current-date)) (def cal (new java.util.GregorianCalendar)) (multiple-value-bind
time parts (multiple-value-bind (date-hour (current-date)) (def cal (new java.util.GregorianCalendar)) (multiple-value-bind
build broken-down datetime (encode-universal-time 0 22 10 31 5 2015) (let (encode-time 0 50 8 31 5 2015)
lists
common lisp racket clojure emacs lisp
literal '(1 2 3) '(1 2 3) '(1 2 3) '(1 2 3)
constructor (list 1 2 3) (list 1 2 3) (list 1 2 3) (list 1 2 3)
predicate (listp '(1 2 3)) (list? '(1 2 3)) (list? '(1 2 3)) (listp '(1 2 3))
empty test nil and '() are synonyms and evaluate as false in a boolean context. All other values are true. (empty? '()) (empty? ()) nil and '() are synonyms and evaluate as false in a boolean context. All other values are true.
evaluating the empty list nil error () nil
cons (cons 1 '(2 3)) (cons 1 '(2 3)) (cons 1 '(2 3)) (cons 1 '(2 3))
head (car '(1 2 3)) (car '(1 2 3)) first car
tail (cdr '(1 2 3)) (cdr '(1 2 3)) (rest '(1 2 3)) (cdr '(1 2 3))
head and tail of empty list both evaluate to nil error () both evaluate to nil
length (length '(1 2 3)) (length '(1 2 3)) (count '(1 2 3)) (length '(1 2 3))
equality test (equal '(1 2 3) '(1 2 3)) (equal? '(1 2 3) '(1 2 3)) (= '(1 2 3) '(1 2 3)) (equal '(1 2 3) '(1 2 3))
nth element ; indexed from zero: (list-ref '(1 2 3 4) 2) (nth '(1 2 3 4) 2) (nth 2 '(1 2 3 4))
out-of-bounds behavior nil error raises IndexOutOfBoundsException nil
element index (position 7 '(5 6 7 8)) (require srfi/1) none (position 7 '(5 6 7 8))
concatenate (append '(1 2 3) '(4 5 6)) (append '(1 2 3) '(4 5 6)) (concat '(1 2 3) '(4 5 6)) (append '(1 2 3) '(4 5 6))
take none (take '(1 2 3 4) 2) (take 2 '(1 2 3 4)) (subseq '(1 2 3 4) 0 2)
drop (nthcdr 2 '(1 2 3 4)) (drop '(1 2 3 4) 2) (drop 2 '(1 2 3 4)) (nthcdr 2 '(1 2 3 4))
last element (car (last '(1 2 3))) (last '(1 2 3)) (last '(1 2 3)) (car (last '(1 2 3)))
all but last element (butlast '(1 2 3)) (define a '(1 2 3)) (butlast '(1 2 3)) (butlast '(1 2 3))
reverse (reverse '(1 2 3)) (reverse '(1 2 3)) (reverse '(1 2 3)) (reverse '(1 2 3))
sort (sort '(3 2 4 1) '<) (sort '(3 2 4 1) <) (sort < '(3 2 4 1)) (sort '(3 2 4 1) '<)
dedupe (remove-duplicates '(1 1 2 3)) (remove-duplicates '(1 1 2 3)) (remove-duplicates '(1 1 2 3))
membership (member 7 '(1 2 3)) (member 7 '(1 2 3)) (member 7 '(1 2 3)
map (mapcar (map (lambda (x) (* x x)) '(1 2 3)) (map #(* % %) '(1 2 3)) (mapcar
filter (remove-if-not (filter (filter #(> % 2) '(1 2 3)) (remove-if-not
reduce (reduce '- (foldl (lambda (x y) (- y x)) 0 '(1 2 3 4)) (reduce - 0 '(1 2 3 4)) (reduce '-
right fold (reduce '- (foldr - 0 '(1 2 3 4)) none (reduce '-
iterate (dolist (x '(1 2 3)) (for ((x '(1 2 3))) (doseq [x '(1 2 3)] (dolist (x '(1 2 3))
universal predicate (every (for/and ((i '(1 2 3 4))) (every? #(= 0 (rem % 2)) '(1 2 3 4)) (every
existential predicate (some (for/or ((i '(1 2 3 4))) (some #(= 0 (rem % 2)) '(1 2 3 4)) (some
list comprehension (for*/list (for
shuffle (shuffle '(1 2 3 4)) (shuffle '(1 2 3 4))
set head (defparameter *a* '(1 2 3)) (require schema/mpair) none (setq a '(1 2 3)
set tail (defparameter *a* '(1 2 3)) (require schema/mpair) none (setq a '(1 2 3)
manipulate back (defparameter *a* '(1 2 3)) none (setq a '(1 2 3))
flatten (flatten '(1 2 (3 (4)))) (flatten '(1 2 (3 (4))))
associative array lookup (assoc 3 '((1 2) (3 4))) (assoc 3 '((1 2) (3 4))) none, see note (assoc 3 '((1 2) (3 4)))
flat associative array lookup (getf '(1 2 3 4) 3) none none (getf '(1 2 3 4) 3)
pair literal '(1 . 2) '(1 . 2) none '(1 . 2)
cons cell test (cons '(1 . 2)) (cons? '(1 . 2)) none (cons '(1 . 2))
translate elements recursively (sublis '((1 . 2) (3 . 4)) (sublis '((1 . 2) (3 . 4))
fixed-length arrays
common lisp racket clojure emacs lisp
literal #(1 2 3) #(1 2 3) [1 2 3] [1 2 3]
constructor (vector 1 2 3) (vector 1 2 3) (vector 1 2 3) (vector 1 2 3)
size (length #(1 2 3)) (vector-length #(1 2 3)) (count [1 2 3]) (length [1 2 3])
lookup (elt #(1 2 3) 0) or (vector-ref #(1 2 3) 0) (nth [1 2 3] 0) (elt [1 2 3] 0)
update (setq v [1 2 3]) (define v (vector 1 2 3)) (replace {2 4} [1 2 3]) (setq v #(1 2 3))
out-of-bounds behavior raises sb-kernel:index-too-large-error error
array to list (coerce #(1 2 3) 'list) (vector->list #(1 2 3)) (seq [1 2 3]) (coerce [1 2 3] 'list)
list to array (coerce '(1 2 3) 'vector) (list->vector '(1 2 3)) (vec '(1 2 3)) (coerce '(1 2 3) 'vector)
reverse (reverse #(1 2 3))
sort (sort #(2 4 1 3) #'<)
map (map 'vector (lambda (x) (* x x)) #(1 2 3))
filter (remove-if-not (lambda (x) (> x 2)) #(1 2 3))
reduce
dictionaries
common lisp racket clojure emacs lisp
literal none ; immutable: ; clojure.lang.PersistentArrayMap: none
constructor (defparameter *h* (make-hash-table :test 'equal)) (define ih ; immutable: (setq h (make-hash-table :test 'equal))
predicate (hash-table-p *h*) (hash? h) (map? ih) (hash-table-p h)
size (hash-table-count *h*) (hash-count h) (count ih) (hash-table-count h)
lookup (gethash "t" *h*) (hash-ref h "t") (get ih "t") (gethash "t" h)
update (setf (gethash "t" *h*) 1) (hash-set! h "t" 2) (def ih2 (assoc ih "t" 2)) (puthash "t" 1 h)
missing key behavior returns nil error returns nil returns nil
is key present (nth-value 1 (gethash "t" *h*)) (hash-has-key? h "t") (contains? ih "t") none
delete (remhash "t" *h*) (hash-remove! h "t") (def ih2 (dissoc ih "t")) (remhash "hello" h)
merge ; values in ih2 take precedence:
invert (require 'clojure.set)
iterate (maphash (hash-for-each h (doseq [p ih] (maphash
keys and values as lists none (hash-keys h) (def hkeys (map (fn [p] (first p)) ih)) none
user-defined types
common lisp racket clojure emacs lisp
defstruct (defstruct account id balance) (define-struct account (id (balance #:mutable))) (defstruct account :id :balance) (defstruct account id balance)
struct (setq a (define a (make-account 3 17.12)) (def a (struct account 3 17.12)) (setq a
struct getter (account-id a) (account-id a) (:id a) (account-id a)
struct setter (setf (account-balance a) 0) (set-account-balance! a 0) none (setf (account-balance a) 0)
struct predicate (account-p a) (account? a) none (account-p a)
functions
common lisp racket clojure emacs lisp
define function (defun add (x y) (+ x y)) (define (add x y) (+ x y)) (defn add [x y] (+ x y)) (defun add (x y) (+ x y))
can function and variable share name yes no no yes
optional argument (defun add (a &optional b) (define (add a (b null)) (defn add ([a] a) ([a b] (+ a b))) (defun add (a &optional b)
variable number of arguments (defun add (a &rest b) (define (add a . b) (defn add [a & b] (defun add (a &rest b)
default value (defun add (a &optional (b 0)) racket: (defn add none
named parameter (defun logarithm (&key number base) none (defn logarithm [{x :number b :base}] (/ (Math/log x) (Math/log b))) (defun logarithm
return multiple values (defun sqrts (x) (define (sqrts x) (defn sqrts [x] (list (Math/sqrt x) (- (Math/sqrt x)))) values creates a list:
assign multiple values to local variables (multiple-value-bind (r1 r2) (let-values (let [[r1 r2] (sqrts 3)] r2) (multiple-value-bind
assign multiple values to global variables (multiple-value-setq (r1 r2) (define-values (r1 r2) (sqrts 3)) none (multiple-value-setq (r1 r2) (sqrts 3))
convert list to multiple values (values-list '(1 2 3)) (apply values '(1 2 3)) multiple values are lists multiple values are lists
assign multiple values to list (multiple-value-list (sqrts 3)) (call-with-values multiple values are lists multiple values are lists
tail call optimization yes for sbcl yes yes with recur no
lambda (lambda (x) (* x x)) (lambda (x) (* x x)) #(* % %) (lambda (x) (* x x))
apply ((lambda (x) (* x x)) 2) ((lambda (x) (* x x)) 2) (#(* % %) 2) ((lambda (x) (* x x)) 2)
execution control
common lisp racket clojure emacs lisp
progn progn prog1 prog2 begin none none do none none progn prog1 prog2
loop (setq i 1) none, use recursion (loop [i 1] (setq i 1)
do (do ((i 1) (sum 0)) none none (do ((i 1) (sum 0))
dotimes (dotimes (i 10 nil) none (dotimes [_ 10] (dotimes (i 10 nil)
if (if (< x 0) (- x) x) (if (< x 0) (- x) x) (if (< x 0) (- x) x) (if (< x 0) (- x) x)
when (when (< x y) racket: (when (< x y) (when (< x y)
cond (cond ((> x 0) 1) (cond ((> x 0) 1) (cond (> x 0) 1 (cond ((> x 0) 1)
lazy evaluation (define x (delay (/ 1 0)))
continuations (define cc null)
exceptions
common lisp racket clojure emacs lisp
error (error "failed") (error "failed") (throw (Exception. "failed")) (error "failed")
handle error (handler-case (with-handlers (try (throw (Exception. "failure")) (condition-case e
define exception (define-condition odd-err (error) (define exn:odd-err? "odd number") only symbols and keywords can be thrown and caught
throw exception (error 'odd-err :num 7) (raise exn:odd-err?) (throw (Exception. "failed")) (throw 'odd-err t)
catch exception (handler-case (/ 1 0) (with-handlers ((exn:fail? (lambda (e) (begin (printf "division by zero~n") null)))) (/ 1 0)) (try (/ 1 0) (catch ArithmeticException _ (do (println "division by zero") nil))) (catch 'failed (throw 'failed nil) t)
restart-case (defun halve (l) none none
invoke-restart (handler-bind none none
finally clause (unwind-protect none (try (throw (Exception. "failure")) (unwind-protect
streams
common lisp racket clojure emacs lisp
standard file handles *standard-input* (current-input-port) *in*
end-of-file behavior read-line returns two values, the 2nd set to T at end-of-file. Returns the value eof. .readLine on a java.io.Reader object returns nil.
read line from stdin (setq line (read-line)) (let ((s (read-line))) (let [s (read-line)]
chomp read-line discards newline read-line discards newline
write line to stdout (defun println (s) (write-string s) (println "hello")
write formatted string to stdout (format t "~s ~d: ~2$~%" (printf "~a ~a: ~a~n" (printf "%s %d %.2f\n" "foo" 7 13.7)
open file for reading (setq in (open "/etc/hosts")) (let ; f is java.io.Reader object:
open file for writing (setq out (open "/tmp/test" :direction :output :if-exists :supersede)) (let ; f is java.io.Writer object:
open file for appending (setq out (open "/tmp/test" :direction :output :if-exists :append)) (let (let [f (clojure.java.io/writer "/tmp/foo"
close file (close in) (close-input-port f) (.close f)
close file implicitly (with-open-file (out #P"/tmp/test" :direction :output) (write-line "lorem ipsum" out)) (call-with-input-file (with-open [f
read line (setq line (read-line f)) (define line (read-line in)) (.readLine f)
iterate over file by line (for ([line (in-lines (loop [line (.readLine f)]
read file into array of strings ; to list of strings: (vec (line-seq f))
read file into string (define s (file->string "/etc/hosts")) (let [s (slurp "/etc/hosts")]
write string (write-string s f) (.write f s)
write line (write-string s f) (.write f (println-str s))
flush file handle (flush-output f) (f .flush)
file handle position ; Evaluates to non-negative integer: ; arg is characters from current position;
in memory stream (setq f (make-string-input-stream (define f (open-input-string "lorem ipsum")) ; use *in* to read from string:
emacs buffers
emacs lisp
list buffers ;; list of buffer objects:
current buffer ;; name of current buffer:
clear buffer ;; current buffer:
point ;; 1-based index of char under cursor:
search and set point ;; Set point to character after string.
insert at string point ;; takes 1 or more args:
current buffer as string (buffer-string)
insert file contents at point (insert-file "/etc/passwd")
mark ;; to beginning of current buffer:
files
common lisp racket clojure emacs lisp
file test, regular file test (osicat:file-exists-p "/tmp/foo") ?? (.exists (io/file "/etc/hosts")) (file-exists-p "/etc/hosts")
file size (file-size "/etc/hosts") (.length (io/file "/etc/hosts")) (eighth
is file readable, writable, executable (pair? (filter (.canRead (io/file "/etc/hosts"))
set file permissions (file-or-directory-permissions (set-file-modes "/tmp/foo" #o755)
last modification time (file-or-directory-modify-seconds "/tmp/foo") ; Unix epoch in milliseconds:
copy file, remove file, rename file (cl-fad:copy-file #P"/tmp/foo" (copy-file "/tmp/foo" "/tmp/bar") (clojure.java.io/copy (copy-file "/tmp/foo" "/tmp/bar")
create symlink, symlink test, get target (osicat:make-link "/tmp/hosts" :target "/etc/hosts") (make-file-or-directory-link (make-symbolic-link "/etc/hosts" /tmp/hosts")
temporary file (define tmp (make-temporary-file)) ; java.io.File: (make-temp-file "foo")
directories
common lisp racket clojure emacs lisp
build pathname (make-pathname ; returns path; convert to string (require '[clojure.java.io :as io])
dirname and basename (pathname-directory #P"/etc/hosts") (let-values (((dir file _) (require '[clojure.java.io :as io]) (file-name-directory "/etc/hosts")
absolute pathname (simplify-path (.getCanonicalPath (java.io.File. "..")) (expand-file-name "..")
iterate over directory by file (dolist (file (osicat:list-directory "/tmp")) (format t "~a~%" file)) (for ([path (directory-list "/etc")]) ; file-seq returns java.io.File objects for files (dolist
make directory (make-directory* "/tmp/foo/bar") (require '[clojure.java.io :as io]) creates parents if 2nd arg non-nil:
recursive copy (copy-directory/files "/tmp/foo.d"
remove empty directory (delete-directory "/tmp/foo.d") (delete-directory "/tmp/foo.d") (clojure.java.io/delete-file "/tmp/foo.d") (delete-directory "/tmp/foo.d")
remove directory and contents (osicat:delete-directory-and-files "/tmp/foo.d") (delete-directory/files "/tmp/foo.d") (delete-directory "/tmp/foo.d" t)
directory test (osicat:directory-exists-p #P"/etc") (directory-exists? "/etc") (.isDirectory (io/file "/etc")) (file-directory-p "/etc")
processes and environment
common lisp racket clojure emacs lisp
command line arguments *posix-argv* current-command-line-arguments *command-line-args* in shebang mode only:
program name
environment variables (posix-getenv "HOME") (getenv "HOME") (System/getenv "HOME") (getenv "HOME")
user id and name
exit
external command (run-program "ls" '( "/etc")) (require scheme/system) (.exec (Runtime/getRuntime) "ls") (shell-command "ls /etc")
command substitution (shell-command-to-string "ls /etc")
libraries and namespaces
common lisp racket clojure emacs lisp
complete example $ cat b/a.clj
compile library (compile-file "a.lisp") $ raco make a.rkt (compile 'a) $ emacs -batch -Q -L . \
load library (load "a.lisp") (require a) (require 'a) (require "a")
load library in subdirectory (load "b/a.lisp") (require "b/a.rkt") (require 'b.a)
hot patch (load "a.lisp") none (require 'b.a :reload) (load "a")
load error raises sb-int:simple-file-error raises exn:fail:syntax:missing-module. Because require must be top-level, the exception cannot be handled. raises FileNotFoundException raises file-err
library path contains working directory at startup (require setup/dirs) same as path used by java VM ; adds directory to library path:
library path environment variable none CLASSPATH EMACSLOADPATH
library path command line option none $ java -cp /foo/bar:/baz/quux $ emacs -L /foo/bar
namespace declaration (defpackage :foo) (module mconst racket (ns mconst) No namespaces; a common convention is to use a prefix on all identifiers in a library, separated from the rest of the identifier by a hyphen.
subnamespace declaration none ; must be in b/a.clj:
namespace separator : : . and /
import definitions ; set current *package* to foo and import symbol twiddle from bar:
import all definitions in namespace ; set current *package* to foo and import symbols from bar:
namespace shadow avoidance
identifier shadow avoidance
package manager help $ raco help
list installed packages $ raco pkg show --all M-x list packages
search packages (ql:system-apropos "time") http://pkgs.racket-lang.org M-x list-packages
install package ; install quicklisp $ raco pkg install --deps search-auto srfi Use M-x list-packages to bring up the package menu; i to select a package to install, and x to install it.
remove package $ raco pkg remove srfi In the package menu, use d to select a package to uninstall and x to uninstall it.
objects
common lisp racket clojure emacs lisp
define class (defclass rectangle () (define rectangle% use java:
make instance (make-instance 'rectangle (define rect (import 'Rectangle)
read attribute (rectangle-height rect) (send rect get-height) (.height r)
write attribute (setf (rectangle-height rect) 4) (send rect set-height 4) (.setHeight r 8)
define method (defmethod area ((figure rectangle)) (define/public (area) (defmulti area class)
invoke method (area rect) (send rect area) (area r)
universal superclass standard-object t object% Object
multiple inheritance yes no only one direct superclass; can implement multiple interfaces
lisp macros
common lisp racket clojure emacs lisp
backquote and comma (setq op '+) (define op '+) (def op +) (setq op '+)
defmacro (defmacro rpn (arg1 arg2 op) (define-syntax-rule (rpn arg1 arg2 op) (op arg1 arg2)) (defmacro rpn [arg1 arg2 op] (defmacro rpn (arg1 arg2 op)
defmacro w/ backquote (defmacro rpn (arg1 arg2 op) (define-syntax-rule (rpn3 arg1 arg2 op) (defmacro rpn [arg1 arg2 op] `(~op ~arg1 ~arg2)) (defmacro rpn (arg1 arg2 op)
macro predicate (macro-function rpn) none none none
macroexpand (macroexpand ’(rpn 1 2 +)) (syntax-object->datum (expand-to-top-form '(rpn 1 2 +))) (macroexpand '(rpn 1 2 +)) (macroexpand '(rpn 1 2 +))
splice quote (defmacro add ( &rest args ) (define-syntax-rule ( add first …) (+ first …)) (defmacro add [ & args ] `(+ ~@args)) (defmacro add ( &rest args )
recursive macro (defmacro add (a &rest b) (define-syntax add (syntax-rules () (defmacro add ([a] `(+ ~a)) ([a & b] `(+ ~a (add ~@b)))) (defmacro add (a &rest b)
hygienic no yes with # suffix no
local values (defmacro square-sum (x y) (define-syntax-rule (square-sum x y) (defmacro two-list [x] `(let [arg# ~x] (list arg# arg#))) (defmacro square-sum (x y)
reflection
common lisp racket clojure emacs lisp
inspect type (type-of '(1 2 3)) (list? '(1 2 3)) (= (type 1) java.lang.Long) (type-of [1 2 3] 'vector)
instance-of instance?
basic types logical and numeric:
sequence data types list vector list vector hash-table string input-port range all collections and strings list vector
get docstring (describe #'mapcar) none (doc map) (describe-function 'mapcar)
define function with docstring (defun add (x y) none (defn add "add x and y" [x y] (defun add (x y)
apropos and documentation search none none (apropos #"^add$") (apropos "^add$")
java interoperation
common lisp racket clojure emacs lisp
new (def rnd (new java.util.Random))
method (. rnd nextFloat)
class method (Math/sqrt 2)
chain
import (import '(java.util Random))
to java array (to-array '(1 2 3))
__________________________________________ __________________________________________ __________________________________________ __________________________________________

version used

Versions used to verify examples in the reference sheet.

show version

How to determine the version.

compiler

racket

Compiling a.ss creates the byte-code compiled file a_ss.zo, which will be used by mzscheme in preference to the source code if it encounters

standalone executable

racket

In order for code to be compiled as a standalone executable, it must be packaged as a module. This can be accomplished by putting the #lang scheme shorthand the top of the file. All functions that are defined in the module will be executed in order. Here is a simple example:

#lang scheme
(define hello
  (printf "Hello world!~n"))

emacs

Building Emacs

interpreter

How to interpret the code in a file.

shebang

How to have a script run by the interpreter automatically. Replace the given path with the path to the interpreter on your system.

emacs lisp

To run some lisp code from within emacs, use M-x load or M-x load-file. The first command will use the list of strings in load-path to search for the file. It is not necessary to specify the .el or .elc suffix if the file has one.

The following snippet is an emacs lisp shebang script implementation of cat:

#!/usr/bin/env emacs --script
(condition-case nil
  (let (line)
    (while (setq line (read-from-minibuffer ""))
        (princ line)
        (princ "\n")))
  (error nil))

An implementation of echo:

#!/usr/bin/env emacs --script
(condition-case nil
  (progn
    (dotimes (i (length argv) nil)
            (princ (nth i argv))
            (princ " "))
    (princ "\n"))
  (error nil))

repl

How to invoke the repl from the command line.

racket:

Racket also provides a GUI repl environment called DrRacket.

clojure:

The clojure repl saves the result of each evaluation in the variables *1, *2, … and the last exception in *e.

command line program

How to pass in a program to be executed on the command line.

word separator

What is used to separate the operator and data of a S-expression.

identifier characters

In lisps other than clojure, any character can be used in a symbol. Some characters are special to the reader and must be escaped to include them in a symbol. The reader will interpret a sequence of characters starting with a digit as a number instead of a symbol, so escaping must be used to create such a symbol.

common lisp:

Common Lisp is case insensitive, and the reader converts all letters to upper case. A symbol consisting of just periods "." must be escaped. Symbols that start and end with an asterisk "*" may conflict with system defined special variables.

racket:

# is only disallowed by the reader at the beginning of symbols. A symbol consisting of a single period must be escaped.

end-of-line comment

multiple line comment

#| |# delimited comments in Common Lisp and Scheme can span multiple lines, and thus can be used to comment out code.

clojure:

Code with balanced parens can be commented out in the following manner:

identifier

Are identifiers case sensitive; which characters can be used in identifers.

In Lisp, identifiers are called symbols.

quoted identifer

How to quote or escape characters in identifiers which are otherwise prohibited.

local variable

How to declare a local variable.

global variable

How to declare a global variable.

remove variable

How to remove a variable.

null

The null value.

common lisp

nil and the empty list '() are identical.

racket

null and the empty list '() are identical.

clojure

nil and the empty list '() are distinct.

emacs lisp

nil and the empty list '() are identical.

null test

How to test whether a value is null.

identifier as value

How to get the value of an identifier.

In Lisp, identifiers are first class values and can be stored in variables. When used as an argument, the Lisp interpreter will treat an identifier as the value of the variable associated with the identifier unless special syntax is used.

identifier test

How to test whether a value is an identifier.

non-referential identifier

A non-referential identifier is an identifier whose value is itself.

Non-referential identifiers are called keywords in Lisp. They also appear in Prolog, where they are called atoms, and Ruby, where they are called symbols.

A non-referential identifier can be convenient to use as a key in a dictionary, since it doesn't have to single quote escaped.

Strings are an alternative to non-referential identifiers; some languages have string interning which makes the use of strings just as efficient as non-referential identifiers.

identifier attributes

In Common Lisp, there is a dictionary of attributes associated with each identifier called a property list.

Clojure metadata is stored with a value which is an instance of clojure.lang.IObj. Many types are subclasses of clojure.lang.IObj, but integers, floats, and strings are not. Clojure metadata is immutable: all keys must be set at once and there is no way to remove keys.

cell types

The different cell types. A lisp-1 only stores a single entity under a symbol in a given environment. A lisp-2 stores multiple entities, and which entity a symbol will resolve to depends on how the symbol is used. In particular, a value and a function can be stored under the same symbol without collision.

nil, is () null?, is () symbol?

is true in common lisp and emacs lisp.

is true in Scheme.

keyword

Keywords are pre-defined symbols that evaluate to their printed representation. The reader recognizes them by the initial colon, or in the case of Scheme, by the initial "#:". In Scheme it is an error to use a keyword as an expression.

atom

atom is is a predicate which returns false for cons cells, and true for anything else. All lists except for the empty list are cons cells.

racket

Scheme lacks atom, but cons? is its logical negation.

clojure

Clojure lacks cons cells. Thus atom if implemented in the language would always return true. However, (not (list? x)) is closer to the spirit and certainly more useful. Because nil is not the empty list in clojure there is also ambiguity about what the value of (atom ()) would be.

quote

All lisps have a single quote macro abbreviation for quote. Here are identical ways to quote a symbol and a list:

(quote a)
'a

(quote (+ 3 7))
'(+ 3 7)

eval is a one-sided inverse of quote. If X is arbitrary lisp code, then the following are identical

eq, equal, =

In his 1960 paper, McCarthy described eq as undefined if either or both arguments are not atomic. Common Lisp and Scheme (eq?) return true if the arguments both evaluate to the same list in memory, otherwise false. equal and equal? (Scheme) return true if the arguments evaluate to lists with the same elements as determined by calling equal or equal? recursively.

In Common Lisp and Scheme, = can only be called on numeric arguments. The predicates for whether a symbol is numeric are numberp and number?, respectively.

Clojure dispenses with eq and equal and defines = to be equivalent to the Common Lisp equal.

car

Because car and cdr are abbreviations for parts of the word of the IBM 704, there is a trend to replace them with first and rest. However, car and cdr are short, and convenient notation exists for abbreviating nested calls to car and cdr.

In terms of car, cdr, and combinations thereof, here is what the dialects define:

common lisp r5rs racket clojure emacs lisp
car,first car car,first first car,first
cadr,second cadr cadr,second second,fnext cadr,second
caddr,third caddr caddr,third caddr,third
cadddr,fourth cadddr cadddr,fourth cadddr,fourth
fifth fifth fifth
sixth sixth sixth
seventh seventh seventh
eighth eighth eighth
ninth ninth ninth
tenth tenth tenth
cdr, rest cdr cdr, rest rest,next cdr, rest
cddr cddr cddr cddr
cdddr cdddr cdddr cdddr
cddddr cddddr cddddr cddddr
caar caar caar ffirst caar
cdar cdar cdar nfirst cdar

cdr

common lisp

cdr and rest return nil when called on an empty list.

racket

cdr and rest raise an error when called on an empty list.

clojure

rest returns an empty set () when called on an empty or singleton list, whereas next returns nil. In clojure, the empty set evaluates as true in a boolean context and nil evaluates as false.

cons

clojure

Clojure does not implement a list as a linked list of cons cells. The second argument to cons must be a list.

cond

lambda

clojure:

label

apply

integers

Common Lisp and Racket have arbitrary-precision integers and use them by default.

Racket provides the fixnum library for access to hardware integers:

(require racket/fixnum)

(fx+ 3 7)

Operations on Racket fixnums cause an error when they overflow.

rationals and floats

Common Lisp and Racket have arbitrary-precision rationals. Racket uses them in a number of cases when Common Lisp uses hardware floats:

Racket provides the flonum library for access to hardware floats:

(require racket/flonum)

(fl* 3.1 -7.2)

complex numbers

Both the real and imaginary part of a Common Lisp complex number will have the same type, but the type can be integer, rational, or float.

true and false

Literals for true and false.

falsehoods

Values which evaluate to false in a boolean context.

racket

null and the empty list {{'{} do not evaluate as false in a boolean context.

logical operators

The logical operators.

relational operators

Relational operators for performing comparisons.

min and max

Functions for returning the least and greatest of the arguments.

numeric predicates

A selection of numeric predicates.

realp and real? are true of all numbers which have a zero imaginary component. floatp and inexact? are true if the number is being stored in a floating point representation.

racket:

The following all evaluate as #t:

(rational? 1.1)
(rational? (sqrt 2))
(rational? pi)

closure of integers under division

The number system that containing the potential results of integer division. In mathematics, the closure of integers under division is the rationals, and this is true for common lisp, scheme, and clojure as well.

Emacs lisp performs integer division (i.e. computes the quotient), so the closure of the integers under division is the integers.

arithmetic operators

In Lisp, + and * take zero or more arguments and - and / take one or more arguments. With zero arguments + and * return the additive and multiplicative identities 0 and 1. With one argument + and * return the argument and - and / return the additive and multiplicative inverses: i.e. the negation and the reciprocal. When evaluating 3 or more arguments - and / are computed from left to right: i.e. (- 3 4 5) is computed as (- (- 3 4) 5).

clojure:

Math.pow returns a double.

emacs:

Unary division (i.e. computing the reciprocal) generates a wrong number of arguments error.

transcendental functions

float truncation

For rounding, floor, and ceiling, the return value is integer if the argument is rational and floating point if the argument is floating point, unless otherwise noted.

racket:

inexact->exact can be used to convert a float returned by round, ceiling, or floor to an integer.

clojure:

Math/round always returns an integer and throws and error if called on a rational. Math/floor and Math/ceil can be called on a rational, but always return a float.

emacs:

round, ceiling, and floor return integers. fround, fceiling, and ffloor return floats.

quotient and remainder

(sqrt -2)

The value of (sqrt -2). Common lisp and Scheme support complex numbers. Clojure and Emacs Lisp do not.

decomposition of integer, rational, complex

For absolute value, the type of the return value is the same of the type of the argument.

racket:

The scheme/math library must be loaded to use sgn.

clojure:

Math/signum only operates on a float and returns a float

random number

How to generate a random integer, and a random float in a uniform and a normal distribution.

bit operators

racket:

The bitwise operators implemented by Gambit and Racket are specified in the withdrawn standard SRFI 33.

emacs:

Also has ash, which gives a different value when both arguments are negative.

character literals

The syntax for character literals. The first literal uses the letter "a" as an example of how to write a literal for all ASCII printing characters.

common lisp:

Characters are of type standard-char. The predicate is characterp.

racket:

The predicate is char?.

clojure:

Characters are of type java.lang.Character.

emacs:

Characters are of type integer and can be manipulated by arithmetic operators. characterp and integerp are synonyms.

string literal

The syntax for a string literal.

string escapes

A list of escape sequences that can be used in string literals.

emacs lisp:

The \x escape sequence is followed by one to six hex digits. Because a variable number of hex digits can be used, it may be necessary to indicate the end of the sequence with a backslash and a space, e.g. the following string literal is "λ123":

character access

How to get the character at a given position in a string.

find substring

Find the location of a substring in a string.

extract substring

length

constructors

comparison

common lisp:

Here is the complete list of string comparison functions:

string=
string<
string>
string<=
string>=
string/=

There are also case insensitive versions of the above functions:

string-equal
string-lessp
string-greaterp
string-not-greaterp
string-not-lessp
string-not-equal

racket:

Case sensitive string comparison:

string<=?
string<?
string=?
string>=?
string>?

Case insensitive string comparison:

string-ci<=?
string-ci<?
string-ci=?
string-ci>=?
string-ci>?

emacs lisp:

Emacs has only these string comparison functions, all of which are case sensitive:

string=
string-equal
string<
string-lessp

string= and string-equal are synonyms, as are string< and string-lessp.

case

trim

emacs:

An implementation of trim:

(defun trim (s)
  (let ((s1 (replace-regexp-in-string "[ \t]*$" "" s)))
    (replace-regexp-in-string "^[ \t]*" "" s1)))

convert from string, to string

How to convert strings to numbers, and numbers to strings.

common lisp:

read-from-string invokes the reader, so the return value is not guaranteed to be a floating point number.

Here is a parse-float function which will convert all real numeric types to floats and raise a simple error if another condition is encountered.

(defun parse-float (s)
  (let ((readval (handler-case
                  (read-from-string s)
                  (sb-int:simple-reader-error nil)
                  (end-of-file nil))))
    (cond ((realp readval ) (+ readval 0.0))
          (t (error (concatenate 'string "not a float: " s))))))

concat

split

join

format

regular expressions

common lisp

http://weitz.de/cl-ppcre/

emacs lisp

string-match returns the first index of the first matching substring, or nil.

The following code moves the point to next position following the point that matches the argument, and returns the index of the that position.

(re-search-forward "hello")

regex substitution

regex special characters

current datetime

current unix epoch

unix epoch to broken-down datetime

broken-down datetime to unix epoch

format datetime

parse datetime

date parts

time parts

build broken-down datetime

list literal

pair literal

(car '())

(cdr '())

(eval '())

A practical advantage of having (eval '()) be equal to '() is that the empty list doesn't have to be quoted.

list functions

nth

nth and list-ref count from zero. nth returns nil if the index is too large. list-ref throws an error.

index of list element

How to get the index of a list element. The first element of a list has an index of zero.

last butlast

In clojure, last and butlast are analogs of first and rest which operate at the end of a list. If X is a list, then the following code pairs are identities:

(last X)
(first (reverse X))

(butlast X)
(reverse (rest (reverse X)))

The analogy breaks down in Common Lisp because last returns a list with a single element.

set-car set-cdr

common lisp:

The following code pairs perform the same operation on the list:

(setf (car l) 3)
(rplaca l 3)

(setf (cdr l) '(4 5 6))
(rplacd l '(4 5 6))

However, they are not identical because rplaca and rplacd return the modified list instead of their 2nd argument.

racket:

Racket provides a separate interpreter plt-r5rs for an R5RS compliant version of Scheme. Also, the language can be set to R5RS within DrRacket.

emacs lisp:

Also has setf.

sort

assoc

clojure

In Clojure, assoc returns a new association with the specified values replaced:

(def numbers {1 :one 2 :two 3 :three 4 :four})
(def jumble (assoc numbers 1 :uno 3 :drei 4 :quatre))

getf

racket:

How to implement getf in Scheme:

(define (getf lst key (default null))
    (cond ((null? lst) default)
          ((null? (cdr lst)) default)
          ((eq? (car lst) key) (cadr lst))
          (else (getf (cddr lst) key default))))

map

common lisp

The lambda can accept multiple arguments:

(mapcar '+ '(1 2 3) '(4 5 6))

racket

(map + '(1 2 3) '(4 5 6))

clojure

(map + '(1 2 3) '(4 5 6))

emacs lisp

mapcar does not accept multiple argument lambdas

filter

common lisp

Also the negative version:

(remove-if (lambda (x) (> x 2)) '(1 2 3))

clojure

Also the negative version:

(remove #(> % 2) '(1 2 3))

emacs lisp

Also has negative version:

(remove-if (λ (x) (> x 2)) '(1 2 3))

reduce (left fold)

right fold

clojure:

How to define foldr:

(defn foldr [f init list] (reduce #(f %2 %1) (reverse list)))

sublis

How to apply the mapping defined by an associative list to a recursive list.

dolist

take

Here is how to define take for common lisp or emacs lisp:

(defun take (n l)
  (cond ((< n 0) (error "index negative"))
        ((= n 0) ())
        ((null l) (error "index too large"))
        (t (cons (car l) (take (- n 1) (cdr l))))))

drop

push and pop

racket:

Here is an implementation of push and pop in Racket using boxes:

(define (push x a-list)
  (set-box! a-list (cons x (unbox a-list))))

(define (pop a-list)
  (let ((result (first (unbox a-list))))
    (set-box! a-list (rest (unbox a-list)))
    result))

clojure:

Note the in clojure, pop only returns the first element; the original list is left unmodified.

vector literal

racket

#(1 2 3) creates an immutable vect. (vector 1 2 3) creates a mutable vector.

vector access

set vector element

racket

vector-set! throws an error if called on an immutable vector.

vector to list

list to vector

abstract sequence

Lists and vectors support the same operations; the only difference is the speed at which the operations can be performed. It is a convenience for the developer if functions that perform the operations have the same name; i.e. if lists and vectors are members of an abstract sequence type. Clojure has gone furthest in this direction, making all the customary list functions work on vectors as well. In common lisp and emacs lisp, some of the list functions also work on vectors, and some don't. In Scheme none of the list functions work on vectors.

sequence data types

The containers that respond to sequence functions.

sequence predicate

list functions usable on sequences

make-array

In Lisp terminology, both arrays and vectors refer to collections which are of fixed size; vectors are arrays with rank 1. Only common lisp supports arrays with rank greater than 1.

array access

set array element

array dimensions

array-rank returns the number of indices required to specify an element in the array. array-dimensions returns the size of the array; the number of cells is the product of the elements of the list.

range

list comprehension

Lisp has a tradition of using lists of pairs for dictionaries. The data structures in this section are implemented using hash tables.

racket:

In addition to hash tables there are a set of functions which work with any dictionary type, which in Racket include hash tables, lists of cons cell pairs, and vectors. When a vector is treated as a dictionary, the value is an element and the key is the integer index of the element.

clojure:

There are three dictionary types which can be used with the functions described in this section:

constructor type
(hash-map "t" 1 "f" 0) clojure.lang.PersistentHashMap
(array-map "t" 1 "f" 0) clojure.lang.PersistentArrayMap
(zipmap '("t" "f") '(1 0)) clojure.lang.PersistentArrayMap
(sorted-map "t" 1 "f" 0) clojure.lang.PersistentTreeMap
(sorted-map-by #(< %1 %2) "t" 1 "f" 0) clojure.lang.PersistentTreeMap

The syntax for a dictionary literal.

The constructor for a dictionary.

racket:

The constructors use equal? to test for equality of the two keys.

There are also constructors which use eq? or eqv? to test keys: hasheq, hasheqv, make-immutable-hasheq, make-immutable-hasheqv.

How to test whether a value is a dictionary.

How to get the number of keys stored in the dictionary.

How to look up the value associated with a key.

How to insert a key-value pair or replace the value stored with an existing key.

What happens when a lookup is performed on a key not in the dictionary.

racket:

How to handle the error and return a null when the key is not found:

(with-handlers ((exn:fail? (lambda (e) null))) (get h "goodbye"))

How to check whether a key exists in a dictionary.

How to remove a key and its associated value from a dictionary.

How to merge two dictionaries.

How to turn a dictionary into its inverse. If a key 'foo' is mapped to value 'bar' by a dictionary, then its inverse will map the key 'bar' to the value 'foo'.

If multiple keys are mapped to the same value in the original dictionary, some of the keys will be discarded in the inverse.

How to iterate over the key-value pairs in a dictionary.

How to get the keys or the values in a dictionary as lists.

defstruct

struct

struct getter

struct setter

struct predicate

let, let*

Traditionally let performs its assignments in parallel and let* serially.

clojure

In Clojure, let and let* are synonyms and both perform serial assignment.

emacs

Note that let uses dynamic scope. Use lexical-let for lexical scope:

ELISP> (let ((x 3)) (defun get-x () x))
get-x
ELISP> (get-x)
*** Eval error ***  Symbol's value as variable is void: x
ELISP> (let ((x 4)) (get-x))
4
ELISP> (lexical-let ((x 3)) (defun get-x-2 () x))
get-x-2
ELISP> (get-x-2)
3
ELISP> (lexical-let ((x 4)) (get-x-2))
3

define function

optional argument

variable number of arguments

default value

named parameter

common lisp:

In common lisp, named parameters are optional. Named values can be assigned default values:

 (defun logarithm (&key number (base 10)) (/ (log number) (log base)))

If a named parameter is not provided at invocation and has not been assigned a default value, then it is set to nil.

racket:

How to Implement Named Parameters in Scheme

emacs lisp:

In emacs lisp named parameters are mandatory. A runtime error results in they are not provided when the function is invoked.

tail call optimization

common lisp:

The ANSI Common Lisp specification does not require an implementation to perform tail call optimization.

get docstring

How to get the documentation string for a function.

common lisp:

describe returns the documentation string with additional information such as the function signature. To get just the documentation string use this:

(documentation #'mapcar 'function)

define function with docstring

How to define a function that has a documentation string.

apropos and documentation search

How to search definitions and documentation.

Apropos takes a pattern and returns all defined symbol names which match the pattern.

clojure:

apropos returns matching symbol names as a list.

find-doc searches all documentation strings and writes any which match to standard out.

Both apropos and find-doc can take a string or a regular expression as an argument.

emacs lisp:

apropos displays the documentation for matching definitions in the *Apropos* buffer. The argument is a string but will be treated as a regular expression.

progn

progn and its equivalents in other dialects returns the value of the last expression. Common Lisp and Emacs Lisp also have prog1 and prog2 for returning the value of the 1st or 2nd expression.

loop

do

dotimes

if

when

error

handle error

racket:

Calling error raises an exception of type exn:fail

emacs:

In the example:

(condition-case nil (error "failed") (error (message "caught error") nil))

the 2nd argument to condition-case is the code which might raise an error, and the 3rd argument is the error handler. The error handler starts with condition to be caught. The last nil is the return value of the entire condition-case expression.

An error cannot be handled by catch. An uncaught throw will generate an error, which can be handled by a condition-case error handler.

define exception

How to define a custom exception with a payload.

common lisp:

The :report clause is not necessary. If defined it will be displayed if the exception is handled by the lisp debugger.

throw exception

emacs:

The 1st argument of an emacs throw expression identifies the type of exception, and the 2nd argument will be the return value of the catch expression that catches the exception.

catch exception

emacs

The following catch expression will return nil:

(catch 'failed (throw 'failed nil) t)

restart case

invoke restart

finally clause

racket:

clojure:

Here is an optional technique for making sure that a file handle is closed:

(with-open [#^PrintWriter w (writer f)] (.print w content))

lazy evaluation

continuations

standard file handles

end-of-file behavior

read line from stdin

chomp

write line to stdout

write formatted string to stdout

racket

printf prints to stdout. format returns a string.

emacs lisp

The format statement returns the generated string. When used for i/o, it prints in the emacs minibuffer.

open file for reading

open file for writing

open file for appending

close file

close file implicitly

read line

iterate over file by line

read file into array of strings

read file into string

write string

write line

flush filehandle

file test, regular file test

file size

is file readable, writable, executable

set file permissions

copy file, remove file, rename file

create symlink, symlink test, get target

temporary file

in memory file

build pathname

How to build a file pathname from components.

dirname and basename

How to extract the directory portion of a pathname; how to extract the non-directory portion.

absolute pathname

How to get the get the absolute pathname for a pathname. If the pathname is relative the current working directory will be appended.

iterate over a directory by file

How to iterate over the files in a directory.

make directory

How to create a directory, including any parents directories specified in the path.

recursive copy

How to copy a directory and its contents.

remove empty directory

How to remove an empty directory.

remove directory and its contents

How to remove a directory and its contents.

directory test

How to test whether a directory exists.

external command

command line arguments

emacs

The global variables command-line-args and argv are set when emacs is run in shebang mode: i.e. with the —script option. command-line-args contains the pathname used to invoke emacs, as well as any options processed by emacs at startup, in addition to any additional arguments. argv only contains the additional arguments.

environment variables

loading a file

How to load a file and evaluate the top level expressions.

common lisp

Does not display the result of any evaluations.

racket

Displays the result of the last evaluation.

loading a library

define class

make instance

read attribute

write attribute

define method

invoke method

define subclass

universal superclass

multiple inheritance

backquote and comma

defmacro

defmacro-backquote

macro predicate

macroexpand

macroexpand recursively expands a sexp until the head is no longer a macro. It does not expand arguments that are macros.

common lisp

Common lisp also has macroexpand-1, which will non-recursively expand a macro once. The head of the expansion may thus be a macro.

clojure

Clojure also has macroexpand-1. See above for an example of use.

emacs lisp

Emacs has macroexpand-all, which will recursively expand a sexp until head and arguments are free of macros.

splice quote

recursive macro

hygienic

Does the language have macros whose expansions are guaranteed not to introduce name collisions.

local values

type-of

How to get the data type of the entity referred to by a symbol.

version used on jvm

extra libraries used

racket:

The srfi-1 library brings in a common list functions which Kawa does not make available by default. See SRFI.

new

method

class method

chain

import

to java array

ANSI Specification

For a package manager we use Quicklisp. Here is how to install it and use it to load the cl-ppcre library:

$ curl -O http://beta.quicklisp.org/quicklisp.lisp
$ sbcl
* (load "quicklisp.lisp")
* (quicklisp-quickstart:install)
* (ql:quickload "cl-ppcre")
* (cl-ppcre:all-matches "foo" "foo bar")

Quicklisp creates a quicklisp directory in the user's home directory. Once quicklisp is downloaded and installed, it can be used like this:

$ sbcl
* (load "~/quicklisp/setup.lisp")
* (ql:quickload "cl-ppcre")
* (cl-ppcre:all-matches "foo" "foo bar")

One can ensure that Quicklisp is automatically loaded at startup by putting the load command into the .sbclrc file:

$ cat ~/.sbclrc
(load "~/quicklisp/setup.lisp")

Guide: Racket

Racket ships with a large number of libraries in the collects directory of the installation which can be loaded with the require command, which takes a raw symbol which is the relative pathname from the collects directory to the file, not including the .rkt suffix. The Racket 5.1 distribution includes 50 SRFI libraries.

Racket also has a built in package management system. Browse the list of available packages. To install a package, click through to the detail page for the package and get the require string to load it. If the require string is executed by Racket, the library will be downloaded somewhere in the user's home directory. When I ran this on my Mac

$ racket
> (require (planet "spgsql.rkt" ("schematics" "spgsql.plt" 2 3)))

the files for the PostgreSQL database bindings were installed in ~/Library/Racket.

Clojure Reference

Calling Java

Here are the basics of calling Java code:

(def rnd (new java.util.Random))  ; create Java object
(. rnd nextFloat)  ; invoke method on object
(. rnd nextInt 10)  ; invoke method with argument
(. Math PI)  ; static member
(import '(java.util Random))  ; import

Clojure automatically imports everything in java.lang.

There are shortcuts for the above syntax:

(Random.)
(new Random)

Math/PI
(. Math PI)

(.nextInt rnd)
(. rnd nextInt)

Because they are primitive types and not objects, Clojure provides functions specific to Java arrays:

(make-array CLASS LEN)
(make-array CLASS DIM & DIMS)
(aset ARY IDX VAL)
(aset ARY IDX_DIM1 IDX_DIM2 ... VAL)
(aget ARY IDX)
(aget ARY IDX_DIM1 IDX_DIM2 ...)
(alength JARY)
(to-array SEQ)
(into-array TYPE SEQ)
(amap ARY I COPY EXPR)
(areduce ARY IDX  COPY INIT EXPR )

GNU Emacs Manual

To get an introduction to Emacs Lisp Programming from within Emacs use

Run M-x lisp-interaction-mode to put Emacs in lisp interaction mode. In lisp interaction mode the command C-x e will evaluate the s-expression on the current line. M-x eval-buffer will evaluate the entire buffer.

Use lisp interaction mode to define functions which can be called from Emacs. The following defines a function called dired-emacs-lisp for browsing the Emacs Lisp directory:

(defun dired-emacs-lisp ()
  "Open the Emacs Lisp directory in dired."
  (interactive)
   (dired "/Applications/Emacs.app/Contents/Resources/lisp"))

The directory is hard-coded into the function and may be different on your system. Once defined the function can be invoked with M-x dired-emacs-lisp. Not all Lisp functions can be called in this manner. Those that can are called commands. The body of a command has an optional documentation string, followed by a call to interactive, followed by the code which executes when the command is invoked. The documentation string can be accessed from Emacs by running M-x describe-function and entering the name of the function when prompted.

The call to interactive is what makes a Lisp function a command. It can takes optional arguments. Use M-x describe-function on interactive to see a description of these arguments.

To bind the command to the key C-c l run the following in Lisp interaction mode:

(global-set-key "\C-cl" 'dired-emacs-lisp)

If it is desired to have the above command and key binding always available when Emacs starts up, put them in ~/.emacs.d/init.el.