
2026/05/19 4:27
ハイポリグロット・リズプ:コモンリズプ、ラケット、クロージャ、エマックスリズプ。
RSS: https://news.ycombinator.com/rss
要約▶
日本語訳:
この参照シートは、Common Lisp、Racket、Clojure、および Emacs Lisp の間での重要な技術的な比較を提供し、具体的なバージョン(SBCL 1.2、Racket 6.1、Clojure 1.6、および Emacs 24.5)に対する検証結果を含んでいます。本書は、これらの関数型方言特有の構文スタイルと実行モデルを巡る開発者のための不可欠なガイド役を果たします。文書は、識別子のケース感受性における主要な違い(Common Lisp のケース不感 versus それ他言語のケース感)、変数バインディング慣習(例えば
defparameter/defvar versus define)、および null 値のセマンティクス(Common Lisp、Racket、Emacs では nil/'() が同義語であるのに対し、Clojure では区別される)について明確にします。また、核心的な演算における重要な変異も詳述されています。これには、アリティミティック論理リテラル(t versus #t)、浮動小数点除算の扱い、およびファイル I/O パターンが含まれます。この参照は明示的にコンパイル戦略を対比しており、Common Lisp のバイトコードアプローチ versus Racket および Clojure のジャスト・イン・タイム(JIT)または Java ベースの環境について述べています。また、共通リッチにおける末尾呼び出し最適化の可用性があるのと Emacs Lisp にはないという実行モデルの違いも強調しています。エラーハンドリングの実装、マクロシステム、名前空間、およびデータ構造(例えば cons/cdr アクセッサ versus first/rest)について特定の実装を調査することで、エンジニアリングチームはマルチ言語スタックを構築する際の互換性課題を評価し、可搬性の高いコードを記述するとともに、変更可能および不変の設計におけるエコシステム固有のトレードオフを理解することを支援します。本文
ca 並列参照シート
文法と実行 | 変数と式 | 算術と論理 | 文字列 | 正規表現 | 日付と時刻 | リスト | フィクストラム配列 | ダイクト(辞書型)| ユーザー定義型 | 関数 | 実行制御 | エラー処理 | ストリーム | Emacs バッファ | ファイル | ディレクトリ | プロセスと環境 | ライブラリと名前空間 | オブジェクト | Lisp マクロ | リフレクション | Java との連携
Common Lisp / Racket / Clojure / Emacs Lisp
注:以下の各セクションは、左から Common Lisp (SBCL)、Racket、Clojure、Emacs Lisp の順です。
バージョン情報
- SBCL 1.2
- Racket 6.1
- Clojure 1.6
- Emacs 24.5
表示方法:
$ sbcl --version$ racket --version- REPL 起動時に表示される
$ emacs --version
文法と実行 (Grammar and Execution)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
コンパイラまたは | スタンドアロン実行ファイル (sb-ext:save-lisp-and-die "executable" :executable t :toplevel 'function) または | インタプリタClojure の JAR への完全なパスを指定: | シェbang (Shebang)Clojure の JAR への完全なパスを指定: Emacs Lisp: |
| 単語の区切り文字 (Word Separator) 空白のみ 空白とカンマ 空白のみ 空白のみ | |||
| 改行コメント (End-of-line comment) (+ 1 1) ; adding | |||
| 複数行コメント (+ 1 #| adding # | 1) |
変数と式 (Variables and Expressions)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 識別子 (Identifier) 大文字小文字不敏感、数字では始まる不可。 除外文字: SP ( ) " , ' ` : ; # | <br>ユーザーマクロ用予約済み:? ! [ ] { } 照合は行われる | 識別子 大文字小文字敏感、数字では始まる不可。 除外文字: SP ( ) [ ] { } " , ' ` ; # | <br>照合される | 識別子 大文字小文字敏感、数字では始まる不可。 許可文字: A-Z a-z 0-9 * + ! - _ ? 特殊意味/予約: / . : | |
| クォートされた識別子とエスケープ (setq | white space symbol| 3) (setq white\ space\ symbol 3) | (define |white space symbol| 3) (define white\ space\ symbol 3) | なし なし (setq white\ space\ symbol 3) | |
| ローカル変数 並列代入: (let ((x 3) (y 4)) (+ x y)) 順次代入: (let* ((x 3) (y (* x x))) (+ x y)) | 並列代入: (let [x 3 y 4] (+ x y)) 順次代入: (let [[x y] [3 4]] (+ x y)) (let [x 3 y (* x x)] (+ x y)) | (lexical-let ((x 3) (y 4)) (+ x y)) (lexical-let* ((x 3) (y (* x x))) (+ x y)) | |
グローバル変数 *x* 3 *x* 3定義済みなら変更しない: y はグローバルではない: (define (double z) (define y 2) (* y z)) | x 3 'x 3 x 3 | ||
| 変数の削除 (makunbound 'x) (namespace-undefine-variable! 'x) (ns-unmap ns 'x) | (makunbound 'x) | ||
Nothing (Nil) '<>() '<>()(Java と同じ値: ) | '<>()(Java と同じ値) '<>() | ||
| Null チェック (null x) (null? x) (nil? x) (null x) | (null x) | ||
| 識別子を値として扱う 'x (quote x) | 'x (quote x) | 'x (quote x) | |
| 識別子テスト (symbolp 'x) | (symbol? 'x) (symbol? 'x) (symbolp 'x) | ||
| 識別子の等価性テスト (eq 'x 'x) | (eq? 'x 'x) (= 'x 'x) (eq 'x 'x) | ||
| 参照なし識別子 :foo #:foo | :foo | :foo | |
| 識別子の属性 set/get/remove (set 'x 13) (setf (get 'x :desc) "unlucky") (get 'x :desc) (remprop 'x :desc) | なし (値は clojure.lang.IObj のインスタンスでなければならない): (def x (with-meta [13] {:desc "unlucky"})) (get (meta x) :desc) なし (set 'x 13) (setf (get 'x :desc) "unlucky") (get 'x :desc) (remprop 'x :desc) |
算術と論理 (Arithmetic and Logic)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
True/False | | | |
偽 (Falsehoods) '<()> | | | '<()> |
| 論理演算子 (or (not t) (and t nil)) | (or (not #t) (and #t #f)) | (or (not true) (and true false)) | (or (not t) (and t nil)) |
| 関係演算子 = /= < > <= >= | = ない < > <= >= | = not= < > <= >= | = /= < > <= >= |
| 最小値・最大値 (min 1 2 3) (max 1 2 3) | (min 1 2 3) (max 1 2 3) | (min 1 2 3) (max 1 2 3) | (min 1 2 3) (max 1 2 3) |
| 数値判定 numberp integerp rationalp floatp realp complexp | number? integer? rational? inexact? real? complex? | number? integer? rational? float? なし なし | numberp integerp なし floatp なし なし |
| 算術演算子 + - * / mod | + - * / modulo | + - * / mod | + - * / % |
| 整数除算と剰余 (truncate 7 3) (rem 7 3) | (quotient 7 3) (remainder 7 3) (quot 7 3) (rem 7 3) | (/ 7 3) (% 7 3) | |
| ゼロ除算エラー division-by-zero エラー | division by zero エラー | arith-error | |
| 浮動小数点除算 有理数: (/ 7 3) 浮動小数点: (/ 7 (* 3 1.0)) | 有理数: (/ 7 3) 浮動小数点: (/ 7 (float 3)) | 整数商: (/ 7 3) 浮動小数点: (/ 7 (* 3 1.0)) | |
| 浮動小数点のゼロ除算 division-by-zero エラー | -1.0e+INF, -0.0e+NaN, または 1.0e+INF | ||
| 累乗 (Power) (expt 2 32) | (expt 2 32) 浮動小数点を返す: (Math/pow 2 32) | (expt 2 32) | |
| 平方根 (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 |
| 超越関数 exp log sin cos tan asin acos atan cotanh | exp log sin cos tan asin acos atan atan | Math/exp ... Math/atan2 | exp log sin cos tan asin acos atan atan |
| 浮動小数点の丸め処理 2 つの値を返す(1 目は整数): truncate round ceiling floor 浮動小数点を返す: truncate round ceiling floor 整数を返す: int Math/round 浮動小数点を返す: Math/ceil Math/floor | truncate round ceiling floor fround fceiling ffloor truncate は整数を返す | ||
| 絶対値と符号関数 abs signum | abs Racket: sgn | Math/abs Math/signum | abs signum |
| 整数オーバーフロー なし; 任意精度の整数 なし; 任意精度の整数 | clojure.lang.Numbers.throwIntOverflow エクセプション | ||
| 浮動小数点オーバーフロー floating-point-overflow エラー | リテラルでは不可: -Infity NaN Infinity | ||
| 有理数の構築 (/ 3 7) リテラル: 3/7 (/ 3 7) リテラル: 3/7 また有理数: 2.718 (exp 1) | (/ 3 7) リテラル: 3/7 | ||
| 有理数の分解 (numerator 3/7) (denominator 3/7) | (numerator 3/7) (denominator 3/7) | なし なし | |
| 複素数の構築 #c(1 2) | 1+2i (+ 1 +2i) | なし なし | |
| 複素数の分解 (realpart #c(1 2)) (imagpart #c(1 2)) (phase #c(1 2)) (abs #c(1 2)) (conjugate #c(1 2)) | (real-part 1+2i) (imag-part 1+2i) (angle 1+2i) (magnitude 1+2i) (conjugate 1+2i) | なし なし なし なし | |
| 乱数 一様整数、一様浮動小数点、正規分布 (random 100) (random 1.0) なし (random 100) (random) | (def rnd (java.util.Random.)) (.nextInt rnd 100) (.nextFloat rnd) (.nextGaussian rnd) (random 100) なし なし | (random-seed 17) | |
| 乱数のシード (setq random-state (sb-ext:seed-random-state 17)) | (random-seed 17) | ||
| ビット演算子 ash left shift (2 目の引数が正の場合), logand logior logxor lognot | arithmetic-shift left shift (同上), 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 (同上), logand logior logxor lognot |
| 2 進数、8 進数、16 進数リテラル #b101010 #o52 #x2a | #b101010 #o52 #x2a | ||
| 基数 (Radix) (format nil "~7r" 42) |
文字列 (Strings)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 文字列テスト (stringp "foo") | (string? "foo") | (string? "foo") | (stringp "foo") |
| 文字列リテラル "foo bar" | "foo bar" | "foo bar" | "foo bar" |
| リテラル内の改行 はい はい はい はい | |||
| リテラルエスケープ \" \\ \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 | |
| コンストラクタ (string #\f #\o #\o) | (string ?f ?o ?o) | ||
| フォーマット文字列 (format nil "~a: ~a ~,2f" "Foo" 7 13.457) | (format "~a ~a ~a" "Foo" 7 13.457) (String/format "%s: %d %.2f" (to-array ["Foo" 7 13.457])) (format "%s: %d %.2f" "Foo" 7 13.457) | ||
| フォーマット指定子 ~a 任意型、人間 readable ~s 任意型、read parseable ~~ タイルダ ~d 十進数 ~x 16 進数 ~o 8 進数 ~b 2 進数 | ~a any type, human readable ~s any time, read parseable ~~ tilde ~c character ~d decimal ~x hex ~o octal ~b binary | ||
| 文字列の比較 (string= "foo" "bar") (string< "foo" "bar") (string=? "foo" "bar") (string<? "foo" "bar") | (.equals "foo" "bar") (.compareTo "foo" "bar") | (string= "foo" "bar") (string< "foo" "bar") | |
| 文字列の連結 (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 (. Character TYPE) (repeat 3 \f))) | (make-string 3 ?f) |
| 大文字小文字の転換 (string-downcase "FOO") (string-upcase "foo") | (.toLowerCase "FOO") (downcase "FOO") (upcase "foo") | ||
| 頭文字を大文字に (Capitalize) ; "Foo Bar": (string-capitalize "foo bar") ; "Foo Bar": (capitalize "foo") | |||
| 不要なスペースの削除 (Trim) (string-trim '(#\space #\tab #\newline) " foo ") (require srfi/13/string) (string-trim-both " foo ") | (.trim " foo ") | なし; 実装については注釈を参照 | |
| パディング (Pad) 右側、左側 (format nil "~10a" "foo") (format nil "~10@a" "foo") | |||
| 数値から文字列へ (concatenate 'string "value: " (princ-to-string 8)) (string-append "value: " (number->string 8)) | (str "Value: " 8) | (concat "value: " (number-to-string 8)) | |
| 文字列から数値へ (+ 7 (parse-integer "12")) (+ 73.9 (read-from-string ".037")) | (+ 7 (string->number "12")) (+ 73.9 (string->number ".037")) | (+ 7 (Integer/parseInt "12")) (+ 73.9 (Float/parseFloat ".037")) | |
| 文字列の分割 (cl-ppcre:split "[ \t\n]+" "foo bar baz") | (regexp-split #rx"[ \n\t]+" "foo bar baz") | (seq (.split "foo bar baz" "[ \t\n]+")) | (split-string "foo bar baz") |
| 文字列の結合 (Join) (reduce (lambda (m o) (concatenate 'string m " " o)) '("foo" "bar" "baz")) | (string-join '("foo" "bar" "baz") " ") | (reduce #(str %1 " " %2) '("foo" "bar" "baz")) | (reduce (lambda (m o) (concat m " " o)) '("foo" "bar" "baz")) |
| 文字列の長さ (length "foo") (string-length "foo") | (.length "foo") | (length "foo") | |
| 部分文字列の検索 (Index) (search "bar" "foo bar") | Racket: (require srfi/13/string) (string-contains "foo bar" "bar") | (.indexOf "foo bar" "bar") | (search "bar" "foo bar") |
| 部分文字列の抽出 (Extract) (subseq "foo bar" 4 7) (substring "foo bar" 4 7) | (.substring "foo bar" 4 7) | (substring "foo bar" 4 7) | |
| キャラクタリテラル #\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\rubout | #\a #\space #\newline #\backspace #\tab #\linefeed #\page #\return #\nul #\vtab #\alarm #\esc #\delete Racket にない: #\alarm #\esc #\delete | \a \newline \space \backspace \tab ? \formfeed \return ? | |
| キャラクタのテスト (characterp #\x) (alpha-char-p #\x) (alphanumericp #\x) (digit-char-p #\7) (lower-case-p #\x) (upper-case-p #\X) | (char? #\x) (char? \x) | (characterp ?x) | |
| Chr と Ord (code-char 97) (char-code #\a) | (integer->char 97) (char->integer #\a) | (char 97) (int \a) | |
| キャラクタ配列への変換 ; リスト: (string->list "foo") | |||
| キャラクタのアクセス (char "foo" 0) (string-ref "foo" 0) | (.charAt "foo" 0) | (aref "foo" 0) | |
| 正規表現 (Regular Expressions) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| リテラル 文字列を使用: "\b\d{5}\b" POSIX 拡張: #rx"^[0-9][0-9][0-9][0-9][0-9]$" (regexp "^[0-9][0-9][0-9][0-9][0-9]$") Perl スタイル: #px"\b\d{5}\b" (pregexp "\b\d{5}\b") | #\b\d{5}\b | ||
| キャラクタクラスの略号 . \d \D \s \S \w \W regexp: . pregexp: . \d \D \s \S \w \W | . \d \D \s \S \w \W \ca \cl and \cg match ASCII, Latin, and Greek characters. Character classes of the form \sx depend on the current syntax table. | ||
| アンカー ^ $ \b \B regexp: ^ $ pregexp: ^ $ \b \B | ^ $ \A \b \B \G \z \Z | ^ $ \b \B | |
| 一致テスト (Match Test) (ql:quickload "cl-ppcre") (if (cl-ppcre:all-matches "1999" s) (format t "party!")) (regexp-match #rx"bar" "foo bar") | (re-find #"bar" "foo bar") | (string-match "bar" "foo bar") | |
| 大文字小文字無視の一致 (regexp-match #px"(?i:lorem)" "Lorem") | (re-find #"(?i:lorem)" "Lorem") | ||
| 置換 (Substitution) (cl-ppcre:regex-replace "[^l]l" "hello" "EL") (cl-ppcre:regex-replace-all "[^l]l" "hello hello" "EL") | (regexp-replace #rx"el" "hello" "EL") (regexp-replace* #rx"el" "hello hello" "EL") | (.replaceFirst "hello" "[^l]l" "XX") (.replaceAll "hello hello" "[^l]l" "XX") ? | (replace-regexp-in-string "[^l]l" "EL" "hello hello") |
| グループキャプチャ (match (regexp-match #px"(\d{4})-(\d{2})-(\d{2})" "2010-06-03") [(list s yr mn dy) (list yr mn dy)]) | (let [[_ yr mn dy] (re-find #"(\d{4})-(\d{2})-(\d{2})" "2010-06-03")] yr) | ||
| スキャン (re-seq #"\w+" "dolor sit amet") | |||
| 一致と置換におけるバック参照 (regexp-match #px"(\w+) \1" "do do") (regexp-replace #px"(\w+) (\w+)" "do re" "\2 \1") | |||
| 日付と時刻 (Dates and Time) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 破損された日時型 (Broken-down datetime type) 専用型なし; 9 値のリストが使用: 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 (Mon-Sun) daylight savings time: t or nil timezone: negated UTC offset in hours | 現在の日時 (get-decoded-time) (require racket/date) (current-date) (def dt (new java.util.Date)) (current-time) | UNIX epoch gray; seconds since Jan 1, 1900: (get-universal-time) (current-seconds) (/ (System/currentTimeMillis) 1000.0) (float-time) | |
| UNIX epoch から破損された日時へ (decode-universal-time (get-unversal-time)) (seconds->date (current-seconds)) (def dt (new java.util.Date (System/currentTimeMillis))) (seconds-to-time (float-time)) | 破損された日時から UNIX epoch へ (encode-universal-time 0 22 10 31 5 2015) (require racket/date) (date->seconds (current-date)) (/ (.getTime (new java.util.Date)) 1000.0) (multiple-value-bind (b s) (current-time) (+ (* b (expt 2 16)) s)) | ||
| 日時のフォーマット (def s "yyyy-MM-dd HH:mm:ss") (def fmt (new java.text.SimpleDateFormat s)) (.format fmt (new java.util.Date)) | (format-time-string "%Y-%m-%d %H:%M:%S" (current-time)) | 日時の解析 (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") | |
| 日付の構成要素 (multiple-value-bind (ss mi hr dy mo yr) (get-decoded-time) (list ss mi hr) ; warning quiesce (list dy mo yr)) (date-year (current-date)) (date-month (current-date)) (date-day (current-date)) (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) (multiple-value-bind (ss mi hr dy mo yr) (decode-time (current-time)) (list dy mo yr)) | 時刻の構成要素 (multiple-value-bind (ss mi hr) (get-decoded-time) (list ss mi hr)) (date-hour (current-date)) (date-minute (current-date)) (date-second (current-date)) (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) (multiple-value-bind (ss mi hr dy mo yr) (decode-time (current-time)) (list ss mi hr)) | ||
| 破損された日時の構築 (encode-universal-time 0 22 10 31 5 2015) (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))) (encode-time 0 50 8 31 5 2015) | |||
| リスト (Lists) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| リテラル '(1 2 3) (quote (1 2 3)) (1 2 3) (quote (1 2 3)) | '[1 2 3] {1 2 3} (quote (1 2 3)) (1 2 3) (quote (1 2 3)) '(1 2 3) (quote (1 2 3)) | ||
| コンストラクタ (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)) |
| 空リストのテスト nil と '<()> は同義であり、boolean コンテキストでは false として評価される。他のすべての値は true。 (empty? '()) (empty? ()) | nil と '<()> は同義であり、boolean コンテキストでは false として評価される。他のすべての値は true。 (nil and '() are synonyms...) | ||
| 空リストの評価 nil error (') nil | (first '(1 2 3)) (cdr '(1 2 3)) (rest '(1 2 3)) (next '(1 2 3)) (cdr '(1 2 3)) (rest '(1 2 3)) | ||
| 空リストの頭部と尾部 両方とも nil として評価 error | () 両方とも nil として評価 | first car | |
| 長さ (Length) (length '(1 2 3)) | (length '(1 2 3)) | (count '(1 2 3)) | (length '(1 2 3)) |
| 等価性テスト (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)) |
| N 番目の要素 ; 0 インデックスから: (nth 2 '(1 2 3 4)) (list-ref '(1 2 3 4) 2) (nth '(1 2 3 4) 2) (nth 2 '(1 2 3 4)) | (position 7 '(5 6 7 8)) | none (position 7 '(5 6 7 8)) | |
| 境界外動作 nil error raises IndexOutOfBoundsException | nil | (equal '(1 2 3) '(1 2 3)) | |
| 要素のインデックス (list-index (lambda (x) (= x 7)) '(5 6 7 8)) (require srfi/1) none (position 7 '(5 6 7 8)) | |||
| 連結 (Append) (append '(1 2 3) '(4 5 6)) | (concat '(1 2 3) '(4 5 6)) | (append '(1 2 3) '(4 5 6)) | |
| 先頭 N 個を取得 (Take) none (take '(1 2 3 4) 2) (take 2 '(1 2 3 4)) (subseq '(1 2 3 4) 0 2) | (drop '(1 2 3 4) 2) (drop 2 '(1 2 3 4)) | (nthcdr 2 '(1 2 3 4)) | |
| 末尾から N 個を除外 (Drop) (nthcdr 2 '(1 2 3 4)) | (last '(1 2 3)) (last '(1 2 3)) | ||
| 最後の要素 (car (last '(1 2 3))) | (define a '(1 2 3)) (take a (- (length a) 1)) (butlast '(1 2 3)) (butlast '(1 2 3)) | ||
| 最後の要素以外の要素 (butlast '(1 2 3)) | (reverse '(1 2 3)) (reverse '(1 2 3)) | ||
| 逆順 (Reverse) (reverse '(1 2 3)) | (sort '(3 2 4 1) '<) (sort '(3 2 4 1) <) | (sort < '(3 2 4 1)) (sort '(3 2 4 1) '<) | |
| 重複削除 (remove-duplicates '(1 1 2 3)) | (remove-duplicates '(1 1 2 3)) | (remove-duplicates '(1 1 2 3)) | |
| メンバーシップ (member 7 '(1 2 3)) (mapcar (lambda (x) (* x x)) '(1 2 3)) | (filter (lambda (x) (> x 2)) '(1 2 3)) ; filter-not は補集合を返す (filter #(> % 2) '(1 2 3)); remove returns complement | ||
| フィルタリング (remove-if-not (lambda (x) (> x 2)) '(1 2 3)) ; remove-if は補集合を返す (filter (lambda (x) (> x 2)) '(1 2 3)) ; filter-not は補集合を返す (remove-if-not (lambda (x) (> x 2)) '(1 2 3)); remove-if は補集合を返す | |||
| 畳み込み (Reduce) (reduce '- '(1 2 3 4) :initial-value 0) (foldl (lambda (x y) (- y x)) 0 '(1 2 3 4)) | (reduce - 0 '(1 2 3 4)) | (reduce '- '(1 2 3 4) :initial-value 0 :from-end t) (foldr - 0 '(1 2 3 4)) none (reduce '- '(1 2 3 4) :initial-value 0 :from-end t) | |
| 反復 (Iterate) (dolist (x '(1 2 3)) (print x) (print (- x))) (for ((x '(1 2 3))) (printf " | (doseq [x '(1 2 3)] (println x) (println (- x))) (dolist (x '(1 2 3)) (print x) (print (- x))) | ||
| 普遍述語 (every (lambda (i) (= 0 (rem i 2))) '(1 2 3 4)) (for/and ((i '(1 2 3 4))) (= 0 (remainder i 2))) | (every? #(= 0 (rem % 2)) '(1 2 3 4)) (every (lambda (i) (= 0 (% i 2))) '(1 2 3 4)) | ||
| 存在述語 (some (lambda (i) (= 0 (rem i 2))) '(1 2 3 4)) (for/or ((i '(1 2 3 4))) (= 0 (remainder i 2))) | (some #(= 0 (rem % 2)) '(1 2 3 4)) (some (lambda (i) (= 0 (% i 2))) '(1 2 3 4)) | ||
| リスト理解 (List Comprehension) (for*/list ((file "ABCDEFGH") (rank (in-range 1 9))) (format " | (for [file "ABCDEFGH" rank (range 1 9)] (format "%c%d" file rank)) | ||
| シャッフル (shuffle '(1 2 3 4)) | (shuffle '(1 2 3 4)) | ||
| リストの先頭を設定 (Set Head) (defparameter a '(1 2 3)) (setf (car a) 3) (require schema/mpair) (define a (mlist 1 2 3)) (set-mcar! a 3) none (setq a '(1 2 3)) (setcar a 3) | |||
| リストの尾部を設定 (Set Tail) (defparameter a '(1 2 3)) (setf (cdr a) '(4 5 6)) (require schema/mpair) (define a (mlist 1 2 3)) (set-mcdr! a (mlist 4 5 6)) none (setq a '(1 2 3)) (setcar a 3) (setcdr a '(4 5 6)) | |||
| 末尾から操作 (Manipulate Back) (defparameter a '(1 2 3)) (push 4 a) (pop a) none (setq a '(1 2 3)) (push 4 a) (pop a) | |||
| フラッテン (Flatten) (flatten '(1 2 (3 (4)))) | (flatten '(1 2 (3 (4)))) | ||
| 関連配列の検索 (assoc 3 '((1 2) (3 4))) | (assoc 3 '((1 2) (3 4))) | none, see note | (assoc 3 '((1 2) (3 4))) |
| フラットな関連配列の検索 (getf '(1 2 3 4) 3) | none none | (getf '(1 2 3 4) 3) | |
| ペアリテラル '(1 . 2) '(1 . 2) | none '(1 . 2) | ||
| リストセルのテスト (cons '(1 . 2)) (not (atom '(1 . 2))) | (cons? '(1 . 2)) | (pair? '(1 . 2)) | none (cons '(1 . 2)) (not (atom '(1 . 2))) |
| 要素の再帰的置換 (sublis '((1 . 2) (3 . 4)) '(1 (3 3 (1)))) | (sublis '((1 . 2) (3 . 4)) '(1 (3 3 (1)))) | ||
| 固定長配列 (Fixed-length Arrays) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| リテラル #(1 2 3) | #(1 2 3) | [1 2 3] | [1 2 3] |
| コンストラクタ (vector 1 2 3) | (vector 1 2 3) | (vector 1 2 3) | (vector 1 2 3) |
| サイズ (length #(1 2 3)) (vector-length #(1 2 3)) | (count [1 2 3]) (length [1 2 3]) | ||
| 検索 (Lookup) (elt #(1 2 3) 0) or (aref #(1 2 3) 0) (vector-ref #(1 2 3) 0) (nth [1 2 3] 0) (elt [1 2 3] 0) | |||
| 更新 (setq v [1 2 3]) (setf (aref v 2) 4) (define v (vector 1 2 3)) (vector-set! v 2 4) (replace {2 4} [1 2 3]) (setq v #(1 2 3)) (setf (aref v 2) 4) | |||
| 境界外動作 raises sb-kernel:index-too-large-error error | (reverse #(1 2 3)) | (sort #(2 4 1 3) #'<) | (map 'vector (lambda (x) (* x x)) #(1 2 3)) |
| 配列からリストへ (coerce #(1 2 3) 'list) (vector->list #(1 2 3)) | (seq [1 2 3]) (coerce [1 2 3] 'list) | ||
| リストから配列へ (coerce '(1 2 3) 'vector) (list->vector '(1 2 3)) | (vec '(1 2 3)) (coerce '(1 2 3) 'vector) | ||
| 畳み込み (Reduce) none | (filter (lambda (x) (> x 2)) #(1 2 3)); also remove-if | ||
| 辞書 (Dictionaries) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| リテラル none 不可変: #hash(("t" . 1) ("f" . 0)) Clojure.lang.PersistentArrayMap: {"t" 1 "f" 0} | none | ||
| コンストラクタ (defparameter h (make-hash-table :test 'equal)) デフォルトの等価性テストは 'eql (define ih (make-immutable-hash '(("t" . 1) ("f" . 0)))) 可変: (define h (make-hash '(("t" . 1) ("f" . 0)))) 不可変: (def ih (hash-map "t" 1 "f" 0)) (setq h (make-hash-table :test 'equal)) | |||
| 述語 (hash-table-p h) (hash? h) また、関連リストとベクトルにも適用: (dict? h) (map? ih) (hash-table-p h) | |||
| サイズ (hash-table-count h) (hash-count h) また、関連リストとベクトルにも適用: (dict-count ih) (count ih) (hash-table-count h) | |||
| 検索 (Lookup) (gethash "t" h) (hash-ref h "t") 見つからない場合は -1 を返す: (hash-ref h "m" -1) また、関連リストとベクトルにも適用: (dict-ref ih "t") (dict-ref ih "m" -1) (get ih "t") (find ih "t") 見つからない場合は -1 を返す: (get ih "m" -1) (gethash "t" h) | |||
| 更新 (setf (gethash "t" h) 1) (hash-set! h "t" 2) (define ih2 (hash-set ih "t" 2)) また、dict-set! と dict-set (def ih2 (assoc ih "t" 2)) (puthash "t" 1 h) | |||
| キーが存在しない場合の動作 nil を返す error nil を返す nil を返す | |||
| キーの有無チェック (nth-value 1 (gethash "t" h)) (hash-has-key? h "t") また、dict-has-key? (contains? ih "t") none | |||
| 削除 (Delete) (remhash "t" h) (hash-remove! h "t") (define ih2 (hash-remove ih "t")) また、dict-remove! と dict-remove (def ih2 (dissoc ih "t")) (remhash "hello" h) | |||
| マージ (Merge) ih2 の値が優先される: (define ih3 (merge ih ih2)) | (invert) (require 'clojure.set) (define ih4 (clojure.set/map-invert ih)) | ||
| 反復 (Iterate) (maphash (lambda (k v) (print k) (print v)) h) (hash-for-each h (lambda (k v) (printf " また、dict-for-each (doseq [p ih] (println (first p)) (println (second p))) (maphash (lambda (k v) (print k) (print v)) h) | |||
| キーと値をリストへ none (hash-keys h) (hash-values h) また、dict-keys と dict-values (def hkeys (map (fn [p] (first p)) ih)) (def hvals (map (fn [p] (second p)) ih)) none | |||
| ユーザー定義型 (User-defined Types) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| Defstruct (defstruct account id balance) (setq a (make-account :id 3 :balance 17.12)) (account-id a) (setf (account-balance a) 0) (account-p a) | account (id (balance #:mutable))(define a (make-account 3 17.12)) (account-id a) (set-account-balance! a 0) (account? a) | (defstruct account :id :balance) (def a (struct account 3 17.12)) (:id a) none *(account-p a) | |
| 構造体 (defstruct account id balance) (setq a (make-account :id 3 :balance 17.12)) (define a (make-account 3 17.12)) (def a (struct account 3 17.12)) *(setq a (make-account :id 3 :balance 17.12)) | |||
| 構造体のゲッター (account-id a) | (:id a) (account-id a) | ||
| 構造体のセッター (setf (account-balance a) 0) (set-account-balance! a 0) | none (setf (account-balance a) 0) | ||
| 構造体の述語 (account-p a) | (account? a) | none (account-p a) | |
| 関数 (Functions) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 関数の定義 (defun add (x y) (+ x y)) | (define (add x y) (+ x y)) | (defn add [x y] (+ x y)) | (defun add (x y) (+ x y)) |
| 関数と変数の名前共有 可能 不可能 不可能 可能 | |||
| オプション引数 (defun add (a &optional b) (if (null b) a (+ a b))) (define (add a (b null)) (if (null? b) a (+ a b))) (defn add ([a] a) ([a b] (+ a b))) 引数が 2 つより多く呼ばれる場合はエラーにならない: (defn add [a & [b]] (if (nil? b) a (+ a b))) (defun add (a &optional b) (if (null b) a (+ a b))) | |||
| 可変数個の引数 (defun add (a &rest b) (if (null b) a (+ a (eval (cons '+ b))))) (define (add a . b) (if (null? b) a (+ a (apply + b)))) (defn add [a & b] (if (nil? b) a (+ a (apply + b)))) (defun add (a &rest b) (if (null b) a (+ a (eval (cons '+ b))))) | |||
| デフォルト値 (defun add (a &optional (b 0)) (+ a b)) Racket: (define (add a (b 0)) (+ a b)) (defn add ([a] (add a 0)) ([a b] (+ a b))) | none | ||
| 名前付きパラメータ (defun logarithm (&key number base) (/ (log number) (log base))) (logarithm :base 2 :number 8) none (defn logarithm [{x :number b :base}] (/ (Math/log x) (Math/log b))) (logarithm {:base 2 :number 8}) (defun logarithm (&key number &key base) (if base (/ (log number) (log base)) (log number))) 順序が重要、キー名ではない: (logarithm :foo 8 :bar 2) | |||
| 複数の値を返す (defun sqrts (x) (values (sqrt x) (- (sqrt x)))) | (define (sqrts x) (values (sqrt x) (- (sqrt x)))) (defn sqrts [x] (list (Math/sqrt x) (- (Math/sqrt x)))) values はリストを作成: (defun sqrts (x) (values (sqrt x) (- (sqrt x)))) | (values creates a list) (values-list '(1 2 3)) (apply values '(1 2 3)) 複数の値はリスト 複数の値はリスト | |
| ローカル変数への複数値の割り当て (multiple-value-bind (r1 r2) (sqrts 3) r2) (let-values (((r1 r2) (sqrts 3))) r2) | (let [[r1 r2] (sqrts 3)] r2) | (multiple-value-bind (r1 r2) (sqrts 3) r2) | |
| グローバル変数への複数値の割り当て (multiple-value-setq (r1 r2) (sqrts 3)) (define-values (r1 r2) (sqrts 3)) | none | (multiple-value-setq (r1 r2) (sqrts 3)) | |
| リストから複数値への変換 (values-list '(1 2 3)) (apply values '(1 2 3)) 複数の値はリスト 複数の値はリスト | |||
| タイルコール最適化 (Tail Call Optimization) Sbcl 用には可能 可能 recur で可能 不可 | |||
| ラムダ (Lambda) (lambda (x) (* x x)) | (lambda (x) (* x x)) | #(* % %) 2 つの引数の簡略表記: #(* %1 %2) | (fn [x] (* x x)) ; 2 つの引数の簡略表記: #(* %1 %2) (lambda (x) (* x x)) |
| 適用 (Apply) ((lambda (x) (* x x)) 2) | (apply #'(lambda (x) (* x x)) '(2)) | ((lambda (x) (* x x)) 2) (apply (lambda (x) (* x x)) '(2)) (#(* % %) 2) ((fn [x] (* x x)) 2) (apply #(* % %) '(2)) ((lambda (x) (* x x)) 2) (apply #'(lambda (x) (* x x)) '(2)) | |
| 実行制御 (Execution Control) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| progn progn prog1 prog2 begin none none r6rs: begin begin0 none do none none | progn prog1 prog2 | ||
| ループ (Loop) (setq i 1) (loop (print "hello") (if (> i 10) (return) (setq i (+ i 1)))) | none, recursion を使用 (loop [i 1] (if (<= i 10) (do (println "hello") (recur (+ i 1))))) none (loop [i 1] (if (<= i 10) (do (println "hello") (recur (+ i 1))))) | ||
| Do (do ((i 1) (sum 0)) ((> i 100) sum) (setq sum (+ sum i)) (setq i (+ i 1))) do* は順次初期化 none (do ((i 1) (sum 0)) ((> i 100) sum) (setq sum (+ sum i)) (setq i (+ i 1))) do* は直列に初期化 | |||
| Dotimes (dotimes (i 10 nil) (format t "hello~%")) | (dotimes [_ 10] (println "hello")) (dotimes (i 10 nil) (print "hello\n")) | ||
| 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) (print "x is less ") (print "than y")) | Racket: (when (< x y) (display "x is less ") (display "than y")) (when (< x y) (println "x is less ") (println "than y")) (when (< x y) (print "x is less ") (print "than y")) | ||
| Cond (cond ((> x 0) 1) ((= x 0) 0) (t -1)) (cond ((> x 0) 1) ((= x 0) 0) (else -1)) (cond (> x 0) 1 (= x 0) 0 true -1) (cond ((> x 0) 1) ((= x 0) 0) (t -1)) | |||
| 遅延評価 (define x (delay (/ 1 0))) (promise? x) (+ 1 (force x)) | |||
| 継続 (Continuations) (define cc null) (+ 1 (call/cc (lambda (x) (set! cc x) 0))) (cc 5) | |||
| エラー処理 (Exceptions) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| エラー (error "failed") | (error "failed") | (throw (Exception. "failed")) | (error "failed") |
| エラー処理 (handler-case (error "failed") (simple-error (e) (format t "error: ~a" e))) (with-handlers ((exn:fail? (lambda (e) (printf "error: ~a" (exn-message e))))) (error "failed")) | (try (throw (Exception. "failure")) (catch Exception e (printf "error: %s" (.getMessage e)))) | (condition-case e (error "failed") (error (message "error: %s" (error-message-string e)))) | |
| エラーの定義 (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))))) (define exn:odd-err? "odd number") シンボルとキーワードのみがスローされ、キャッチできる | only symbols and keywords can be thrown and caught | ||
| 例外のスロー (error 'odd-err :num 7) (raise exn:odd-err?) | (throw (Exception. "failed")) | (throw 'odd-err t) | |
| 例外のキャッチ (handler-case (/ 1 0) (division-by-zero () (progn (format t "division by zero") nil))) (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) (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)) | none | ||
| Restart の呼び出し (handler-bind ((odd-err (lambda (c) (invoke-restart 'round-down)))) (halve '(1 2 4 9))) | none | ||
| Finally クロージャ (unwind-protect (error "failure") (print "clean up")) | none | (try (throw (Exception. "failure")) (finally (println "clean up"))) | (unwind-protect (error "failure") (print "clean up")) |
| ストリーム (Streams) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 標準ファイルハンドル standard-input standard-output error-output | (current-input-port) (current-output-port) (current-error-port) | in out err | |
| EOF 動作 read-line は 2 つの値を返し、2 目は EOF で T に設定される。ファイル終了以降には read を試すと EOF-OF-FILE がスローされる。 Returns the value eof. Use eof-object? to test for it. .readLine on a java.io.Reader object returns nil. | read-line は改行を破棄 write-string s (newline) (println "hello") | ||
| stdin から 1 行読み込み (setq line (read-line)) (let ((s (read-line))) #|use s# | ) | (let [s (read-line)] (comment use s)) | |
| 改行の削除 (Chomp) read-line は改行を破棄 | read-line は改行を破棄 | ||
| stdout に 1 行書き出し (defun println (s) (format t " (println "hello") (write-string s) (newline) (println "hello") | (printf "%s %d %.2f\n" "foo" 7 13.7) | ||
| フォーマットされた文字列の stdout への書き出し (format t "~s ~d: (printf "~a ~a: | |||
| ファイルの読み込みオープン (setq in (open "/etc/hosts")) (let ((f (open-input-file "/etc/hosts"))) #| use f # | ) f は java.io.Reader オブジェクト: (let [f (clojure.java.io/reader "/etc/hosts")] (.readLine f)) | ||
| ファイルの書き込みオープン (setq out (open "/tmp/test" :direction :output :if-exists :supersede)) (let ((f (open-output-file "/tmp/foo" #:exists 'truncate))) #| use f # | ) f は java.io.Writer オブジェクト: (let [f (clojure.java.io/writer "/tmp/foo")] (.write f "lorem ipsum\n") (.close f)) | ||
| ファイルの追加書き込みオープン (setq out (open "/tmp/test" :direction :output :if-exists :append)) (let ((f (open-output-file "/tmp/foo" #:exists 'append))) #| use f # | ) (let [f (clojure.java.io/writer "/tmp/foo" :append true)] (.write f "lorem ipsum\n") (.close f)) | ||
| ファイルの閉鎖 (close in) (close-input-port f) (close-output-port f) | (.close f) | ||
| 明示的なファイル閉鎖 (with-open-file (out #P"/tmp/test" :direction :output) (write-line "lorem ipsum" out)) (call-with-input-file "/etc/hosts" (lambda (f) (#| use f # | ))) また、call-with-output-file (with-open [f (clojure.java.io/reader "/etc/hosts")] (comment use f)) | ||
| 1 行読み込み (setq line (read-line f)) (define line (read-line in)) | (.readLine f) | ||
| ファイルの反復 (1 行単位) (for ([line (in-lines (open-input-file "/etc/hosts"))]) (write-string line) (newline)) (loop [line (.readLine f)] (if (not= line nil) (do (println line) (recur (.readLine f))))) | |||
| ファイルを文字列配列へ読み込み 文字列のリストへ: (sequence->list (in-lines (open-input-file "/etc/hosts"))) | (vec (line-seq f)) | ||
| ファイルを文字列へ読み込み (define s (file->string "/etc/hosts")) (let [s (slurp "/etc/hosts")] (print s)) | |||
| 文字列の書き出し (write-string s f) (.write f s) | |||
| 1 行の書き出し (write-string s f) (newline f) (.write f (println-str s)) | |||
| ファイルハンドルのフラッシュ (flush-output f) (f .flush) | |||
| ファイルハンドル位置 get, set 非負の整数として評価: (file-position f) 次回の読み書きをファイル先頭へ設定: (file-position f 0) 引数は現在の位置から文字数; 後ろ移動は不可能: (.skip f 1000) バッファする最大文字数: (.mark f 1000000) mark 時の位置へ移動: (.rest f) | |||
| メモリストリーム (setq f (make-string-input-stream "lorem ipsum")) (read-line f) (setq f2 (make-string-output-stream)) (write-string "lorem ipsum" f2) (get-output-stream-string out) (define f (open-input-string "lorem ipsum")) (read-line f) (define f2 (open-output-string)) (write-string "lorem ipsum" f2) (get-output-string f2) 文字列からの読み込み: (with-in-str "lorem ispum" (read-line)) 文字列への書き込み: (with-out-str (println "lorem ipsum")) | |||
| Emacs バッファ |
| Emacs Lisp |
|---|
| バッファリストの作成 ;; バッファオブジェクトのリスト: (buffer-list) ;; リスト内の最初のバッファ名: (buffer-name (car (buffer-list))) ;; 現在のバッファ名: (buffer-name (current-buffer)) |
| 現在バッファ get and set ;; 現在のバッファ名: (buffer-name (current-buffer)) ;; 現在のパネでオープン: (switch-to-buffer "foo.txt") ;; 他のパネでオープン: (switch-to-buffer-other-window "bar.txt") |
| バッファのクリア ;; 現在のバッファ: (erase-buffer) ;; "foo.txt" という名前のバッファ: (with-current-buffer "foo.txt" (erase-buffer)) |
| カーソル位置 (Point) get and set ;; カーソルの下の文字の 1 ベースインデックス: (point) ;; 現在のバッファの先頭へ移動: (goto-char 1) ;; 現在のバッファの末尾へ移動: (goto-char (buffer-size)) |
| 検索と Point の設定 ;; 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) |
| 文字列の Point への挿入 ;; 1 つ以上の引数を受け取る: (insert "lorem" " ipsum") |
| バッファを文字列へ (buffer-string) |
| Point へのファイル内容の挿入 (insert-file "/etc/passwd") |
| マーク (Mark) get and set ;; 現在のバッファの先頭: (set-mark 1) ;; 現在のバッファの Point へ: (set-mark (point)) |
ファイル (Files)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| ファイルテスト、通常ファイルテスト (osicat:file-exists-p "/tmp/foo") (osicat:regular-file-exists-p "/tmp/foo") | ?? | (file-exists? "/etc/hosts") (.exists (io/file "/etc/hosts")) | (file-exists-p "/etc/hosts") (file-regular-p "/etc/hosts") |
| ファイルサイズ (file-size "/etc/hosts") | (.length (io/file "/etc/hosts")) | (eighth (file-attributes "/etc/hosts")) | |
| 読み込み/書き込み/実行許可テスト (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"))) | (.canRead (io/file "/etc/hosts")) (.canWrite (io/file "/etc/hosts")) (.canExecute (io/file "/etc/hosts")) | ||
| ファイル権限の設定 (file-or-directory-permissions "/tmp/foo" #o755) (set-file-modes "/tmp/foo" #o755) | |||
| 最終変更時刻 (file-or-directory-modify-seconds "/tmp/foo") UNIX epoch in milliseconds: (.lastModified (java.io.File. "/tmp/foo")) | |||
| ファイルのコピー、削除、改名 (cl-fad:copy-file #P"/tmp/foo" #P"/tmp/bar") (delete-file #P"/tmp/foo") (rename-file #P"/tmp/bar" #P"/tmp/foo") (copy-file "/tmp/foo" "/tmp/bar") (delete-file "/tmp/foo") (rename-file-or-directory "/tmp/bar" "/tmp/foo") | (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")) (copy-file "/tmp/foo" "/tmp/bar") (delete-file "/tmp/foo") (rename-file "/tmp/bar" "/tmp/foo") | ||
| シンボリックリンクの作成、テスト、ターゲット取得 (osicat:make-link "/tmp/hosts" :target "/etc/hosts") (make-file-or-directory-link "/etc/hosts" "/tmp/hosts") (link-exists? "/tmp/hosts") | ?? | (make-symbolic-link "/etc/hosts" /tmp/hosts") シンボリックリンクまたは nil の場合、ターゲットを返す: (file-symlink-p "/tmp/hosts") | |
| 一時ファイル (define tmp (make-temporary-file)) (path->string tmp) java.io.File: (java.io.File/createTempFile "foo" ".txt") | (make-temp-file "foo") |
ディレクトリ (Directories)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| パス名の構築 (make-pathname :directory '(:absolute "etc") :name "hosts") パスを返す; 文字列へ変換するには path->string を使用: (build-path "/etc" "hosts") | (require '[clojure.java.io :as io]) java.io.File を返す; 文字列へ変換するには .getPath を使用: (io/file "/etc" "hosts") | ||
| ディレクトリ名とファイル名の取得 (pathname-directory #P"/etc/hosts") (pathname-name #P"/etc/hosts") | (let-values (((dir file _) (split-path "/etc/hosts"))) #| use dir or file # | ) | (.getParent (io/file "/etc/hosts")) (.getName (io/file "/etc/hosts")) |
| 絶対パス (simplify-path (path->complete-path "..")) | (.getCanonicalPath (java.io.File. "..")) | (expand-file-name "..") | |
| ディレクトリの反復 (ファイル単位) (dolist (file (osicat:list-directory "/tmp")) (format t " (for ([path (directory-list "/etc")]) (write-string (path->string path))) file-seq は引数ディレクトリとサブディレクトリ再帰的にファイルの java.io.File オブジェクトを返す: (filter #(= (.getParent %) "/etc") (file-seq (clojure.java.io/file "/etc"))) | (dolist (file (directory-files "/etc")) (print file)) | ||
| ディレクトリの作成 (make-directory* "/tmp/foo/bar") 2 目の引数が nil でない場合、親ディレクトリを作成: (make-directory "/tmp/foo/bar" t) | |||
| 再帰コピー (copy-directory/files "/tmp/foo.d" "/tmp/bar.d") | |||
| 空ディレクトリの削除 (delete-directory "/tmp/foo.d") | (delete-directory "/tmp/foo.d") (clojure.java.io/delete-file "/tmp/foo.d") | (delete-directory "/tmp/foo.d") | |
| ディレクトリと内容の削除 (osicat:delete-directory-and-files "/tmp/foo.d") | (delete-directory/files "/tmp/foo.d") | (delete-directory "/tmp/foo.d" t) | |
| ディレクトリテスト (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 |
|---|---|---|---|
| コマンドライン引数 posix-argv | current-command-line-arguments | command-line-args shebang モードのみ: command-line-args or argv | |
| プログラム名 | |||
| 環境変数 (posix-getenv "HOME") | (getenv "HOME") | (System/getenv "HOME") | (getenv "HOME") |
| ユーザー ID と名前 | |||
| 終了 | |||
| 外部コマンド (run-program "ls" '("/etc")) | (require scheme/system) (system "ls /etc") (.exec (Runtime/getRuntime) "ls") | (shell-command "ls /etc") | |
| コマンド置換 (shell-command-to-string "ls /etc") |
ライブラリと名前空間 (Libraries and Namespaces)
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
完全な例(ns b.a) (def x 3) <br=> (require 'b.a)<br=> b.a/x3 | コンパイルライブラリ (compile-file "a.lisp") (compile 'a) | ロードライブラリ (load "a.lisp") | |
| サブディレクトリのライブラリ読み込み (load "b/a.lisp") | (require "b/a.rkt") (require 'b.a) | ||
| ホットパッチ (load "a.lisp") | none | (require 'b.a :reload) (load "a") | |
| ロードエラー raises sb-int:simple-file-error | raises exn:fail:syntax:missing-module. require はトップレベルである必要があるため、例外は処理できない。 raises FileNotFoundException raises file-err | ||
| ライブラリパス 起動時に作業ディレクトリが含まれる (require setup/dirs) (get-collects-search-dirs) | same as path used by java VM 追加: (add-to-list 'load-path ("/home/ed/.emacs.d/lib")) | EMACSLOADPATH | |
| ライブラリパス環境変数 | none | CLASSPATH | |
| コマンドラインオプション none | $ java -cp /foo/bar:/baz/quux $ emacs -L /foo/bar | ||
| 名前空間宣言 (defpackage :foo) | (module mconst racket (provide pi) (define pi 3.14)) | (ns mconst) | No namespaces; library のすべての識別子にハイフンで区切られたプレフィックスを使用する一般的な慣習がある。 |
| サブ名前空間宣言 | none b/a.clj でなければならない: (ns b.a) | ||
| 名前空間のセパレータ : | : | . and / | |
| インポート定義 *現在の package を foo に設定し、twiddle を bar からインポート: (defpackage :foo (:import-from :bar :twiddle)) | |||
| 名前空間のすべての定義をインポート *現在の package を foo に設定し、bar のシンボルをインポート: (defpackage :foo (:use :bar)) | |||
| 名前空間のシャドウ回避 | |||
| 識別子のシャドウ回避 | |||
パッケージマネージャーヘルプM-x list packages | M-x list-packages | ||
インストールされたパッケージのリスト | |||
| パッケージの検索 (ql:system-apropos "time") http://pkgs.racket-lang.org | M-x list-packages | ||
| パッケージのインストール quicklisp のインストール: (load "~/quicklisp/setup.lisp") (ql:quickload "osicat") M-x list-packages でパッケージメニューを開く; i で選択、x でインストール。 | |||
パッケージの削除 | パッケージメニューで d で選択、x でアンインストール。 | ||
| オブジェクト (Objects) |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| クラスの定義 (defclass rectangle () ((height :accessor rectangle-height :initarg :height) (width :accessor rectangle-width :initarg :width))) | (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)))) | use java: public class Rectangle { public float height; public float width; ... } public void setHeight(float h) {...} public void setWidth(float w) {...} | |
| インスタンスの作成 (make-instance 'rectangle :height 3 :width 7) (define rect (new rectangle (height 7) (width 3))) (import 'Rectangle) (def r (Rectangle. 7 3)) | (.height r) (.setHeight r 8) | ||
| 属性の読み取り (rectangle-height rect) | (send rect get-height) | ||
| 属性の書き込み (setf (rectangle-height rect) 4) (send rect set-height 4) | (.setHeight r 8) | ||
| メソッドの定義 (defmethod area ((figure rectangle)) (* (rectangle-height figure) (rectangle-width figure))) | (define/public (area) (* curr-height curr-width)) | (defmulti area class) (defmethod area Rectangle [r] (* (.height r) (.width r))) | |
| メソッドの呼び出し (area rect) | (send rect area) | (area r) | |
| 普遍的な上位クラス standard-object t | object% | Object | |
| 多重継承 | 可能 不可 1 つの直接上位クラスのみ; 複数のインタフェースを実装可能 | ||
| Lisp マクロ |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| Backquote と Comma (setq op '+) (eval `(,op 1 1)) | (define op '+) (eval `(,op 1 1)) | (eval (quasiquote ((unquote op) 1 1))) | (def op +) (eval `(,op 1 1)) *(setq op '+) (eval `(,op 1 1)) |
| Defmacro (defmacro rpn (arg1 arg2 op) (list op arg1 arg2)) | (define-syntax-rule (rpn arg1 arg2 op) (op arg1 arg2)) | (defmacro rpn [arg1 arg2 op] (list op arg1 arg2)) | (defmacro rpn (arg1 arg2 op) (list op arg1 arg2)) |
| Backquote での Defmacro (defmacro rpn (arg1 arg2 op) `(,op ,arg1 ,arg2)) | (define-syntax-rule (rpn3 arg1 arg2 op) (eval '(,op ,arg1 ,arg2))) | (defmacro rpn [arg1 arg2 op] `(~op ~arg1 ~arg2)) | (defmacro rpn (arg1 arg2 op) `(,op ,arg1 ,arg2)) |
| マクロ述語 (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) `(+ ,@args)) | (define-syntax-rule (add first ...) (+ first ...)) | (defmacro add [& args] `(~@args ~@arg1)) | (defmacro add (&rest args) `(,op ,@args)) |
| 再帰マクロ (defmacro add (a &rest b) `(if (null ',b) (+ ,a) (+ ,a (add ,@b)))) | (define-syntax add (syntax-rules () [(add x) x] [(add x y) (+ x y)] [(add x y ...) (+ x (add y ...))])) | (defmacro add ([a] `(,~a)) ([a & b] `(,~a (add ~@b)))) | (defmacro add (a &rest b) `(if (null ',b) (+ ,a) (+ ,a (add ,@b)))) |
| 衛生的 (Hygienic) 不可 可能 # 接尾符付きで可能 不可 | |||
| ローカル値 (defmacro square-sum (x y) (let ((sum (gensym))) `(let ((,sum (+ ,x ,y))) (* ,sum ,sum)))) | (define-syntax-rule (square-sum x y) (let ((sum (+ x y))) (* sum sum))) | (defmacro two-list [x] `((let [arg# ~x]) (list arg# arg#))) (defmacro square-sum (x y) (let ((sum (gensym))) `(let ((,sum (+ ,x ,y))) (* ,sum ,sum)))) | |
| リフレクション |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 型を調査 (type-of '(1 2 3)) (typep '(1 2 3) 'list) (listp '(1 2 3)) | (type-of [1 2 3] 'vector) (typep [1 2 3] 'vector) (vectorp [1 2 3]) | (= (type 1) java.lang.Long) (= (class 1) java.lang.Long) (integer? 1) | |
| インスタンスの所属 instance-of | instance? | ||
| 基本型 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-byte symbols and strings: base-character character extended-character keyword simple-string standard-char string symbol data structures: array atom bit-vector cons hash-table list sequence simple-array simple-bit-vector simple-vector vector other: compiled-function function package pathname random-state stream | all collections and strings list vector sequence data types list vector hash-table string input-port range | get docstring (describe #'mapcar) (none) (doc map) (describe-function 'mapcar) | |
| ドキュメント文字列付き関数の定義 (defun add (x y) "add x and y" (+ x y)) | none defn add "add x and y" [x y] (+ x y) | (defun add (x y) "add x and y" (+ x y)) | |
| Apropos とドキュメント検索 none none | (apropos #"^add$") (find-doc #"add \S+ and \S+") | (apropos "^add$") none | |
| Java インタラプション |
| Common Lisp | Racket | Clojure | Emacs Lisp |
|---|---|---|---|
| 新しいオブジェクト作成 (def rnd (new java.util.Random)) (def rnd (java.util.Random.)) | (. rnd nextFloat) (.nextFloat rnd) (. rnd nextInt 10) (.nextInt rnd 10) | (Math/sqrt 2) | |
| メソッド | (import '(java.util Random)) (def rnd (Random.)) | ||
| クラスメソッド | (to-array '(1 2 3)) | (into-array Integer '(1 2 3)) | |
| JVM のバージョンと追加ライブラリ racket: The srfi-1 library brings in a common list functions which Kawa does not make available by default. See SRFI. ANSI Specification SBCL User Manual Quicklisp パッケージマネージャーとして Quicklisp を使用: * インストールと cl-ppcre のロード方法: * (load "quicklisp.lisp") * (quicklisp-quickstart:install) * (ql:quickload "cl-ppcre") * (cl-ppcre:all-matches "foo" "foo bar") Quicklisp はユーザーのホームディレクトリに quicklisp ディレクトリを作成: * (load " * (ql:quickload "cl-ppcre") * (cl-ppcre:all-matches "foo" "foo bar") 起動時に自動的に Quicklisp をロードするには、.sbclrc ファイルにロードコマンドを入れる: (load " | Racket Guide: Racket Reference: Racket PLaneT: Racket Packages Racket の collects ディレクトリには多くのライブラリが含まれ、require コマンドでロード可能: raw symbol が collects ディレクトリからの相対パス。 Racket 5.1 には 50 つの SRFI ライブラリが含まれる。 ビルトインのパッケージ管理システムも備える。利用可能なパッケージのリストを表示、詳細ページから require 文字列を取得。 > (require (planet "spgsql.rkt" ("schematics" "spgsql.plt" 2 3))) ファイルは ~/Library/Racket にインストール。 | Clojure Clojure Reference Clojure Cheat Sheet Calling Java: (def rnd (new java.util.Random)) ; Java object 作成 (. rnd nextFloat) ; オブジェクト上のメソッド呼び出し (. rnd nextInt 10) ; 引数付きメソッド呼び出し (. Math PI) ; 静的メンバー (import '(java.util Random)) ; インポート Clojure は java.lang のすべてを自動的にインポート。 短縮形: (Random.) (new Random) Math/PI (. Math PI) (.nextInt rnd) (. rnd nextInt) primitive 型のため、Java 配列に特化した関数: (make-array CLASS LEN) (make-array CLASS DIM & DIMS) (aset ARY IDX VAL) (aget ARY IDX) (alength JARY) (to-array SEQ) (into-array TYPE SEQ) (amap ARY I COPY EXPR) (areduce ARY IDX COPY INIT EXPR) | Emacs Lisp GNU Emacs Manual GNU Emacs Lisp Reference Manual Emacs 内での導入: M-x lisp-interaction-mode で Lisp インタラクションモードへ。 C-x e で現在の行の s-expression を評価。 M-x eval-buffer でバッファ全体を評価。 Lisp インタラクションモードで関数を定義: (defun dired-emacs-lisp () "Open the Emacs Lisp directory in dired." (interactive) (dired "/Applications/Emacs.app/Contents/Resources/lisp")) 関数は M-x dired-emacs-lisp で呼べる。 Lisp 関数の一部はコマンドとして呼び出せる。 コマンドの本体にはオプションの説明文字列があり、followed by interactive call. M-x describe-function で機能名を入力すると説明を表示。 interactive は Lisp 関数をコマンドにする。 キー C-c l にバインド: (global-set-key "\C-cl" 'dired-emacs-lisp) 起動時に常時利用可能なら ~/.emacs.d/init.el に置く。 |