Comparison
Functional
Haskell, Scheme, Common Lisp and Clojure
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
---|---|---|---|---|
function literal | (\x y -> x^2 + y^2) 3 4 | ((lambda (x y) (+ (* x x) (* y y))) 3 4) | ((lambda (x y) (+ (* x x) (* y y))) 3 4) | ((fn[x y] (+ (* x x) (* y y))) 3 4) |
bind a function literal to a variable | sos = (\x y -> x^2 + y^2) | (define sos (lambda (x y) (+ (* x x) (* y y))) (sos 3 4) -> 25 | (setq sos (lambda (x y) (+ (* x x) (* y y))) | (def sos (fn [x y] (+ (* x x) (* y y))) (sos 3 4) -> 25 |
bind a function literal to a variable in a scope | let sos = (\x y -> x^2 + y^2) in sos 3 4 -> 25 sos 3 4 -> Not in scope: `sos' | (let ((sos (lambda (x y) (+ (* x x) (* y y))))) | (let ((sos (lambda (x y) (+ (* x y) (* y y)))))
| (let [sos (fn [x y] (+ (* x x) (* y y)))] (sos 3 4)) -> 25 (sos 3 4) -> Unable to resolve symbol: sos |
named function | sos x y = x^2 + y^2 | (define (sos x y) (+ (* x x) (* y y))) (sos 3 4) -> 25 | (defun sos (x y) (+ (* x x) (* y y))) (sos 3 4) -> 25 | (defn sos [x y] (+ (* x x) (* y y))) (sos 3 4) -> 25 |
named function in a scope | let sos x y = x^2 + y^2 in | (define-syntax labels | (labels ((sos (x y) (+ (* x x) (* y y)))) | (letfn [(sos [x y] (+ (* x x) (* y y)))] (sos 3 4)) -> 25 |
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
car,head,first (3,1,4,1,5,9,2) -> 3 | head [3,1,4,1,5,9,2] -> 3 | (car '(3 1 4 1 5 9 2)) -> 3 | (car '(3 1 4 1 5 9 2)) -> 3 | (first '(3 1 4 1 5 9 2)) -> 3 |
cdr,tail,next (3,1,4,1,5,9,2) -> (1,4,1,5,9,2) | tail [3,1,4,1,5,9,2] -> [1,4,1,5,9,2] | (cdr '(3 1 4 1 5 9 2)) -> (1 4 1 5 9 2) | (cdr '(3 1 4 1 5 9 2)) -> (1 4 1 5 9 2) | (rest '(3 1 4 1 5 9 2)) -> (1 4 1 5 9 2) |
cons 3 (1,4,1,5,9,2) -> (3,1,4,1,5,9,2) | 3:[1,4,1,5,9,2] -> [3,1,4,1,5,9,2] | (cons 3 '(1 4 1 5 9 2)) -> (3 1 4 1 5 9 2) | (cons 3 '(1 4 1 5 9 2)) -> (3 1 4 1 5 9 2) | (cons 3 '(1 4 1 5 9 2)) (conj '(1 4 1 5 9 2) 3) |
append,concat (3,1,4) (1,5,9,2) -> (3,1,4,1,5,9,2) | [3,1,4] ++ [1,5,9,2] -> [3,1,4,1,5,9,2] | (append '(3 1 4) '(1 5 9 2)) -> (3 1 4 1 5 9 2) | (append '(3 1 4) '(1 5 9 2)) -> (3 1 4 1 5 9 2) | (concat '(3 1 4) '(1 5 9 2)) -> (3 1 4 1 5 9 2) |
take | take 5 [3,1,4,1,5,9,2] -> [3,1,4,1,5] | (take '(3 1 4 1 5 9 2) 5) | (labels (subseq '(3 1 4 1 5 9 2) 0 5) | (take 5 '(3 1 4 1 5 9 2)) -> (3 1 4 1 5) |
drop 5 (3,1,4,1,5,9,2) -> (9,2) | drop 5 [3,1,4,1,5,9,2] -> [9,2] | (drop '(3 1 4 1 5 9 2) 5) | (labels | (drop 5 '(3 1 4 1 5 9 2)) -> (9 2) |
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
take-while odd? (3,1,4,1,5,9,2) -> (3,1) | takeWhile odd [3,1,4,1,5,9,2] -> [3,1] | (letrec | (labels | (take-while odd? '(3 1 4 1 5 9 2)) -> (3 1) |
drop-while odd? (3,1,4,1,5,9,2) -> (4,1,5,9,2) | dropWhile odd [3,1,4,1,5,9,2] -> [4,1,5,9,2] | (letrec | (labels | (drop-while odd? '(3 1 4 1 5 9 2)) -> (4 1 5 9 2) |
map square (3,1,4,1,5,9,2) -> (9,1,16,1,25,81,4) | map (\x -> x^2) [3,1,4,1,5,9,2] -> [9,1,16,1,25,81,4] | (map (lambda (x) (* x x)) '(3 1 4 1 5 9 2)) | (mapcar #'(lambda (x) (* x x)) '(3 1 4 1 5 9 2)) -> (9 1 16 1 25 81 4) | (map #(* % %) '(3 1 4 1 5 9 2)) |
filter odd? (3,1,4,1,5,9,2) -> (3,1,1,5,9) | filter odd [3,1,4,1,5,9,2] -> [3,1,1,5,9] | (filter odd? '(3 1 4 1 5 9 2)) | (*5) | (filter odd? '(3 1 4 1 5 9 2)) -> (3 1 1 5 9) |
fold-right f (3,1,4,1) 5 -> f(3, f(1, f(4, f(1, 5)))) | foldr (-) 5 [3,1,4,1] | (fold-right - 5 '(3 1 4 1)) | (funcall (*5) | ((reduce (*7) |
fold-left f 3 (1,4,1,5) -> f(f(f(f(3, 1), 4), 1) 5) | foldl (-) 3 [1,4,1,5] | (fold (lambda (y x) (- x y)) 3 '(1 4 1 5)) | (reduce #'- '(1 4 1 5) :initial-value 3) | (reduce - 3 '(1 4 1 5)) -> -8 |
reduce-right f (3,1,4,1,5) -> f(3, f(1, f(4, f(1, 5)))) | foldr1 (-) [3,1,4,1,5] | (reduce-right - identity '(3 1 4 1 5)) | (*6) | (*8) |
reduce-left f (3,1,4,1,5) -> f(f(f(f(3, 1), 4), 1), 5) | foldl1 (-) [3,1,4,1,5] | (reduce (lambda (y x) (- x y)) identity '(3 1 4 1 5)) | (reduce #'- '(3 1 4 1 5)) -> -8 | (reduce - '(3 1 4 1 5)) -> -8 |
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
nth 2 (3, 1, 4, 1, 5) -> 4 | [3,1,4,1,5]!!2 -> 4 | (car (drop '(3 1 4 1 5) 2)) -> 4 (*2) | (nth 2 '(3 1 4 1 5)) -> 4 | (nth '(3 1 4 1 5) 2) -> 4 |
elem, member 2 (3,1,4,1,5,9,2) -> true 7 (3,1,4,1,5,9,2) -> false | elem 2 [3,1,4,1,5,9,2] -> True elem 7 [3,1,4,1,5,9,2] -> False | (member 2 '(3 1 4 1 5 9 2)) -> (2) (member 7 '(3 1 4 1 5 9 2)) -> #f | (member 2 '(3 1 4 1 5 9 2)) -> (2) (member 7 '(3 1 4 1 5 9 2)) -> NIL | (some #(= % 2) '(3 1 4 1 5 9 2)) |
some, any even? '(3 1 4 1) -> true even? '(3 5 7 9) -> false | any even [3,1,4,1] | (any even? '(3 1 4 1)) | (some even? '(3 1 4 1)) -> true (some even? '(3 5 7 9)) -> nil | |
every?, all odd? '(3 1 4 1) -> false odd? '(3 5 7 9) -> true | all odd [3,1,4,1] -> False all odd [3,5,7,9] -> True | (every odd? '(3 1 4 1)) | (every? odd? '(3 1 4 1)) -> false (every? odd? '(3 5 7 9)) -> true | |
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
0, 1, 2, ... infinite | [0..] -> [0,1,2,...infinitely] | (range) -> (0 1 2 ... infinitely) | ||
0, 1, 2, 3, 4 | [0..4] -> [0,1,2,3,4] | (iota 5) -> (0 1 2 3 4) (*2) | (*9) (unfold #'(lambda (x) (<= 5 x)) #'identity #'1+ 0) -> (0 1 2 3 4) | (range 5) |
2, 3, 4, 5, 6 | [2..6] -> [2,3,4,5,6] | (iota 5 2) | (*9) (unfold #'(lambda (x) (<= 7 x)) #'identity #'1+ 2) -> (2 3 4 5 6) | (range 2 7) |
3, 5, 7, 9, 11 | [3,5..11] -> [3,5,7,9,11] | (iota 5 3 2) | (*9) | (range 3 12 2) -> (3 5 7 9 11) |
(3, 1, 4, 1, 5) -> 14 | sum [3,1,4,1,5] foldl (+) 0 [3,1,4,1,5] | (apply + '(3 1 4 1 5)) (fold-right + 0 '(3 1 4 1 5)) | (apply #'+ '(3 1 4 1 5)) (reduce #'+ '(3 1 4 1 5)) | (apply + '(3 1 4 1 5)) (reduce + 0 '(3 1 4 1 5)) |
unfold x f g -> x, f(x), f(f(x)), ... unless g(n) | x2 x = 2 * x Data.List.unfoldr | (define (x2 x) (* 2 x)) | (*9) | (*10) |
iterate | iterate (2 *) 1 -> [1,2,4,8,16,... infinitely] | (iterate (partial * 2) 1) -> (1 2 4 8 16 ... infinitely) | ||
finite iterate x f 5 -> x, f(x), f(f(x)), f(f(f(x))), f(f(f(f(x)))) | take 5 $ iterate (2 *) 1 -> [1,2,4,8,16] | |||
repeat x -> (x, x, x, ...) | repeat 2 -> [2,2,2,2,2,... infinitely] | (repeat 2) -> (2 2 2 2 2 ... infinitely) | ||
finite repeat x 5 -> (x, x, x, x, x) | take 5 $ repeat 2 -> [2,2,2,2,2] | (make-list 5 2) -> (2 2 2 2 2) (*2) | (take 5 (repeat 2)) | |
Haskell | Scheme (R5RS) | Common Lisp | Clojure | |
assoc | ||||
show contents of a file | (print (slurp "hoge.clj")) |
(*1) : To use function definitions in ghci, 'let' is required.
(*2) : SRFI-1 is needed. It's dependent on processors how to load SRFI-1.
For example, use (use srfi-1) with gauche and (require (lib "1.ss" "srfi")) with MzScheme.
In some processors, some functions defined in SRFI-1 can be used without an explicit loading of SRFI-1.
(*3): This definition of 'labels' is valvallows' Common Lisp の labels を Scheme の衛生的マクロで書いてみる
(*4): The SRFI-1's 'fold' is a variant of the general "fold-left".
(fold f z '(x1 x2 x3 x4)) is meant to be (f x4 (f x3 (f x2 (f x1 z)))).
R6RS has "fold-left".
(fold-left f z '(x1 x2 x3 x4)) is meant to be (f (f (f (f z x1) x2) x3) x4).
(*5): Here is a definition of fold-right for Common Lisp.
(defun fold-right (f s ls) (funcall (reduce #'(lambda (acc x) #'(lambda (y) (funcall acc (funcall f x y)))) ls :initial-value #'identity) s))
(*6): Here is a definition of reduce-right for Common Lisp. https://gist.github.com/2894872
(defun reduce-right (f ls) (labels ((rec (lss cont) (if (null (cdr lss)) (funcall cont (car lss)) (rec (cdr lss) #'(lambda (x) (funcall cont (funcall f (car lss) x))))))) (rec ls #'identity)))
(*7): Here is a definition of fold-right for Clojure.
(defn fold-right [f s coll] ((reduce (fn [acc x] (comp acc #(f x %))) identity coll) s))
https://gist.github.com/2893987
or
(defn r-reduce [init updt pred retn f coll] (loop [stat init [h & r :as curr] coll cont identity] (if (or (pred stat) (nil? r)) (cont (retn curr)) (recur (updt stat) r (comp cont #(f h %)))))) (defn fold-right [f z coll] (r-reduce coll next nil? (fn [x] z) f coll))
https://gist.github.com/2896939
(*8): Here is a definition of reduce-right for Clojure.
(defn reduce-right [f coll] (loop [[h & r] coll acc identity] (if (nil? r) (acc h) (recur r (comp acc #(f h %))))))
https://gist.github.com/2894687
(defn r-reduce [init updt pred retn f coll] (loop [stat init [h & r :as curr] coll cont identity] (if (or (pred stat) (nil? r)) (cont (retn curr)) (recur (updt stat) r (comp cont #(f h %)))))) (defn reduce-right [f coll] (r-reduce coll next nil? first f coll))
https://gist.github.com/2896939
(*9): Here is a definition of unfold for Common Lisp.
(defun unfold (p f g s) (if (funcall p s) nil (cons (funcall f s) (unfold p f g (funcall g s)))))
(*10): Here is definitions of unfold for Clojure. https://gist.github.com/2901487
(defn unfold [p f g s] (loop [curr s cont identity] (if (p curr) (cont '()) (recur (g curr) (comp cont (partial cons (f curr)))))))
JavaScript, Scala, OCaml and F#
JavaScript | Scala | OCaml | F# | |
---|---|---|---|---|
function literal | function(x, y){return x*x + y*y}(3,4) -> 25 | ((x:Int, y:Int) => x*x + y*y)(3, 4) -> Int = 25 | (fun x y -> x*x + y*y) 3 4;; -> int = 25 | (fun x y -> x*x + y*y) 3 4;; |
bind a function literal to a variable | var sos = function(x, y){return x*x + y*y}; sos(3,4) -> 25 | var sos = (x:Int, y:Int) => x*x + y*y sos(3,4) -> Int = 25 | let sos = fun x y -> x*x + y*y;; | let sos = fun x y -> x*x + y*y;; sos 3 4;; -> int = 25 |
bind a function literal to a variable in a scope | function(){ | (() => { | let sos = fun x y -> x*x + y*y in sos 3 4;; -> int = 25 sos 3 4;; -> Unbound value sos | let sos = fun x y -> x*x + y*y in sos 3 4 |
named function | function sos(x, y){return x*x + y*y}; sos(3,4) -> 25 | def sos(x:Int, y:Int) = x*x + y*y sos(3, 4) -> Int = 25 | let sos x y = x*x + y*y;; sos 3 4;; -> int = 25 | let sos x y = x*x + y*y;; sos 3 4;; -> int = 25 |
named function in a scope | function(){ function sos(x, y) {return x*x + y*y}; return sos(3, 4); }() -> 25 sos(3, 4) -> sos is not defined | (() => { def sos(x:Int, y:Int) = x*x + y*y sos(3, 4) })() -> Int = 25 sos(3, 4) -> not found: value sos | let sos x y = x*x + y*y in sos 3 4;; -> int = 25 sos 3 4;; -> Unbound value sos | let sos x y = x*x + y*y in sos 3 4;; -> int = 25 sos 3 4;; -> The value or constructor 'sos' is not defined |
JavaScript | Scala | OCaml | F# | |
car,head,first (3,1,4,1,5,9,2) -> 3 | [3,1,4,1,5,9,2].shift() | List(3,1,4,1,5,9,2).head -> Int = 3 | List.hd [3;1;4;1;5;9;2];; | List.head [3;1;4;1;5;9;2];; |
cdr,tail,next (3,1,4,1,5,9,2) -> (1,4,1,5,9,2) | (function(x){x.shift(); return x})([3,1,4,1,5,9,2]) | List(3,1,4,1,5,9,2).tail -> List[Int] = List(1,4,1,5,9,2) | List.tl [3;1;4;1;5;9;2];; -> - : int list = [1; 4; 1; 5; 9; 2] | List.tail [3;1;4;1;5;9;2];; |
cons 3 (1,4,1,5,9,2) -> (3,1,4,1,5,9,2) | (function(h,t){t.unshift(h); return t})(3, [1,4,1,5,9,2]) | 3::List(1,4,1,5,9,2) -> List[Int] = List(3,1,4,1,5,9,2) | 3::[1;4;1;5;9;2];; -> - : int list = [3; 1; 4; 1; 5; 9; 2] | 3::[1;4;1;5;9;2];; |
append,concat (3,1,4) (1,5,9,2) -> (3,1,4,1,5,9,2) | [3,1,4].concat([1,5,9,2]) -> [ 3, 1, 4, 1, 5, 9, 2 ] | List(3,1,4):::List(1,5,9,2) -> List[Int] = List(3,1,4,1,5,9,2) | [3;1;4] @ [1;5;9;2];; List.append [3;1;4] [1;5;9;2];; | [3;1;4] @ [1;5;9;2];; List.append [3;1;4] [1;5;9;2];; |
take | ||||
drop 5 (3,1,4,1,5,9,2) -> (9,2) | ||||
JavaScript | Scala | OCaml | F# | |
take-while odd? (3,1,4,1,5,9,2) -> (3,1) | ||||
drop-while odd? (3,1,4,1,5,9,2) -> (4,1,5,9,2) | ||||
map square (3,1,4,1,5,9,2) -> (9,1,16,1,25,81,4) | List(3,1,4,1,5,9,2).map(x => x * x) -> List[Int] = List(9,1,16,1,25,81,4) | List.map (fun x->x*x) [3;1;4;1;5;9;2];; | List.map (fun x->x*x) [3;1;4;1;5;9;2];; | |
filter odd? (3,1,4,1,5,9,2) -> (3,1,1,5,9) | List(3,1,4,1,5,9,2).filter(x => x % 2 != 0) -> List[Int] = List(3,1,1,5,9) | List.filter (fun x->(x mod 2) != 0) [3;1;4;1;5;9;2];; | List.filter (fun x->(x%2)<>0) [3;1;4;1;5;9;2];; | |
fold-right f (3,1,4,1) 5 -> f(3, f(1, f(4, f(1, 5)))) | List(3,1,4,1).foldRight(5){_ - _} (List(3,1,4,1) :\ 5){_ - _} | List.fold_right (-) [3;1;4;1] 5;; | List.foldBack (-) [3;1;4;1] 5;; | |
fold-left f 3 (1,4,1,5) -> f(f(f(f(3, 1), 4), 1) 5) | List(1,4,1,5).foldLeft(3){_ - _} (3 /: List(1,4,1,5)){_ - _} | List.fold_left (-) 3 [1;4;1;5];; | List.fold (-) 3 [1;4;1;5];; -> val it : int = -8 | |
reduce-right f (3,1,4,1,5) -> f(3, f(1, f(4, f(1, 5)))) | List(3,1,4,1,5).reduceRight(_ - _) -> Int = 10 | List.reduceBack (-) [3;1;4;1;5];; | ||
reduce-left f (3,1,4,1,5) -> f(f(f(f(3, 1), 4), 1), 5) | List(3,1,4,1,5).reduceLeft(_ - _) -> Int = -8 | List.reduce (-) [3;1;4;1;5];; | ||
JavaScript | Scala | OCaml | F# | |
nth 2 (3, 1, 4, 1, 5) -> 4 | List.nth [3;1;4;1;5;9;2] 2;; | List.nth [3;1;4;1;5;9;2] 2;; | ||
elem, member 2 (3,1,4,1,5,9,2) -> true 7 (3,1,4,1,5,9,2) -> false | List.mem 2 [3;1;4;1;5;9;2];; | |||
some, any even? '(3 1 4 1) -> true even? '(3 5 7 9) -> false | ||||
every?, all odd? '(3 1 4 1) -> false odd? '(3 5 7 9) -> true | ||||
JavaScript | Scala | OCaml | F# | |
0, 1, 2, ... infinite | ||||
0, 1, 2, 3, 4 | List.range(0,5) -> List[Int] = List(0,1,2,3,4) | |||
2, 3, 4, 5, 6 | List.range(2,7) -> List[Int] = List(2,3,4,5,6) | |||
3, 5, 7, 9, 11 | List.range(3,12,2) -> List[Int] = List(3,5,7,9,11) | |||
(3, 1, 4, 1, 5) -> 14 | ||||
unfold x f g -> x, f(x), f(f(x)), ... until g(x) | ||||
iterate | ||||
finite iterate x f 5 -> x, f(x), f(f(x)), f(f(f(x))), f(f(f(f(x)))) | ||||
repeat x -> (x, x, x, ...) | ||||
finite repeat x 5 -> (x, x, x, x, x) | ||||
JavaScript | Scala | OCaml | F# | |
assoc | ||||
show contents of a file |
OCaml reference: http://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html
F# reference: http://msdn.microsoft.com/en-us/library/ee353738.aspx
Processors
Haskell | Glasgow Haskell Compiler (GHC) Hugs 98 |
Scheme | Gauche GNU Guile Racket (PLT Scheme) MIT Scheme |
Common Lisp | Steeel Bank Common Lisp (SBCL) |
Clojure | Clojure |
Standard ML | Standard ML of New Jersey (SML/NJ) MLton SML# |
OCaml | OCaml (INRIA) |
F# | F# (Microsoft) |
Scala | Scala |
JavaScript | Node.js Rhino |
GHC | Gauche | SBCL | CLISP | Clojure | Node.js | Scala | OCaml | Mono F# | |
---|---|---|---|---|---|---|---|---|---|
interpreter | ghci | gosh | sbcl | clisp | java clojure.main | node | java scala.tools.nsc.MainGenericRunner (Use a bundled script instead) | ocaml | fsi |
recomended command line editor | built-in | rlwrap | rlwrap | built-in | rlwrap | built-in | rlwrap | ledit | built-in |
exit interpreter | :quit | (exit) | (quit) | (exit) (quit) | (System/exit 0) ^D | ^D | exit :quit | #quit;; | #quit;; |
import a library | :m +Data.List | (use srfi-1) | (use 'clojure.java.io) | ||||||
load a source file | :l hoge.hs :l hoge | (load "./hoge.scm") | (load "hoge.lisp") | (load "hoge.lisp") | (load-file "hoge.clj") | :l hoge.scala | #use "hoge.cma" | #load "hoge.fsx" note: | |
execute a script without compiling | |||||||||
compile and execute | |||||||||
args | $ cat args.scm | ||||||||
multi line | :{ |
LISPs
5 Basic Functions
Scheme | Common Lisp | Clojure | |
---|---|---|---|
1. car | car | car, first | first |
2. cdr | cdr | cdr, rest | rest |
3. cons | cons | cons | cons |
4. atom | (lambda (x) (not (pair? x))) | atom | #(not (list? %)) |
5. eq | eq? | eq | = |
Special Forms (Syntax)
scheme | Common Lisp | Clojure | |
---|---|---|---|
cond | cond | cond | cond |
lambda | lambda | lambda | fn |
define | define | set | def |
Other Basics
scheme | Common Lisp | Clojure | |
---|---|---|---|
(= 0 0) | #t | T | true |
(= 0 1) | #f | NIL | false |
Y.Kohyama