Skip to content

对比学习Racket/Clojure/EmacsLisp/CommonLisp, 以及基本算法

Notifications You must be signed in to change notification settings

chanshunli/fp-book

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 

Repository files navigation

《 Functional Racket/Clojure/EmacsLisp/CommonLisp 》

对比学习Racket/Clojure/EmacsLisp/CommonLisp, 以及基本算法

Declaration: Content forked form the http://hyperpolyglot.org/lisp, only for compare study lisp and record learning experience

Show Version

;; common-lisp
$ sbcl --version
;; racket
$ racket --version
;; clojure
displayed by repl on startup
;; emacs-lisp
$ emacs --version

Compiler

;; common-lisp
;; racket
$ raco make module.rkt
;; clojure
;; emacs-lisp
M-x byte-compile-file

Standalone Executable

;; common-lisp
(sb-ext:save-lisp-and-die  "executable"  :executable t  :toplevel 'function)
;; racket
$ mzc —exe executable file
;; clojure
;; emacs-lisp

Interpreter

;; common-lisp
$ sbcl --script foo.lisp
;; racket
$ racket -r foo.racket
;; clojure
specify full path to clojure jar:
java -cp clojure.jar clojure.main foo.clj
;; emacs-lisp

Shebang

;; common-lisp
#!/usr/bin/env sbcl --script
;; racket
#!/usr/bin/env racket --script
;; clojure
specify full path to clojure jar:
#!/usr/bin/env java -jar clojure.jar
;; emacs-lisp
#!/usr/bin/env emacs --script

Repl

;; common-lisp
$ sbcl
;; racket
$ racket
;; clojure
$ java -jar /PATH/TO/clojure.jar
;; emacs-lisp
M-x ielm

Command Line Program

;; common-lisp
;; racket
$ racket -e '(+ 1 1)'
;; clojure
;; emacs-lisp

Word Separator

;; common-lisp
whitespace
;; racket
whitespace
;; clojure
whitespace and commas
;; emacs-lisp
whitespace

End Of Line Comment

;; common-lisp
(+ 1 1) ; adding
;; racket
(+ 1 1) ; adding
;; clojure
(+ 1 1) ; adding
;; emacs-lisp
(+ 1 1) ; adding

Multiple Line Comment

;; common-lisp 和 emacs-lisp的区别, clisp 可以行中间注释, elisp不可以
(+ 1 #| adding |# 1) ;;=> 2
;; racket
(+ 1 #| adding |# 1)
;; clojure
;; emacs-lisp

Identifier

;; common-lisp
case insensitive, cannot start with digitexcluded characters:
SP ( ) " , ' ` : ; # | \reserved for user macros:
? ! [ ] { }
;; racket
case sensitive, cannot start with digitexcluded characters:
SP ( ) [ ] { } " , ' ` ; # | \
;; clojure
case sensitive, cannot start with digitpermitted characters:
A-Z a-z 0-9 * + ! - _ ?these have special meaning or are reserved:
/ . :
;; emacs-lisp
case sensitive, cannot start with digitexcluded characters:
SP ( ) " , ' ` ; # | \ _ [ ]

Quoted Identifierand Escaped Identifier

;; common-lisp
(setq |white space symbol| 3) ;;=> 3
(setq white\ space\ symbol 3) ;;
;; racket
(define |white space symbol| 3)
(define white\ space\ symbol 3)
;; clojure
nonenone
;; emacs-lisp
none
(setq white\ space\ symbol 3)

Local Variable

;; common-lisp
; parallel assignment:
(let ((x 3) (y 4)) (+ x y)) ; sequential assignment: 7
(let* ((x 3) (y (* x x))) (+ x y)) ;;=> 12
;; racket
; parallel assignment:
(let ((x 3) (y 4))  (+ x y)); sequential assignment:
(let* ((x 3) (y (* x x)))  (+ x y))
;; clojure
(let [x 3 y 4]  (+ x y))
(let [[x y] [3 4]]  (+ x y))
(let [x 3 y (* x x)]  (+ x y))
;; emacs-lisp
; parallel assignment:
(lexical-let ((x 3) (y 4))  (+ x y)) ;; 7
(lexical-let* ((x 3) (y (* x x)))  (+ x y)) ;; 12

Global Variable

;; common-lisp
(defparameter *x* 3) ;; doesn't change x if already set, *X* => 3 , (setq *X* 312312) => *X* 还是312312?
(defvar *x* 3)
;; racket
(define x 3); y is not global:
(define (double z)  (define y 2)  (* y z))
;; clojure
(def x 3)
;; emacs-lisp 即使是一个列表,也是可以作为变量名的
(set 'x 3)
(setq x 3)

Remove Variable

;; common-lisp
(makunbound 'x) ;; (makunbound '*X*) 去除变量值
;; racket
(namespace-undefine-variable! 'x)
;; clojure
(ns-unmap *ns* 'x)
;; emacs-lisp 这里是移除变量的操作
(makunbound 'x)

Null

;; common-lisp
nil '()
;; racket
null '()
;; clojure
; same value as null in Java:
nil
;; emacs-lisp
nil '()

Null Test

;; common-lisp
(null x) ;; x 为nil时, 结果为T. 否则为NIL
;; racket
(null? x)
;; clojure
(nil? x)
;; emacs-lisp
(null x)

Identifier As Value

;; common-lisp
'x
(quote x) ;; (= (quote x) 'X) ? ==> = 只能是数字
;; racket
'x
(quote x)
;; clojure
'x
(quote x)
;; emacs-lisp
'x
(quote x)

Identifier Test

;; common-lisp
(symbolp 'x) ;; T 判断是否为symbol类型
;; racket
(symbol? 'x)
;; clojure
(symbol? 'x)
;; emacs-lisp p判断类型通常有着一个p
(symbolp 'x)

Identifier Equality Test

;; common-lisp
(eq 'x 'x) ;; => (eq (quote x) 'x) => T, eq通常用于测试是否相等的表达式,=测试是否相等的数字
;; racket
(eq? 'x 'x)
;; clojure
(= 'x 'x)
;; emacs-lisp
(eq 'x 'x)

Non Referential Identifier

;; common-lisp
:foo ;;=> :FOO
;; racket
#:foo
;; clojure
:foo
;; emacs-lisp
:foo

Identifier Attributesset Get Remove

;; common-lisp
(set 'x 13)
(setf (get 'x :desc) #|这里测试是NIL|# "unlucky") ;;=> 结果输出unlucky, (get 'x :desc)变成了unlucky, setf 给:desc属性赋值为unlucky
(get 'x :desc)
(remprop 'x :desc) ;;=> (:DESC "unlucky"), :desc属性去除后为零了
;; racket
none
;; clojure
; value must be instance of clojure.lang.IObj:
(def x (with-meta [13] {:desc "unlucky"}))
(get (meta x) :desc); none
;; emacs-lisp 元数据的操作,移除和获取
(set 'x 13)
;; get is nil, setf is string
(setf (get 'x :desc) "unlucky")
(get 'x :desc) ;; string
(remprop 'x :desc) ;; 移除元数据就没有字符串了

True And False

;; common-lisp
t nil ;;=> T, NIL
;; racket
#t #f
true false
;; clojure
true false
;; emacs-lisp
t nil

Falsehoods

;; common-lisp
nil ()
;; racket
#f false
;; clojure
false nil
;; emacs-lisp
nil ()

Logical Operators

;; common-lisp
(or (not t) #|输出NIL|# (and t nil) #|输出NIL|#) ;;=> NIL
;; racket
(or (not #t) (and #t #f))
;; clojure
(or (not true) (and true false))
;; emacs-lisp
(or (not t) (and t nil))

Relational Operators

;; common-lisp
= /= < > <= >=
;; racket
= none < > <= >=
;; clojure
= not= < > <= >=
;; emacs-lisp
= /= < > <= >=

Min And Max

;; common-lisp
(min 1 2 3) ;;=> 1
(max 1 2 3) ;;=> 3
;; racket
(min 1 2 3)
(max 1 2 3)
;; clojure
(min 1 2 3)
(max 1 2 3)
;; emacs-lisp
(min 1 2 3)
(max 1 2 3)

Numeric Predicates

;; common-lisp 数值和浮点型判断
numberp integerp
rationalp floatp
realp complexp
;; racket
number? integer?
rational? inexact?
real? complex?
;; clojure
number? integer?
rational? float?none none
;; emacs-lisp 基本上和clisp设计是一样的,类型的判断p
numberp integerpnone floatpnone none

Arithmetic Operators

;; common-lisp
+ - * / mod
;; racket
+ - * / modulo
;; clojure
+ - * / mod
;; emacs-lisp
+ - * / %

Integer Divisionand Remainder

;; common-lisp
(truncate 7 3) ;;=> 2, 1
(rem 7 3) ;;=> 1
;; racket
(quotient 7 3)
(remainder 7 3)
;; clojure
(quot 7 3)
(rem 7 3)
;; emacs-lisp
(/ 7 3)
(% 7 3)

Integer Division By Zero

;; common-lisp
division-by-zero error
;; racket
division by zero error
;; clojure
;; emacs-lisp
arith-error

Float Division

;; common-lisp
rational:
(/ 7 3) ;;=> float: => 7/3 (2.3333333) ;;;=> (= (/ 7 3) 2) => NIL
(/ 7 (* 3 1.0)) ;; =>  2.3333333
;; racket
rational:
(/ 7 3)float:
(/ 7 (float 3))
;; clojure
rational:
(/ 7 3)float:
(/ 7 (* 3 1.0))
;; emacs-lisp
integer quotient:
(/ 7 3)float:
(/ 7 (* 3 1.0))

Float Division By Zero

;; common-lisp
division-by-zero error
;; racket
;; clojure
;; emacs-lisp
-1.0e+INF, -0.0e+NaN, or 1.0e+INF

Power

;; common-lisp
(expt 2 32) ;;=> => 4294967296 (33 bits, #x100000000, #o40000000000, #b100000000000000000000000000000000)
;; racket
(expt 2 32)
;; clojure
returns float:
(Math/pow 2 32)
;; emacs-lisp
(expt 2 32) ;; 0, ?

Sqrt

;; common-lisp
(sqrt 2) ;;=> => 1.4142135
;; racket
(sqrt 2)
;; clojure
(Math/sqrt 2)
;; emacs-lisp
(sqrt 2)

Sqrt 1

;; common-lisp
#c(0.0 1.0)
;; racket
0+1i
;; clojure
(Math/sqrt -1): NaN
;; emacs-lisp
-0.0e+NaN

Transcendental Functions

;; common-lisp
exp log sin cos tan asin acos atan atan ;;=> 周期函数,声波的机器学习,傅里叶分析
;; racket
exp log sin cos tan asin acos atan atan
;; clojure
Math/exp Math/log Math/sin Math/cos Math/tan Math/asin Math/acos Math/atan Math/atan2
;; emacs-lisp 三角函数的,周期的建模
exp log sin cos tan asin acos atan atan

Float Truncation

;; common-lisp
return two values, first is integer:
truncate round ceiling floor
;; racket
return floats:
truncate round ceiling floor
;; clojure
return integers:
int Math/roundreturn floats:
Math/ceil Math/floor
;; emacs-lisp
truncate round ceiling floor
fround fceiling ffloortruncate returns integer

Absolute Valueand Signum

;; common-lisp
abs signum
;; racket
absracket: sgn
;; clojure
Math/abs Math/signum
;; emacs-lisp
abs signum

Integer Overflow

;; common-lisp
none; arbitrary-precision integers
;; racket
none; arbitrary-precision integers
;; clojure
clojure.lang.Numbers.throwIntOverflow exception
;; emacs-lisp

Float Overflow

;; common-lisp
floating-point-overflow error
;; racket
;; clojure
not literals:
-Infity NaN Infinity
;; emacs-lisp

Rational Construction

;; common-lisp
(/ 3 7); literal:
3/7
;; racket
(/ 3 7); literal:
3/7; also rational:
2.718
(exp 1)
;; clojure
(/ 3 7); literal:
3/7
;; emacs-lisp

Rational Decomposition

;; common-lisp
(numerator 3/7) ;;=> 3
(denominator 3/7) ;;=> 7
;; racket
(numerator 3/7)
(denominator 3/7)
;; clojure
(numerator 3/7)
(denominator 3/7)
;; emacs-lisp
none none

Complex Construction

;; common-lisp
#c(1 2) ;;=> ??
;; racket
1+2i
(+ 1 +2i)
;; clojure
none
;; emacs-lisp
none

Complex Decomposition

;; common-lisp
(realpart #c(1 2)) ;; => 1
(imagpart #c(1 2)) ;;=> 2
(phase #c(1 2)) ;;=> 1.1071488
(abs #c(1 2)) ;;=> 2.236068
(conjugate #c(1 2)) ;;=> #C(1 -2)
;; racket
(real-part 1+2i)
(imag-part 1+2i)
(angle 1+2i)
(magnitude 1+2i)
(conjugate 1+2i)
;; clojure
nonenone
;; emacs-lisp
none none

Random Numberuniform Integer Uniform Float Normal Float

;; common-lisp
(random 100) ;; => 92
(random 1.0) ;; => 0.6700171
;; racket
(random 100)
(random)none
;; clojure
(def rnd (java.util.Random.))
(.nextInt rnd 100)
(.nextFloat rnd)
(.nextGaussian rnd)
;; emacs-lisp
(random 100)

Random Seed

;; common-lisp
(setq *random-state*  (sb-ext:seed-random-state 17))
;; racket
(random-seed 17)
;; clojure
;; emacs-lisp

Bit Operators

;; common-lisp 位运算
ash left shift when 2nd argument positive logand logior logxor lognot
;; racket
arithmetic-shift left shift when 2nd argument positive bitwise-and bitwise-ior bitwise-xor bitwise-not
;; clojure
bit-shift-left bit-shift-right bit-and bit-or bit-xor bit-not
;; emacs-lisp 位的操作
lsh left shift when 2nd argument positive logand logior logxor lognot

Binary Octal And Hex Literals

;; common-lisp
#b101010 ;; => 42 (6 bits, #x2A, #o52, #b101010)
#o52 ;;=> 42 (6 bits, #x2A, #o52, #b101010)
#x2a ;;=> 42 (6 bits, #x2A, #o52, #b101010)
;; racket
#b101010
#o52
#x2a
;; clojure
;; emacs-lisp

Radix

;; common-lisp
(format nil "~7r" 42) ;;=> "60"
;; racket
;; clojure
;; emacs-lisp

String Test

;; common-lisp
(stringp "foo") ;;=> T, (symbolp :abc)=> T
;; racket
(string? "foo")
;; clojure
(string? "foo")
;; emacs-lisp p的类型判断
(stringp "foo")

String Literal

;; common-lisp
"foo bar"
;; racket
"foo bar"
;; clojure
"foo bar"
;; emacs-lisp
"foo bar"

Newline In Literal

;; common-lisp
yes
;; racket
yes
;; clojure
yes
;; emacs-lisp
yes

Literal Escapes

;; common-lisp
\" \\ ;; 特殊字符反引号
;; racket
\t \n \r \" \\ \ooo \uhhhh
;; clojure
\b \t \n \f \r \" \\ \ooo \uhhhh
;; emacs-lisp 特殊字符如换行
\b \t \n \f \r \" \\ \ooo \uhhhh \xh - \xhhhhhh \C-x \M-x

Constructor

;; common-lisp
;; racket
(string #\f #\o #\o)
;; clojure
;; emacs-lisp 列表转为字符串
(string ?f ?o ?o) ;; foo

Format String

;; common-lisp "~,2f" 是浮点型的format
(format nil "~a: ~a ~,2f" "Foo" 7 13.457) ;;=> "Foo: 7 13.46"
;; racket
(format "~a ~a ~a" "Foo" 7 13.457)
;; clojure
(String/format "%s: %d %.2f"  (to-array ["Foo" 7 13.457]))
;; emacs-lisp
(format "%s: %d %.2f" "Foo" 7 13.457)

Format Specifiers

;; common-lisp 各种类型的Format填充方法
~a    any type, human readable
~s    any time, read parseable
~%    newline
~~    tilde
~c    character
~,5f  5 digits right of decimal mark
~d    decimal
~x    hex
~o    octal
~b    binary
;; racket
~a    any type, human readable
~s    any time, read parseable
~%    newline
~~    tilde
~c    character
~d    decimal
~x    hex
~o    octal
~b    binary
;; clojure
;; emacs-lisp

Compare Strings

;; common-lisp
(string= "foo" "bar") ;;=> NIL ,字符串比较是否相同
(string< "foo" "bar") ;;=> NIL
;; racket
(string=? "foo" "bar")
(string<? "foo" "bar")
;; clojure
(.equals "foo" "bar")
(.compareTo "foo" "bar")
;; emacs-lisp 字母的先后排序大小
(string= "foo" "bar")
(string< "foo" "bar")

Concatenate

;; common-lisp 字符串连接
(concatenate 'string "foo " "bar " "bar") ;;=> "foo bar bar" ,, (concatenate 'string 1 2 3) 是报错的
;; racket
(string-append "foo " "bar " "baz")
;; clojure
(str "foo " "bar " "baz")
;; emacs-lisp 字符串连接
(concat "foo " "bar " "baz")

Replicate

;; common-lisp
(make-string 3 :initial-element #\f) ;;=> "fff"
;; racket
(make-string 3 #\f)
;; clojure
(String. (into-array  (. Character TYPE)  (repeat 3 \f)))
;; emacs-lisp 字符串创建
(make-string 3 ?f) ;; fff

Translate Case

;; common-lisp
(string-downcase "FOO") ;;=> "foo"
(string-upcase "foo")
;; racket
(string-downcase "FOO")
(string-upcase "foo")
;; clojure
(.toLowerCase "FOO")
;; emacs-lisp
(downcase "FOO")
(upcase "foo")

Capitalize

;; common-lisp
; "Foo Bar":
(string-capitalize "foo bar") ;;=> "Foo Bar", 驼峰
;; racket
;; clojure
;; emacs-lisp
; "Foo Bar": 类似rails 命名
(capitalize "foo")

Trim

;; common-lisp
(string-trim '(#\space #\tab #\newline) " foo ") ;;=> "foo" 去除一些字符串
;; racket
(require srfi/13/string)
(string-trim-both " foo ")
;; clojure
(.trim " foo ")
;; emacs-lisp
none; see notes for an implementation

Padon Right On Left

;; common-lisp
(format nil "~10a" "foo") ;; => "foo       "
(format nil "~10@a" "foo") ;;=> "       foo"
;; racket
;; clojure
;; emacs-lisp

Number To String

;; common-lisp
(concatenate 'string "value: " (princ-to-string 8)) ;;=> "value: 8"
;; racket
(string-append  "value: "  (number->string 8))
;; clojure
(str "Value: " 8)
;; emacs-lisp 这里要注意转换为字符串才可以拼接
(concat  "value: "  (number-to-string 8))

String To Number

;; common-lisp
(+ 7 (parse-integer "12")) ;;=> 19 (5 bits, #x13, #o23, #b10011)
(+ 73.9 (read-from-string ".037") #|输出=> 0.037, 4|#) ;;=> 73.937004
;; racket
(+ 7 (string->number "12"))
(+ 73.9 (string->number ".037"))
;; clojure
(+ 7 (Integer/parseInt "12"))
(+ 73.9 (Float/parseFloat ".037"))
;; emacs-lisp
(+ 7 (string-to-number "12"))
(+ 73.9 (string-to-number ".037"))

Split

;; common-lisp
(cl-ppcre:split "[ \t\n]+" "foo bar baz") ;; 必须要安装包=> Package CL-PPCRE does not exist.
;; racket
(regexp-split #rx"[ \n\t]+"  "foo bar baz")
;; clojure
(seq  (.split "foo bar baz"    "[ \t\n]+"))
;; emacs-lisp 这里可以按照正则表达式来切割
(split-string "foo bar baz")

String Join

;; common-lisp reduce累加的字符串
(reduce (lambda (m o) (concatenate 'string m " " o)) '("foo" "bar" "baz")) ;;=> "foo bar baz"
;; racket
(string-join  '("foo" "bar" "baz")  " ")
;; clojure
(reduce #(str %1 " " %2)  '("foo" "bar" "baz"))
;; emacs-lisp ruby's inject 求字符串的积分
(reduce (lambda (m o) (concat m "_" o)) '("foo" "bar" "baz")) ; "foo_bar_baz"

Length

;; common-lisp
(length "foo") ;;=> 3 (2 bits, #x3, #o3, #b11)
;; racket
(string-length "foo")
;; clojure
(.length "foo")
;; emacs-lisp
(length "foo")

Index Of Substring

;; common-lisp
(search "bar" "foo bar") ;;=> 4 (3 bits, #x4, #o4, #b100)
;; racket
racket:
(require srfi/13/string)
(string-contains "foo bar" "bar")
;; clojure
(.indexOf "foo bar" "bar")
;; emacs-lisp 搜索得到一个数字,说明是存在的,并且知道它所在的位置
(search "bar" "foo bar") ; 4

Extract Substring

;; common-lisp
(subseq "foo bar" 4 7)
;; racket
(substring "foo bar" 4 7)
;; clojure
(.substring "foo bar" 4 7)
;; emacs-lisp 根据位置来拿到字符串
(substring "foo bar" 4 7)

Character Literal

;; common-lisp
#\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\rubout
;; racket
#\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\nul #\vtab #\alarm #\esc #\deletenot in racket: #\alarm #\esc #\delete
;; clojure
\a \newline \space \backspace \tab ? \formfeed \return ?
;; emacs-lisp 一些特殊的字符串
?a ?\b ?\t ?\n ?\f ?\r ?\" ?\\ ?\ooo ?\uhhhh ?\xh - ?\xhhhhhh ?\C-x ?\M-x

Test Characters

;; common-lisp
(characterp #\x)
(alpha-char-p #\x)
(alphanumericp #\x)
(digit-char-p #\7)
(lower-case-p #\x)
(upper-case-p #\X)
;; racket
(char? #\x)
;; clojure
(char? \x)
;; emacs-lisp 这里的问号是代表什么东西呢, char
(characterp ?x) ; t

Chr And Ord

;; common-lisp
(code-char 97)
(char-code #\a)
;; racket
(integer->char 97)
(char->integer #\a)
;; clojure
(char 97)
(int \a)
;; emacs-lisp

To Array Of Characters

;; common-lisp
;; racket
; list:
(string->list "foo")
;; clojure
;; emacs-lisp

Character Lookup

;; common-lisp
(char "foo" 0)
;; racket
(string-ref "foo" 0)
;; clojure
(.charAt "foo" 0)
;; emacs-lisp 这里的应该是不同于环境查找变量
(aref "foo" 2) ; 0 => 102, 2 => 111

Literal

;; common-lisp
use a string:
"\\b\\d{5}\\b"
;; racket
posix extended:
#rx"^[0-9][0-9][0-9][0-9][0-9]$"
(regexp "^[0-9][0-9][0-9][0-9][0-9]$")perl style:
#px"\\b\\d{5}\\b"
(pregexp "\\b\\d{5}\\b")
;; clojure
#"\b\d{5}\b"
;; emacs-lisp

Character Class Abbrevations

;; common-lisp
. \d \D \s \S \w \W
;; racket
regexp:
.pregexp:
. \d \D \s \S \w \W
;; clojure
. \d \D \s \S \w \W
;; emacs-lisp
. \w \W \ca \cl \cg \Ca \Cl \Cg \sx\ca \cl and \cg match ASCII, Latin, and Greek characters.Character classes of the form \sx depend on the current syntax table.

Anchors

;; common-lisp
^ $ \b \B
;; racket
regexp:
^ $pregexp:
^ $ \b \B
;; clojure
^ $ \A \b \B \G \z \Z
;; emacs-lisp
^ $ \b \B

Match Test

;; common-lisp
(ql:quickload "cl-ppcre")
(if (cl-ppcre:all-matches "1999" s)  (format t "party!"))
;; racket
(regexp-match #rx"bar" "foo bar")
;; clojure
(re-find #"bar" "foo bar")
;; emacs-lisp 这里就像红宝石的 =~
(string-match "bar" "foo bar")

Case Insensitive Match Test

;; common-lisp
;; racket
(regexp-match #px"(?i:lorem)" "Lorem")
;; clojure
(re-find #"(?i:lorem)" "Lorem")
;; emacs-lisp

Substitution

;; common-lisp
(cl-ppcre:regex-replace "[^l]l"  "hello"  "EL")
(cl-ppcre:regex-replace-all "[^l]l"  "hello hello"  "EL")
;; racket
(regexp-replace #rx"el"  "hello"  "EL")
(regexp-replace* #rx"el"  "hello hello"  "EL")
;; clojure
(.replaceFirst "hello" "[^l]l" "XX")
(.replaceAll "hello hello"  "[^l]l" "XX")
;; emacs-lisp 这里就像红宝石的gsub
?
(replace-regexp-in-string "[^l]l"  "EL"  "hello hello")

Group Capture

;; common-lisp
;; racket
(match (regexp-match    #px"(\\d{4})-(\\d{2})-(\\d{2})"    "2010-06-03")  [(list s yr mn dy) (list yr mn dy)])
;; clojure
(let [[_ yr mn dy]    (re-find #"(\d{4})-(\d{2})-(\d{2})"      "2010-06-03")]  yr)
;; emacs-lisp

Scan

;; common-lisp
;; racket
;; clojure
(re-seq #"\w+" "dolor sit amet")
;; emacs-lisp

Backreference In Match And Substitution

;; common-lisp
;; racket
(regexp-match #px"(\\w+) \\1" "do do")
(regexp-replace #px"(\\w+) (\\w+)"  "do re"  "\\2 \\1")
;; clojure
;; emacs-lisp

Broken Down Datetime Type

;; common-lisp
No dedicated type; a list of 9 values is used:  second: 0-59  minute: 0-59  hour: 0-23  day of month: 1-31  month: 1-12  year: 4 digits  day of week: 0-6 for Mon-Sun  is daylight savings time: t or nil  timezone: negated UTC offset in hours
;; racket
;; clojure
;; emacs-lisp

Current Datetime

;; common-lisp
(get-decoded-time)
;; racket
(require racket/date)
(current-date)
;; clojure
(def dt (new java.util.Date))
;; emacs-lisp 可以通过时间的先后顺序来判断运算,逻辑的先后顺序
(current-time)

Current Unix Epoch

;; common-lisp
gray|; seconds since Jan 1, 1900:##
(get-universal-time)
;; racket
(current-seconds)
;; clojure
(/ (System/currentTimeMillis) 1000.0)
;; emacs-lisp
(float-time)

Unix Epoch To Broken Down Datetime

;; common-lisp
(decode-universal-time  (get-unversal-time))
;; racket
(seconds->date (current-seconds))
;; clojure
(def dt (new java.util.Date    (System/currentTimeMillis)))
;; emacs-lisp
(seconds-to-time (float-time))

Broken Down Datetime To Unix Epoch

;; common-lisp
(encode-universal-time 0 22 10 31 5 2015)
;; racket
(require racket/date)
(date->seconds (current-date))
;; clojure
(/ (.getTime (new java.util.Date)) 1000.0)
;; emacs-lisp
(multiple-value-bind (b s)  (current-time)  (+ (* b (expt 2 16)) s))

Format Datetime

;; common-lisp
;; racket
;; clojure
(def s "yyyy-MM-dd HH:mm:ss")
(def fmt (new java.text.SimpleDateFormat s))
(.format fmt (new java.util.Date))
;; emacs-lisp
(format-time-string  "%Y-%m-%d %H:%M:%S"  (current-time))

Parse Datetime

;; common-lisp
;; racket
(require (prefix-in s19. srfi/19))
(define (date-str->unix-time s fmt)    (s19.time-second      (s19.date->time-utc        (s19.string->date s fmt))))
(date-str->unix-time  "2015-05-31 07:06:00"  "~Y-~m-~d ~H:~M:~S")
;; clojure
(def s "yyyy-MM-dd HH:mm:ss")
(def fmt (new java.text.SimpleDateFormat s))
(.parse fmt "2015-05-30 09:14:14")
;; emacs-lisp

Date Parts

;; common-lisp
(multiple-value-bind  (ss mi hr dy mo yr)  (get-decoded-time)  (list ss mi hr) ; quiesce warning  (list dy mo yr))
;; racket
(date-year (current-date))
(date-month (current-date))
(date-day (current-date))
;; clojure
(def cal (new java.util.GregorianCalendar))
(.setTime cal dt)
(.get cal java.util.Calendar/DAY_OF_MONTH)
(+ (.get cal java.util.Calendar/MONTH) 1)
(.get cal java.util.Calendar/YEAR)
;; emacs-lisp
(multiple-value-bind  (ss mi hr dy mo yr)   (decode-time (current-time))  (list dy mo yr))

Time Parts

;; common-lisp
(multiple-value-bind  (ss mi hr)  (get-decoded-time)  (list ss mi hr))
;; racket
(date-hour (current-date))
(date-minute (current-date))
(date-second (current-date))
;; clojure
(def cal (new java.util.GregorianCalendar))
(.setTime cal dt)
(.get cal java.util.Calendar/HOUR_OF_DAY)
(.get cal java.util.Calendar/MINUTE)
(.get cal java.util.Calendar/SECOND)
;; emacs-lisp
(multiple-value-bind  (ss mi hr dy mo yr)   (decode-time (current-time))  (list ss mi hr))

Build Broken Down Datetime

;; common-lisp
(encode-universal-time 0 22 10 31 5 2015)
;; racket
;; clojure
(let  [yr 2015 mo 5 dy 31 hr 10 mi 22 ss 0]  (def cal    (new java.util.GregorianCalendar      yr (- mo 1) dy hr mi ss)))
;; emacs-lisp
(encode-time 0 50 8 31 5 2015)

Literal

;; common-lisp
'(1 2 3)
(quote (1 2 3))
;; racket
'(1 2 3)
'[1 2 3]
'{1 2 3}
(quote (1 2 3))
;; clojure
'(1 2 3)
(quote (1 2 3))
;; emacs-lisp
'(1 2 3)
(quote (1 2 3))

Constructor

;; common-lisp
(list 1 2 3)
;; racket
(list 1 2 3)
;; clojure
(list 1 2 3)
;; emacs-lisp
(list 1 2 3)

Predicate

;; common-lisp
(listp '(1 2 3))
;; racket
(list? '(1 2 3))
;; clojure
(list? '(1 2 3))
;; emacs-lisp 判断是不是列表
(listp '(1 2 3))

Empty Test

;; common-lisp
nil and '() are synonyms and evaluate as false in a boolean context. All other values are true.
;; racket
(empty? '())
;; clojure
(empty? ())
;; emacs-lisp
nil and '() are synonyms and evaluate as false in a boolean context. All other values are true.

Evaluating The Empty List

;; common-lisp
nil
;; racket
error
;; clojure
()
;; emacs-lisp
nil

Cons

;; common-lisp
(cons 1 '(2 3))
;; racket
(cons 1 '(2 3))
;; clojure
(cons 1 '(2 3))
;; emacs-lisp 连接列表
(cons 1 '(2 3))

Head

;; common-lisp
(car '(1 2 3))
(first '(1 2 3))
;; racket
(car '(1 2 3))
(first '(1 2 3))
;; clojure
first
;; emacs-lisp 取列表的第一个
car

Tail

;; common-lisp
(cdr '(1 2 3))
(rest '(1 2 3))
;; racket
(cdr '(1 2 3))
(rest '(1 2 3))
;; clojure
(rest '(1 2 3))
(next '(1 2 3))
;; emacs-lisp 取除了第一个列表
(cdr '(1 2 3))
(rest '(1 2 3))

Head And Tail Of Empty List

;; common-lisp
both evaluate to nil
;; racket
error
;; clojure
()
;; emacs-lisp
both evaluate to nil

Length

;; common-lisp
(length '(1 2 3))
;; racket
(length '(1 2 3))
;; clojure
(count '(1 2 3))
;; emacs-lisp
(length '(1 2 3))

Equality Test

;; common-lisp
(equal '(1 2 3) '(1 2 3))
;; racket
(equal? '(1 2 3) '(1 2 3))
;; clojure
(= '(1 2 3) '(1 2 3))
;; emacs-lisp 这里是eq增强版,可以判断整一个列表是不是相同
(equal '(1 2 3) '(1 2 3))

Nth Element

;; common-lisp
; indexed from zero:
(nth 2 '(1 2 3 4))
;; racket
(list-ref '(1 2 3 4) 2)
;; clojure
(nth '(1 2 3 4) 2)
;; emacs-lisp 直接根据列表的位置去取,和clojure一样的
(nth 2 '(1 2 3 4))

Out Of Bounds Behavior

;; common-lisp
nil
;; racket
error
;; clojure
raises IndexOutOfBoundsException
;; emacs-lisp
nil

Element Index

;; common-lisp
(position 7 '(5 6 7 8))
;; racket
(require srfi/1)
(list-index (lambda (x) (= x 7)) '(5 6 7 8))
;; clojure
none
;; emacs-lisp 根据值来得到位置所在
(position 7 '(5 6 7 8)) ; 2

Concatenate

;; common-lisp
(append '(1 2 3) '(4 5 6))
;; racket
(append '(1 2 3) '(4 5 6))
;; clojure
(concat '(1 2 3) '(4 5 6))
;; emacs-lisp 拼接两个大的列表
(append '(1 2 3) '(4 5 6)) ; ( 1 2 3 4 5 6)

Take

;; common-lisp
none
;; racket
(take '(1 2 3 4) 2)
;; clojure
(take 2 '(1 2 3 4))
;; emacs-lisp
none

Drop

;; common-lisp
(nthcdr 2 '(1 2 3 4))
;; racket
(drop '(1 2 3 4) 2)
;; clojure
(drop 2 '(1 2 3 4))
;; emacs-lisp 切割部分列表
(nthcdr 2 '(1 2 3 4)) ; (3 4)

Last Element

;; common-lisp
(car (last '(1 2 3)))
;; racket
(last '(1 2 3))
;; clojure
(last '(1 2 3))
;; emacs-lisp first对应的last
(car (last '(1 2 3)))

All But Last Element

;; common-lisp
(butlast '(1 2 3))
;; racket
(define a '(1 2 3))
(take a (- (length a) 1))
;; clojure
(butlast '(1 2 3))
;; emacs-lisp 对应的rest
(butlast '(1 2 3)) ; (2 3)

Reverse

;; common-lisp
(reverse '(1 2 3))
;; racket
(reverse '(1 2 3))
;; clojure
(reverse '(1 2 3))
;; emacs-lisp
(reverse '(1 2 3))

Sort

;; common-lisp
(sort '(3 2 4 1) '<)
;; racket
(sort '(3 2 4 1) <)
;; clojure
(sort < '(3 2 4 1))
;; emacs-lisp
(sort '(3 2 4 1) '<)

Dedupe

;; common-lisp
(remove-duplicates '(1 1 2 3))
;; racket
(remove-duplicates '(1 1 2 3))
;; clojure
;; emacs-lisp, uniq
(remove-duplicates '(1 1 2 3))

Membership

;; common-lisp
(member 7 '(1 2 3))
;; racket
(member 7 '(1 2 3))
;; clojure
;; emacs-lisp ??? ====
(member 7 '(2 2 3)) ;nil

Map

;; common-lisp
(mapcar  (lambda (x) (* x x))  '(1 2 3))
;; racket
(map (lambda (x) (* x x)) '(1 2 3))
;; clojure
(map #(* % %) '(1 2 3))
;; emacs-lisp , mapcar is c code
;; (-map (lambda (x) (* x x))  '(1 2 3)) ;; dash
(mapcar  (lambda (x) (* x x))  '(1 2 3)) ;; (1 4 9)

Filter

;; common-lisp
(remove-if-not  (lambda (x) (> x 2))  '(1 2 3)); remove-if returns complement
;; racket
(filter  (lambda (x) (> x 2))  '(1 2 3)); filter-not returns complement
;; clojure
(filter #(> % 2) '(1 2 3)); remove returns complement
;; emacs-lisp, ruby select
(remove-if-not  (lambda (x) (> x 2))  '(1 2 3)); remove-if returns complement

Reduce

;; common-lisp
(reduce '-  '(1 2 3 4)  :initial-value 0)
;; racket
(foldl (lambda (x y) (- y x)) 0 '(1 2 3 4))
;; clojure
(reduce - 0 '(1 2 3 4))
;; emacs-lisp
(reduce '-  '(1 2 3 4)  :initial-value 0) ; -10

Right Fold

;; common-lisp
(reduce '-  '(1 2 3 4)  :initial-value 0  :from-end t)
;; racket
(foldr - 0 '(1 2 3 4))
;; clojure
none
;; emacs-lisp
(reduce '-  '(1 2 3 4)  :initial-value 0  :from-end t) ;; -2

Iterate

;; common-lisp
(dolist (x '(1 2 3))  (print x)  (print (- x)))
;; racket
(for ((x '(1 2 3)))  (printf "~a~n" x)  (printf "~a~n" (- x)))
;; clojure
(doseq [x '(1 2 3)]  (println x)  (println (- x)))
;; emacs-lisp
(dolist (x '(1 2 3))  (print x)  (print (- x))) ;; doseq

Universal Predicate

;; common-lisp
(every  (lambda (i) (= 0 (rem i 2)))  '(1 2 3 4))
;; racket
(for/and ((i '(1 2 3 4)))  (= 0 (remainder i 2)))
;; clojure
(every? #(= 0 (rem % 2)) '(1 2 3 4))
;; emacs-lisp
(every  (lambda (i) (= 0 (% i 2)))  '(1 2 3 4))

Existential Predicate

;; common-lisp
(some  (lambda (i) (= 0 (rem i 2)))  '(1 2 3 4))
;; racket
(for/or ((i '(1 2 3 4)))  (= 0 (remainder i 2)))
;; clojure
(some #(= 0 (rem % 2)) '(1 2 3 4))
;; emacs-lisp
(some  (lambda (i) (= 0 (% i 2)))  '(1 2 3 4)) ; t

List Comprehension

;; common-lisp
;; racket
(for*/list  ((file "ABCDEFGH") (rank (in-range 1 9)))  (format "~a~a" file rank))
;; clojure
(for  [file "ABCDEFGH" rank (range 1 9)]  (format "%c%d" file rank))
;; emacs-lisp

Shuffle

;; common-lisp
;; racket
(shuffle '(1 2 3 4))
;; clojure
(shuffle '(1 2 3 4))
;; emacs-lisp

Set Head

;; common-lisp
(defparameter *a* '(1 2 3))
(setf (car *a*) 3)
;; racket
(require schema/mpair)
(define a (mlist 1 2 3))
(set-mcar! a 3)
;; clojure
none
;; emacs-lisp
(setq a '(1 2 6 4 5))
(setcar a 3) ; 3, (3 2 7 4 5)

Set Tail

;; common-lisp
(defparameter *a* '(1 2 3))
(setf (cdr *a*) '(4 5 6))
;; racket
(require schema/mpair)
(define a (mlist 1 2 3))
(set-mcdr! a (mlist 4 5 6))
;; clojure
none
;; emacs-lisp
(setq a '(1 2 3)
(setcar a 3)
(setcdr a '(4 5 6))

Manipulate Back

;; common-lisp
(defparameter *a* '(1 2 3))
(push 4 *a*)
(pop *a*)
;; racket
none
;; clojure
;; emacs-lisp
(setq a '(1 2 3))
(push 4 a)
(pop a)

Flatten

;; common-lisp
;; racket
(flatten '(1 2 (3 (4))))
;; clojure
(flatten '(1 2 (3 (4))))
;; emacs-lisp

Associative Array Lookup

;; common-lisp
(assoc 3 '((1 2) (3 4)))
;; racket
(assoc 3 '((1 2) (3 4)))
;; clojure
none, see note
;; emacs-lisp
(assoc 3 '((1 2) (3 4)))

Flat Associative Array Lookup

;; common-lisp
(getf '(1 2 3 4) 3)
;; racket
none
;; clojure
none
;; emacs-lisp
(getf '(1 2 3 4) 3)

Pair Literal

;; common-lisp
'(1 . 2)
;; racket
'(1 . 2)
;; clojure
none
;; emacs-lisp
'(1 . 2)

Cons Cell Test

;; common-lisp
(cons '(1 . 2))
(not (atom '(1 . 2)))
;; racket
(cons? '(1 . 2))
(pair? '(1 . 2))
;; clojure
none
;; emacs-lisp
(cons '(1 . 2))
(not (atom '(1 . 2)))

Translate Elements Recursively

;; common-lisp
(sublis '((1 . 2) (3 . 4))  '(1 (3 3 (1))))
;; racket
;; clojure
;; emacs-lisp
(sublis '((1 . 2) (3 . 4))  '(1 (3 3 (1))))

Literal

;; common-lisp
#(1 2 3)
;; racket
#(1 2 3)
;; clojure
[1 2 3]
;; emacs-lisp
[1 2 3]

Constructor

;; common-lisp
(vector 1 2 3)
;; racket
(vector 1 2 3)
;; clojure
(vector 1 2 3)
;; emacs-lisp
(vector 1 2 3)

Size

;; common-lisp
(length #(1 2 3))
;; racket
(vector-length #(1 2 3))
;; clojure
(count [1 2 3])
;; emacs-lisp
(length [1 2 3])

Lookup

;; common-lisp
(elt #(1 2 3) 0) or
(aref #(1 2 3) 0)
;; racket
(vector-ref #(1 2 3) 0)
;; clojure
(nth [1 2 3] 0)
;; emacs-lisp
(elt [1 2 3] 0)

Update

;; common-lisp
(setq v [1 2 3])
(setf (aref v 2) 4)
;; racket
(define v (vector 1 2 3))
(vector-set! v 2 4)
;; clojure
(replace {2 4} [1 2 3])
;; emacs-lisp
(setq v #(1 2 3))
(setf (aref v 2) 4)

Out Of Bounds Behavior

;; common-lisp
raises sb-kernel:index-too-large-error
;; racket
error
;; clojure
;; emacs-lisp

Array To List

;; common-lisp
(coerce #(1 2 3) 'list)
;; racket
(vector->list #(1 2 3))
;; clojure
(seq [1 2 3])
;; emacs-lisp
(coerce [1 2 3] 'list)

List To Array

;; common-lisp
(coerce '(1 2 3) 'vector)
;; racket
(list->vector '(1 2 3))
;; clojure
(vec '(1 2 3))
;; emacs-lisp
(coerce '(1 2 3) 'vector)

Reverse

;; common-lisp
(reverse #(1 2 3))
;; racket
;; clojure
;; emacs-lisp

Sort

;; common-lisp
(sort #(2 4 1 3) #'<)
;; racket
;; clojure
;; emacs-lisp

Map

;; common-lisp
(map 'vector (lambda (x) (* x x)) #(1 2 3))
;; racket
;; clojure
;; emacs-lisp

Filter

;; common-lisp
(remove-if-not (lambda (x) (> x 2)) #(1 2 3)); also remove-if
;; racket
;; clojure
;; emacs-lisp

Reduce

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Literal

;; common-lisp
none
;; racket
; immutable:
#hash(("t" . 1) ("f" . 0))
;; clojure
; clojure.lang.PersistentArrayMap:
{"t" 1 "f" 0}
;; emacs-lisp
none

Constructor

;; common-lisp
(defparameter *h* (make-hash-table :test 'equal)); default equality test is 'eql
;; racket
(define ih  (make-immutable-hash    '(("t" . 1) ("f" . 0)))); mutable:
(define h (make-hash '(("t" . 1) ("f" . 0))))
;; clojure
; immutable:
(def ih (hash-map "t" 1 "f" 0))
;; emacs-lisp
(setq h (make-hash-table :test 'equal))

Predicate

;; common-lisp
(hash-table-p *h*)
;; racket
(hash? h); also true of assoc. lists and vectors:
(dict? h)
;; clojure
(map? ih)
;; emacs-lisp
(hash-table-p h)

Size

;; common-lisp
(hash-table-count *h*)
;; racket
(hash-count h); also works with assoc lists and vectors:
(dict-count ih)
;; clojure
(count ih)
;; emacs-lisp
(hash-table-count h)

Lookup

;; common-lisp
(gethash "t" *h*)
;; racket
(hash-ref h "t"); return -1 if not found:
(hash-ref h "m" -1); also works with assoc. lists and vectors:
(dict-ref ih "t")
(dict-ref ih "m" -1)
;; clojure
(get ih "t")
(find ih "t"); return -1 if not found:
(get ih "m" -1)
;; emacs-lisp
(gethash "t" h)

Update

;; common-lisp
(setf (gethash "t" *h*) 1)
;; racket
(hash-set! h "t" 2)
(define ih2 (hash-set ih "t" 2)); also dict-set! and dict-set
;; clojure
(def ih2 (assoc ih "t" 2))
;; emacs-lisp
(puthash "t" 1 h)

Missing Key Behavior

;; common-lisp
returns nil
;; racket
error
;; clojure
returns nil
;; emacs-lisp
returns nil

Is Key Present

;; common-lisp
(nth-value 1 (gethash "t" *h*))
;; racket
(hash-has-key? h "t"); also dict-has-key?
;; clojure
(contains? ih "t")
;; emacs-lisp
none

Delete

;; common-lisp
(remhash "t" *h*)
;; racket
(hash-remove! h "t")
(define ih2  (hash-remove ih "t")); also dict-remove! and dict-remove
;; clojure
(def ih2 (dissoc ih "t"))
;; emacs-lisp
(remhash "hello" h)

Merge

;; common-lisp
;; racket
;; clojure
; values in ih2 take precedence:
(define ih3 (merge ih ih2))
;; emacs-lisp

Invert

;; common-lisp
;; racket
;; clojure
(require 'clojure.set)
(define ih4 (clojure.set/map-invert ih))
;; emacs-lisp

Iterate

;; common-lisp
(maphash  (lambda (k v)    (print k)    (print v))  *h*)
;; racket
(hash-for-each h  (lambda (k v)    (printf "~a~n" k)    (printf "~a~n" v))); also dict-for-each
;; clojure
(doseq [p ih]  (println (first p))  (println (second p)))
;; emacs-lisp
(maphash  (lambda (k v)    (print k)    (print v))  h)

Keys And Values As Lists

;; common-lisp
none
;; racket
(hash-keys h)
(hash-values h); also dict-keys and dict-values
;; clojure
(def hkeys (map (fn [p] (first p)) ih))
(def hvals (map (fn [p] (second p)) ih))
;; emacs-lisp
none

Defstruct

;; common-lisp
(defstruct account id balance)
;; racket
(define-struct account (id (balance #:mutable)))
;; clojure
(defstruct account :id :balance)
;; emacs-lisp
(defstruct account id balance)

Struct

;; common-lisp
(setq a  (make-account    :id 3    :balance 17.12))
;; racket
(define a (make-account 3 17.12))
;; clojure
(def a (struct account 3 17.12))
;; emacs-lisp
(setq a  (make-account :id 3 :balance 17.12))

Struct Getter

;; common-lisp
(account-id a)
;; racket
(account-id a)
;; clojure
(:id a)
;; emacs-lisp
(account-id a)

Struct Setter

;; common-lisp
(setf (account-balance a) 0)
;; racket
(set-account-balance! a 0)
;; clojure
none
;; emacs-lisp
(setf (account-balance a) 0)

Struct Predicate

;; common-lisp
(account-p a)
;; racket
(account? a)
;; clojure
none
;; emacs-lisp
(account-p a)

Define Function

;; common-lisp
(defun add (x y) (+ x y))
;; racket
(define (add x y) (+ x y))
;; clojure
(defn add [x y] (+ x y))
;; emacs-lisp
(defun add (x y) (+ x y))

Can Function And Variable Share Name

;; common-lisp
yes
;; racket
no
;; clojure
no
;; emacs-lisp
yes

Optional Argument

;; common-lisp
(defun add (a &optional b)  (if (null b) a (+ a b)))
;; racket
(define (add a (b null))  (if (null? b) a (+ a b)))
;; clojure
(defn add ([a] a) ([a b] (+ a b)))no syntax error if called with more than 2 args:
(defn add [a & [b]]  (if (nil? b) a (+ a b)))
;; emacs-lisp
(defun add (a &optional b)  (if (null b) a (+ a b))) ;; like ruby *args
(add 1) ; 1
(add 1 2) ; 2

Variable Number Of Arguments

;; common-lisp
(defun add (a &rest b)  (if (null b)    a    (+ a (eval (cons '+ b)))))
;; racket
(define (add a . b)  (if (null? b)    a    (+ a (apply + b))))
;; clojure
(defn add [a & b]  (if (nil? b) a (+ a (apply + b))))
;; emacs-lisp
(defun add (a &rest b)  (if (null b)    a    (+ a (eval (cons '+ b)))))
(add 1) ; 1
(add 1 2) ; 3

Default Value

;; common-lisp
(defun add (a &optional (b 0))  (+ a b))
;; racket
racket:
(define (add a (b 0)) (+ a b))
;; clojure
(defn add  ([a] (add a 0))  ([a b] (+ a b)))
;; emacs-lisp
none

Named Parameter

;; common-lisp
(defun logarithm (&key number base)  (/ (log number) (log base)))
(logarithm :base 2 :number 8)
;; racket
none
;; clojure
(defn logarithm [{x :number b :base}] (/ (Math/log x) (Math/log b)))
(logarithm {:base 2 :number 8})
;; emacs-lisp
(defun logarithm  (&key number &key base)  (if base    (/ (log number) (log base))    (log number))) order significant, not key names:
(logarithm :foo 8 :bar 2)

Return Multiple Values

;; common-lisp
(defun sqrts (x)  (values (sqrt x) (- (sqrt x))))
;; racket
(define (sqrts x)  (values (sqrt x) (- (sqrt x))))
;; clojure
(defn sqrts [x] (list (Math/sqrt x) (- (Math/sqrt x))))
;; emacs-lisp
values creates a list:
(defun sqrts (x)  (values (sqrt x) (- (sqrt x))))

Assign Multiple Values To Local Variables

;; common-lisp
(multiple-value-bind (r1 r2)  (sqrts 3)  r2)
;; racket
(let-values  (((r1 r2) (sqrts 3)))  r2)
;; clojure
(let [[r1 r2] (sqrts 3)] r2)
;; emacs-lisp
(multiple-value-bind  (r1 r2)  (sqrts 3)  r2)

Assign Multiple Values To Global Variables

;; common-lisp
(multiple-value-setq (r1 r2)  (sqrts 3))
;; racket
(define-values (r1 r2) (sqrts 3))
;; clojure
none
;; emacs-lisp
(multiple-value-setq (r1 r2) (sqrts 3))

Convert List To Multiple Values

;; common-lisp
(values-list '(1 2 3))
;; racket
(apply values '(1 2 3))
;; clojure
multiple values are lists
;; emacs-lisp
multiple values are lists

Assign Multiple Values To List

;; common-lisp
(multiple-value-list (sqrts 3))
;; racket
(call-with-values  (lambda () (sqrts 3))  list)
;; clojure
multiple values are lists
;; emacs-lisp
multiple values are lists

Tail Call Optimization

;; common-lisp
yes for sbcl
;; racket
yes
;; clojure
yes with recur
;; emacs-lisp
no

Lambda

;; common-lisp
(lambda (x) (* x x))
;; racket
(lambda (x) (* x x))
;; clojure
#(* % %)
(fn [x] (* x x)); shortcut notation with two args:
#(* %1 %2)
;; emacs-lisp
(lambda (x) (* x x))

Apply

;; common-lisp
((lambda (x) (* x x)) 2)
(apply #'(lambda (x) (* x x)) '(2))
;; racket
((lambda (x) (* x x)) 2)
(apply (lambda (x) (* x x)) '(2))
;; clojure
(#(* % %) 2)
((fn [x] (* x x)) 2)
(apply #(* % %) '(2))
;; emacs-lisp
((lambda (x) (* x x)) 2)
(apply  #'(lambda (x) (* x x))  '(2))

Progn

;; common-lisp
progn prog1 prog2
;; racket
begin none noner6rs:
begin begin0 none
;; clojure
do none none
;; emacs-lisp
progn prog1 prog2

Loop

;; common-lisp
(setq i 1)
(loop (print "hello")  (if (> i 10)    (return)    (setq i (+ i 1))))
;; racket
none, use recursion
;; clojure
(loop [i 1]  (if (<= i 10)      (do (println "hello")          (recur (+ i 1)))))
;; emacs-lisp
(setq i 1)
(loop (print "hello")      (if (> i 10)          (return)          (setq i (+ i 1))))

Do

;; common-lisp
(do ((i 1) (sum 0))  ((> i 100) sum)  (setq sum (+ sum i))  (setq i (+ i 1)))do* initializes serially
;; racket
none
;; clojure
none
;; emacs-lisp
(do ((i 1) (sum 0))    ((> i 100) sum)    (setq sum (+ sum i))    (setq i (+ i 1)))do* initializes sequentially

Dotimes

;; common-lisp
(dotimes (i 10 nil)  (format t "hello~%"))
;; racket
none
;; clojure
(dotimes [_ 10]  (println "hello"))
;; emacs-lisp
(dotimes (i 10 nil)  (print "hello\n"))

If

;; common-lisp
(if (< x 0) (- x) x)
;; racket
(if (< x 0) (- x) x)
;; clojure
(if (< x 0) (- x) x)
;; emacs-lisp
(if (< x 0) (- x) x)

When

;; common-lisp
(when (< x y)  (print "x is less ")  (print "than y"))
;; racket
racket:
(when (< x y)  (display "x is less ")  (display "than y"))
;; clojure
(when (< x y)  (println "x is less ")  (println "than y"))
;; emacs-lisp
(when (< x y)  (print "x is less ")  (print "than y"))

Cond

;; common-lisp
(cond ((> x 0) 1)  ((= x 0) 0)  (t -1))
;; racket
(cond ((> x 0) 1)  ((= x 0) 0)  (else -1))
;; clojure
(cond (> x 0) 1  (= x 0) 0  true -1)
;; emacs-lisp
(cond ((> x 0) 1)  ((= x 0) 0)  (t -1))

Lazy Evaluation

;; common-lisp
;; racket
(define x (delay (/ 1 0)))
(promise? x)
(+ 1 (force x))
;; clojure
;; emacs-lisp

Continuations

;; common-lisp
;; racket
(define cc null)
(+ 1 (call/cc (lambda (x) (set! cc x) 0)))
(cc 5)
;; clojure
;; emacs-lisp

Error

;; common-lisp
(error "failed")
;; racket
(error "failed")
;; clojure
(throw (Exception. "failed"))
;; emacs-lisp
(error "failed")

Handle Error

;; common-lisp
(handler-case  (error "failed")  (simple-error (e)    (format t "error: ~a" e)))
;; racket
(with-handlers  ((exn:fail?     (lambda (e)       (printf "error: ~a"         (exn-message e)))))  (error "failed"))
;; clojure
(try (throw (Exception. "failure"))  (catch Exception e    (printf "error: %s"      (.getMessage e))))
;; emacs-lisp
(condition-case e  (error "failed")  (error (message "error: %s"    (error-message-string e))))

Define Exception

;; common-lisp
(define-condition odd-err (error)  ((num :accessor odd-err-num        :initarg :num))  (:report    (lambda (e s)      (format s "odd number: ~a"        (odd-err-num e)))))
;; racket
(define exn:odd-err? "odd number")
;; clojure
;; emacs-lisp
only symbols and keywords can be thrown and caught

Throw Exception

;; common-lisp
(error 'odd-err :num 7)
;; racket
(raise exn:odd-err?)
;; clojure
(throw (Exception. "failed"))
;; emacs-lisp
(throw 'odd-err t)

Catch Exception

;; common-lisp
(handler-case (/ 1 0)  (division-by-zero ()    (progn      (format t "division by zero")      nil)))
;; racket
(with-handlers ((exn:fail? (lambda (e) (begin (printf "division by zero~n") null)))) (/ 1 0))
;; clojure
(try (/ 1 0) (catch ArithmeticException _ (do (println "division by zero") nil)))
;; emacs-lisp
(catch 'failed (throw 'failed nil) t)

Restart Case

;; common-lisp
(defun halve (l)  (mapcar (lambda (x)    (restart-case      (if (= (rem x 2) 0) (/ x 2)        (error 'odd-error :num x))      (round-down () (/ (- x 1) 2))      (round-up () (/ (+ x 1) 2)))) l))
;; racket
;; clojure
none
;; emacs-lisp
none

Invoke Restart

;; common-lisp
(handler-bind  ((odd-err      (lambda (c)        (invoke-restart          'round-down))))      (halve '(1 2 4 9)))
;; racket
;; clojure
none
;; emacs-lisp
none

Finally Clause

;; common-lisp
(unwind-protect  (error "failure")  (print "clean up"))
;; racket
none
;; clojure
(try (throw (Exception. "failure"))     (finally (println "clean up")))
;; emacs-lisp
(unwind-protect  (error "failure")  (print "clean up"))

Standard File Handles

;; common-lisp
*standard-input*
*standard-output*
*error-output*
;; racket
(current-input-port)
(current-output-port)
(current-error-port)
;; clojure
*in*
*out*
*err*
;; emacs-lisp

End Of File Behavior

;; common-lisp
read-line returns two values, the 2nd set to T at end-of-file.
EOF-OF-FILE is signaled when reading past end of file.
;; racket
Returns the value eof.Use eof-object? to test for it.
;; clojure
.readLine on a java.io.Reader object returns nil.
;; emacs-lisp

Read Line From Stdin

;; common-lisp
(setq line (read-line))
;; racket
(let ((s (read-line)))  #|use s|#)
;; clojure
(let [s (read-line)]  (comment use s))
;; emacs-lisp

Chomp

;; common-lisp
;; racket
read-line discards newline
;; clojure
read-line discards newline
;; emacs-lisp

Write Line To Stdout

;; common-lisp
(defun println (s)  (format t "~a~%" s))
(println "hello")
;; racket
(write-string s)
(newline)
;; clojure
(println "hello")
;; emacs-lisp

Write Formatted String To Stdout

;; common-lisp
(format t "~s ~d: ~2$~%"  "foo"  7  13.7)
;; racket
(printf "~a ~a: ~a~n"  "foo"  7  (/ (round (* 13.7 100)) 100))
;; clojure
(printf "%s %d %.2f\n" "foo" 7 13.7)
;; emacs-lisp

Open File For Reading

;; common-lisp
(setq in (open "/etc/hosts"))
;; racket
(let  ((f (open-input-file "/etc/hosts")))  #| use f |#)
;; clojure
; f is java.io.Reader object:
(let [f (clojure.java.io/reader "/etc/hosts")]  (.readLine f))
;; emacs-lisp

Open File For Writing

;; common-lisp
(setq out (open "/tmp/test" :direction :output :if-exists :supersede))
;; racket
(let  ((f (open-output-file        "/tmp/foo"        #:exists 'truncate)))  #| use f |#)
;; clojure
; f is java.io.Writer object:
(let [f (clojure.java.io/writer "/tmp/foo")]  (.write f "lorem ipsum\n")  (.close f))
;; emacs-lisp

Open File For Appending

;; common-lisp
(setq out (open "/tmp/test" :direction :output :if-exists :append))
;; racket
(let  ((f (open-output-file        "/tmp/foo"        #:exists 'append)))  #| use f |#)
;; clojure
(let [f (clojure.java.io/writer "/tmp/foo"      :append true)]  (.write f "lorem ipsum\n")  (.close f))
;; emacs-lisp

Close File

;; common-lisp
(close in)
;; racket
(close-input-port f)
(close-output-port f)
;; clojure
(.close f)
;; emacs-lisp

Close File Implicitly

;; common-lisp
(with-open-file (out #P"/tmp/test" :direction :output) (write-line "lorem ipsum" out))
;; racket
(call-with-input-file  "/etc/hosts"  (lambda (f) (#| use f |#)); also call-with-output-file
;; clojure
(with-open [f    (clojure.java.io/reader "/etc/hosts")]  (comment use f))
;; emacs-lisp

Read Line

;; common-lisp
(setq line (read-line f))
;; racket
(define line (read-line in))
;; clojure
(.readLine f)
;; emacs-lisp

Iterate Over File By Line

;; common-lisp
;; racket
(for ([line (in-lines        (open-input-file          "/etc/hosts"))])  (write-string line)  (newline))
;; clojure
(loop [line (.readLine f)]  (if (not= line nil)    (do (println line)      (recur (.readLine f)))))
;; emacs-lisp

Read File Into Array Of Strings

;; common-lisp
;; racket
; to list of strings:
(sequence->list (in-lines    (open-input-file "/etc/hosts")))
;; clojure
(vec (line-seq f))
;; emacs-lisp

Read File Into String

;; common-lisp
;; racket
(define s (file->string "/etc/hosts"))
;; clojure
(let [s (slurp "/etc/hosts")]  (print s))
;; emacs-lisp

Write String

;; common-lisp
;; racket
(write-string s f)
;; clojure
(.write f s)
;; emacs-lisp

Write Line

;; common-lisp
;; racket
(write-string s f)
(newline f)
;; clojure
(.write f (println-str s))
;; emacs-lisp

Flush File Handle

;; common-lisp
;; racket
(flush-output f)
;; clojure
(f .flush)
;; emacs-lisp

File Handle Positionget Set

;; common-lisp
;; racket
; Evaluates to non-negative integer:
(file-position f); Sets next read or write
; to beginning of file:
(file-position f 0)
;; clojure
; arg is characters from current position;
; moving backward not possible:
(.skip f 1000); arg is max characters to buffer:
(.mark f 1000000); move to position saved when .mark was called:
(.rest f)
;; emacs-lisp

In Memory Stream

;; common-lisp
(setq f (make-string-input-stream    "lorem ipsum"))
(read-line f)
(setq f2 (make-string-output-stream)
(write-string "lorem ipsum)
(get-output-stream-string out)
;; racket
(define f (open-input-string "lorem ipsum"))
(read-line f)
(define f2 (open-output-string))
(write-string "lorem ipsum" f2)
(get-output-string f2)
;; clojure
; use *in* to read from string:
(with-in-str "lorem ispum"  (read-line)); use *out* to write to string:
(with-out-str  (println "lorem ipsum"))
;; emacs-lisp

List Buffers

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; list of buffer objects:
(buffer-list);; name of first buffer in list:
(buffer-name (car (buffer-list)));; name of current buffer:
(buffer-name (current-buffer))

Current Bufferget And Set

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; name of current buffer:
(buffer-name (current-buffer));; open in current pane:
(switch-to-buffer "foo.txt");; open in other pane:
(switch-to-buffer-other-window  "bar.txt")

Clear Buffer

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; current buffer:
(erase-buffer);; buffer named "foo.txt:
(with-current-buffer "foo.txt"  (erase-buffer))

Pointget And Set

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; 1-based index of char under cursor:
(point);; go to beginning of current buffer:
(goto-char 1);; go to end of current buffer:
(goto-char (buffer-size))

Search And Set Point

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; Set point to character after string.
;; 1st arg is position in buffer beyond
;;   which search stops.
;; If 2nd arg is true, return nil
;;   on failure, otherwise raise error.
;; 3rd argument is the occurrence
;;   of the string, if negative
;;   search backwards from point.
(search-forward "lorem" nil t 1)

Insert At String Point

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; takes 1 or more args:
(insert "lorem" " ipsum")

Current Buffer As String

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
(buffer-string)

Insert File Contents At Point

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
(insert-file "/etc/passwd")

Markget And Set

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
;; to beginning of current buffer:
(set-mark 1);; to point of current buffer:
(set-mark (point))

File Test Regular File Test

;; common-lisp
(osicat:file-exists-p "/tmp/foo")
(osicat:regular-file-exists-p "/tmp/foo")
;; racket
??
(file-exists? "/etc/hosts")
;; clojure
(.exists (io/file "/etc/hosts"))
;; emacs-lisp
(file-exists-p "/etc/hosts")
(file-regular-p "/etc/hosts")

File Size

;; common-lisp
;; racket
(file-size "/etc/hosts")
;; clojure
(.length (io/file "/etc/hosts"))
;; emacs-lisp
(eighth  (file-attributes "/etc/hosts"))

Is File Readable Writable Executable

;; common-lisp
;; racket
(pair? (filter    (lambda (x) (eq? x 'read))    (file-or-directory-permissions      "/etc/hosts")))
(pair? (filter    (lambda (x) (eq? x 'write))    (file-or-directory-permissions      "/etc/hosts")))
(pair? (filter    (lambda (x) (eq? x 'execute))    (file-or-directory-permissions      "/etc/hosts")))
;; clojure
(.canRead (io/file "/etc/hosts"))
(.canWrite (io/file "/etc/hosts"))
(.canExecute (io/file "/etc/hosts"))
;; emacs-lisp

Set File Permissions

;; common-lisp
;; racket
(file-or-directory-permissions  "/tmp/foo"  #o755)
;; clojure
;; emacs-lisp
(set-file-modes "/tmp/foo" #o755)

Last Modification Time

;; common-lisp
;; racket
(file-or-directory-modify-seconds "/tmp/foo")
;; clojure
; Unix epoch in milliseconds:
(.lastModified (java.io.File. "/tmp/foo"))
;; emacs-lisp

Copy File Remove File Rename File

;; common-lisp
(cl-fad:copy-file #P"/tmp/foo"  #P"/tmp/bar")
(delete-file #P"/tmp/foo")
(rename-file #P"/tmp/bar"  #P"/tmp/foo")
;; racket
(copy-file "/tmp/foo" "/tmp/bar")
(delete-file "/tmp/foo")
(rename-file-or-directory  "/tmp/bar"  "/tmp/foo")
;; clojure
(clojure.java.io/copy  (java.io.File. "/tmp/foo")  (java.io.File. "/tmp/bar"))
(clojure.java.io/delete-file "/tmp/foo")
(.renameTo (java.io.File. "/tmp/bar")  (java.io.File. "/tmp/foo"))
;; emacs-lisp
(copy-file "/tmp/foo" "/tmp/bar")
(delete-file "/tmp/foo")
(rename-file "/tmp/bar" "/tmp/foo")

Create Symlink Symlink Test Get Target

;; common-lisp
(osicat:make-link "/tmp/hosts" :target "/etc/hosts")
;; racket
(make-file-or-directory-link  "/etc/hosts"  "/tmp/hosts")
(link-exists? "/tmp/hosts")??
;; clojure
;; emacs-lisp
(make-symbolic-link "/etc/hosts" /tmp/hosts")returns target if symlink or nil:
(file-symlink-p "/tmp/hosts")

Temporary File

;; common-lisp
;; racket
(define tmp (make-temporary-file))
(path->string tmp)
;; clojure
; java.io.File:
(java.io.File/createTempFile "foo" ".txt")
;; emacs-lisp
(make-temp-file "foo")

Build Pathname

;; common-lisp
(make-pathname  :directory '(:absolute "etc")  :name "hosts")
;; racket
; returns path; convert to string
; with path->string:
(build-path "/etc" "hosts")
;; clojure
(require '[clojure.java.io :as io]); returns java.io.File;
; convert to string with .getPath:
(io/file "/etc" "hosts")
;; emacs-lisp

Dirname And Basename

;; common-lisp
(pathname-directory #P"/etc/hosts")
(pathname-name #P"/etc/hosts")
;; racket
(let-values (((dir file _)        (split-path "/etc/hosts")))  #| use dir or file |#)
;; clojure
(require '[clojure.java.io :as io])
(.getParent (io/file "/etc/hosts"))
(.getName (io/file "/etc/hosts"))
;; emacs-lisp
(file-name-directory "/etc/hosts")
(file-name-nondirectory  "/etc/hosts")

Absolute Pathname

;; common-lisp
;; racket
(simplify-path  (path->complete-path ".."))
;; clojure
(.getCanonicalPath (java.io.File. ".."))
;; emacs-lisp
(expand-file-name "..")

Iterate Over Directory By File

;; common-lisp
(dolist (file (osicat:list-directory "/tmp")) (format t "~a~%" file))
;; racket
(for ([path (directory-list "/etc")])  (write-string    (path->string path)))
;; clojure
; file-seq returns java.io.File objects for files
; in arg directory and any subdirs recursively.
(filter #(= (.getParent %) "/etc")  (file-seq (clojure.java.io/file "/etc")))
;; emacs-lisp
(dolist  (file (directory-files "/etc"))  (print file)))

Make Directory

;; common-lisp
;; racket
(make-directory* "/tmp/foo/bar")
;; clojure
(require '[clojure.java.io :as io])
(.mkdir (io/file "/tmp/foo"))
;; emacs-lisp
creates parents if 2nd arg non-nil:
(make-directory "/tmp/foo/bar" t)

Recursive Copy

;; common-lisp
;; racket
(copy-directory/files "/tmp/foo.d"  "/tmp/bar.d")
;; clojure
;; emacs-lisp

Remove Empty Directory

;; common-lisp
(delete-directory "/tmp/foo.d")
;; racket
(delete-directory "/tmp/foo.d")
;; clojure
(clojure.java.io/delete-file "/tmp/foo.d")
;; emacs-lisp
(delete-directory "/tmp/foo.d")

Remove Directory And Contents

;; common-lisp
(osicat:delete-directory-and-files "/tmp/foo.d")
;; racket
(delete-directory/files "/tmp/foo.d")
;; clojure
;; emacs-lisp
(delete-directory "/tmp/foo.d" t)

Directory Test

;; common-lisp
(osicat:directory-exists-p #P"/etc")
;; racket
(directory-exists? "/etc")
;; clojure
(.isDirectory (io/file "/etc"))
;; emacs-lisp
(file-directory-p "/etc")

Command Line Arguments

;; common-lisp
*posix-argv*
;; racket
current-command-line-arguments
;; clojure
*command-line-args*
;; emacs-lisp
in shebang mode only:
command-line-args or argv

Program Name

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Environment Variables

;; common-lisp
(posix-getenv "HOME")
;; racket
(getenv "HOME")
;; clojure
(System/getenv "HOME")
;; emacs-lisp
(getenv "HOME")

User Id And Name

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Exit

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

External Command

;; common-lisp
(run-program "ls" '( "/etc"))
;; racket
(require scheme/system)
(system "ls /etc")
;; clojure
(.exec (Runtime/getRuntime) "ls")
;; emacs-lisp
(shell-command "ls /etc")

Command Substitution

;; common-lisp
;; racket
;; clojure
;; emacs-lisp
(shell-command-to-string "ls /etc")

Complete Example

;; common-lisp
;; racket
;; clojure
$ cat b/a.clj
(ns b.a)
(def x 3)
$ java -cp clojure.jar:. clojure.main
=> (require 'b.a)
=> b.a/x
3
;; emacs-lisp

Compile Library

;; common-lisp
(compile-file "a.lisp")
;; racket
$ raco make a.rkt
;; clojure
(compile 'a)
;; emacs-lisp
$ emacs -batch -Q -L .  -f batch-byte-compile a.el

Load Library

;; common-lisp
(load "a.lisp")
;; racket
(require a)
;; clojure
(require 'a)
;; emacs-lisp
(require "a")

Load Library In Subdirectory

;; common-lisp
(load "b/a.lisp")
;; racket
(require "b/a.rkt")
;; clojure
(require 'b.a)
;; emacs-lisp

Hot Patch

;; common-lisp
(load "a.lisp")
;; racket
none
;; clojure
(require 'b.a :reload)
;; emacs-lisp
(load "a")

Load Error

;; common-lisp
raises sb-int:simple-file-error
;; racket
raises exn:fail:syntax:missing-module. Because require must be top-level, the exception cannot be handled.
;; clojure
raises FileNotFoundException
;; emacs-lisp
raises file-err

Library Path

;; common-lisp
contains working directory at startup
;; racket
(require setup/dirs)
(get-collects-search-dirs)
;; clojure
same as path used by java VM
;; emacs-lisp
; adds directory to library path:
(add-to-list 'load-path ("/home/ed/.emacs.d/lib"))

Library Path Environment Variable

;; common-lisp
none
;; racket
;; clojure
CLASSPATH
;; emacs-lisp
EMACSLOADPATH

Library Path Command Line Option

;; common-lisp
none
;; racket
;; clojure
$ java -cp /foo/bar:/baz/quux
;; emacs-lisp
$ emacs -L /foo/bar

Namespace Declaration

;; common-lisp
(defpackage :foo)
;; racket
(module mconst racket  (provide pi)  (define pi 3.14))
;; clojure
(ns mconst)
;; emacs-lisp
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

;; common-lisp
none
;; racket
;; clojure
; must be in b/a.clj:
(ns b.a)
;; emacs-lisp

Namespace Separator

;; common-lisp
:
;; racket
:
;; clojure
. and /
;; emacs-lisp

Import Definitions

;; common-lisp
; set current *package* to foo and import symbol twiddle from bar:
(defpackage :foo  (:import-from :bar :twiddle))
;; racket
;; clojure
;; emacs-lisp

Import All Definitions In Namespace

;; common-lisp
; set current *package* to foo and import symbols from bar:
(defpackage :foo  (:use :bar))
;; racket
;; clojure
;; emacs-lisp

Namespace Shadow Avoidance

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Identifier Shadow Avoidance

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Package Manager Help

;; common-lisp
;; racket
$ raco help
$ raco pkg --help
$ raco pkg install --help
;; clojure
;; emacs-lisp

List Installed Packages

;; common-lisp
;; racket
$ raco pkg show --all
;; clojure
;; emacs-lisp
M-x list packages

Search Packages

;; common-lisp
(ql:system-apropos "time")
;; racket
http://pkgs.racket-lang.org
;; clojure
;; emacs-lisp
M-x list-packages

Install Package

;; common-lisp
; install quicklisp
(load "~/quicklisp/setup.lisp")
(ql:quickload "osicat")
;; racket
$ raco pkg install --deps search-auto srfi
;; clojure
;; emacs-lisp
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

;; common-lisp
;; racket
$ raco pkg remove srfi
;; clojure
;; emacs-lisp
In the package menu, use d to select a package to uninstall and x to uninstall it.

Define Class

;; common-lisp
(defclass rectangle ()  (    (height      :accessor rectangle-height      :initarg :height)    (width      :accessor rectangle-width      :initarg :width)))
;; racket
(define rectangle%  (class object%    (init width)    (init height)    (super-new)    (define curr-height height)    (define curr-width width)    (define/public (get-height)      curr-height)    (define/public (get-width)      curr-width)    (define/public (set-height ht)      (set! curr-height ht))    (define/public (set-width wd)      (set! curr-width wd))))
;; clojure
use java:
public class Rectangle {  public float height;  public float width;  public Rectangle(float h, float w) {    this.height = h;    this.width = w;  }  public void setHeight(float h) {    this.height = h;  }  public void setWidth(float w) {    this.width = w;
}
;; emacs-lisp

Make Instance

;; common-lisp
(make-instance 'rectangle  :height 3  :width 7)
;; racket
(define rect  (new rectangle    (height 7)    (width 3)))
;; clojure
(import 'Rectangle)
(def r (Rectangle. 7 3))
;; emacs-lisp

Read Attribute

;; common-lisp
(rectangle-height rect)
;; racket
(send rect get-height)
;; clojure
(.height r)
;; emacs-lisp

Write Attribute

;; common-lisp
(setf (rectangle-height rect) 4)
;; racket
(send rect set-height 4)
;; clojure
(.setHeight r 8)
;; emacs-lisp

Define Method

;; common-lisp
(defmethod area ((figure rectangle))  (* (rectangle-height figure)    (rectangle-width figure)))
;; racket
(define/public (area)  (* curr-height curr-width))
;; clojure
(defmulti area class)
(defmethod area Rectangle [r] (* (.height r) (.width r)))
;; emacs-lisp

Invoke Method

;; common-lisp
(area rect)
;; racket
(send rect area)
;; clojure
(area r)
;; emacs-lisp

Universal Superclass

;; common-lisp
standard-object t
;; racket
object%
;; clojure
Object
;; emacs-lisp

Multiple Inheritance

;; common-lisp
yes
;; racket
no
;; clojure
only one direct superclass; can implement multiple interfaces
;; emacs-lisp

Backquote And Comma

;; common-lisp
(setq op '+)
(eval `(,op 1 1))
;; racket
(define op '+)
(eval `(,op 1 1))
(eval (quasiquote ((unquote op) 1 1)))
;; clojure
(def op +)
(eval `(,op 1 1))
;; emacs-lisp
(setq op '+)
(eval `(,op 1 1))

Defmacro

;; common-lisp
(defmacro rpn (arg1 arg2 op)  (list op arg1 arg2))
;; racket
(define-syntax-rule (rpn arg1 arg2 op) (op arg1 arg2))
;; clojure
(defmacro rpn [arg1 arg2 op]  (list op arg1 arg2))
;; emacs-lisp
(defmacro rpn (arg1 arg2 op)  (list op arg1 arg2))

Defmacro W Backquote

;; common-lisp
(defmacro rpn (arg1 arg2 op)  `(,op ,arg1 ,arg2))
;; racket
(define-syntax-rule (rpn3 arg1 arg2 op)  (eval ‘(,op ,arg1 ,arg2)))
;; clojure
(defmacro rpn [arg1 arg2 op] `(~op ~arg1 ~arg2))
;; emacs-lisp
(defmacro rpn (arg1 arg2 op)  `(,op ,arg1 ,arg2))

Macro Predicate

;; common-lisp
(macro-function rpn)
;; racket
none
;; clojure
none
;; emacs-lisp
none

Macroexpand

;; common-lisp
(macroexpand ’(rpn 1 2 +))
;; racket
(syntax-object->datum (expand-to-top-form '(rpn 1 2 +)))
;; clojure
(macroexpand '(rpn 1 2 +))
;; emacs-lisp
(macroexpand '(rpn 1 2 +))

Splice Quote

;; common-lisp
(defmacro add ( &rest args )  `(+ ,@args))
;; racket
(define-syntax-rule ( add first …) (+ first …))
;; clojure
(defmacro add [ & args ] `(+ ~@args))
;; emacs-lisp
(defmacro add ( &rest args )  `(+ ,@args))

Recursive Macro

;; common-lisp
(defmacro add (a &rest b)  `(if (null ',b)    (+ ,a)    (+ ,a (add ,@b))))
;; racket
(define-syntax add (syntax-rules ()  [(add x) x]  [(add x y) (+ x y)]  [(add x y …) (+ x (add y …))]))
;; clojure
(defmacro add ([a] `(+ ~a)) ([a & b] `(+ ~a (add ~@b))))
;; emacs-lisp
(defmacro add (a &rest b)  `(if (null ',b)    (+ ,a)    (+ ,a (add ,@b))))

Hygienic

;; common-lisp
no
;; racket
yes
;; clojure
with # suffix
;; emacs-lisp
no

Local Values

;; common-lisp
(defmacro square-sum (x y)  (let ((sum (gensym)))    `(let ((,sum (+ ,x ,y)))      (* ,sum ,sum))))
;; racket
(define-syntax-rule (square-sum x y)  (let ((sum (+ x y)))    (* sum sum)))
;; clojure
(defmacro two-list [x] `(let [arg# ~x] (list arg# arg#)))
;; emacs-lisp
(defmacro square-sum (x y)  (let ((sum (gensym)))    `(let ((,sum (+ ,x ,y)))      (* ,sum ,sum))))

Inspect Type

;; common-lisp
(type-of '(1 2 3))
(typep '(1 2 3) 'list)
(listp '(1 2 3))
;; racket
(list? '(1 2 3))
;; clojure
(= (type 1) java.lang.Long)
(= (class 1) java.lang.Long)
(integer? 1)
;; emacs-lisp
(type-of [1 2 3] 'vector)
(typep [1 2 3] 'vector)
(vectorp [1 2 3])

Instance Of

;; common-lisp
;; racket
;; clojure
instance?
;; emacs-lisp

Basic Types

;; common-lisp
logical and numeric:
bignum bit complex double-float fixnum float integer long-float nil null number ratio rational real short-float signed-btye single-float t unsigned-bytesymbols and strings:
base-character character extended-character keyword simple-string standard-char string symboldata structures:
array atom bit-vector cons hash-table list sequence simple-array simple-bit-vector simple-vector vectorother:
compiled-function function package pathname random-state stream
;; racket
;; clojure
;; emacs-lisp

Sequence Data Types

;; common-lisp
list vector
;; racket
list vector hash-table string input-port range
;; clojure
all collections and strings
;; emacs-lisp
list vector

Get Docstring

;; common-lisp
(describe #'mapcar)
;; racket
none
;; clojure
(doc map)
;; emacs-lisp
(describe-function 'mapcar)

Define Function With Docstring

;; common-lisp
(defun add (x y)  "add x and y"  (+ x y))
;; racket
none
;; clojure
(defn add "add x and y" [x y]  (+ x y))
;; emacs-lisp
(defun add (x y)  "add x and y"  (+ x y))

Apropos And Documentation Search

;; common-lisp
none
;; racket
none
;; clojure
(apropos #"^add$")
(find-doc #"add \S+ and \S+")
;; emacs-lisp
(apropos "^add$")none

New

;; common-lisp
;; racket
;; clojure
(def rnd (new java.util.Random))
(def rnd (java.util.Random.))
;; emacs-lisp

Method

;; common-lisp
;; racket
;; clojure
(. rnd nextFloat)
(.nextFloat rnd)
(. rnd nextInt 10)
(.nextInt rnd 10)
;; emacs-lisp

Class Method

;; common-lisp
;; racket
;; clojure
(Math/sqrt 2)
;; emacs-lisp

Chain

;; common-lisp
;; racket
;; clojure
;; emacs-lisp

Import

;; common-lisp
;; racket
;; clojure
(import '(java.util Random))
(def rnd (Random.))
;; emacs-lisp

To Java Array

;; common-lisp
;; racket
;; clojure
(to-array '(1 2 3))
(into-array Integer '(1 2 3))
;; emacs-lisp

About

对比学习Racket/Clojure/EmacsLisp/CommonLisp, 以及基本算法

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published