Common Lisp
インストール
dockerで使う
| docker run --rm -it -v ${PWD}$:/home/cl clfoundation/cl-devel:latest sbcl
|
roswell
Chromebook
GitHub公式の情報にしたがってソースからインストールする. 作業時はcd /tmp
しよう. 途中でエラーが出たらros install quicklisp
を実行. EmacsでSLIMEが実行できない場合はros install slime
.
Mac
| brew install roswell
ros install sbcl-bin quicklisp slime fukamachi/cl-project
|
Windows
scoop
でインストールする以外にバイナリのインストールもある.
- バイナリでインストールする.
/path/to/roswell
と.roswell/lisp/quicklisp/bin
にパスを通す. ros setup
ros install slime sbcl-bin
roswell-slime
連繋は~/.roswell/helper.el
を読み込む. .roswell/init.lisp
でREPL初期読み込みライブラリを設定できる.
必要に応じて以下インストールする.
MIT-Scheme
| docker run -it --rm --name ms -p 10000:8888 --mount type=bind,source=$(pwd),destination=/work kkwok/jupyter-mit-scheme jupyter notebook --ip=0.0.0.0 --allow-root --NotebookApp.token=''
|
参考
HyperSpec
HyperSpec は LispWorks が提供している ANSI Common Lisp の仕様書. 検索時も「clhs restart-case」が便利. EmacsのewwでCommonLispのHyperSpecをHack!の方法が便利.
エラー処理用メモ
高速化
ライブラリの調べ方
Quickdocs と CLiki で Common Lisp 製のライブラリの情報を目的別に調べられる.
- Quickdocs: Common Lisp 製ライブラリのドキュメントサイト
- CLiki: Common Lisp Foundation が運営している Common Lisp の Wiki
学習資料
A Road to Common Lisp 翻訳にある勉強順
- [元記事の翻訳]](https://gist.github.com/y2q-actionman/49d7587912b2786eb68643afde6ca192)にある勉強の順.
- Common Lisp: A Gentle Introduction to Symbolic Computation
- Practical Common Lisp
- 邦訳は 実践Common Lisp
- https://gigamonkeys.com/book/
- 言語仕様
- 単純に Google で "clhs なんとか" と検索してもいい
- Sketch を使って Coding Math videos の何かを実装してみる
- https://github.com/vydd/sketch
- https://www.youtube.com/user/codingmath/videos
- Paradigms of Artificial Intelligence Programming
- Common Lisp Recipes
- Richard Gabriel の Patterns of Software: 著者のサイトでPDF形式で入手できる
- On Lisp
- Let Over Lambda
- Object-Oriented Programming in COMMON LISP: A Programmer's Guide to CLOS
- The Art of the Metaobject Protocol
- Land of Lisp
雑多なメモ
TIPS
クォートつきリストを返すときの注意
On LispのP.28にある注意. 下手な書き方をすると関数内のクォートつきリストを書き換えてしまう.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | (ql:quickload :rove)
(use-package :rove)
(testing "P.28, place to quote 1"
(flet ((exclaim1 (expression)
(append expression '(oh my))))
(ok '(exclaim1 '(lions and tigers and bears))
'(LIONS AND TIGERS AND BEARS OH MY))
(ok '(nconc * '(goodness))
'(LIONS AND TIGERS AND BEARS OH MY GOODNESS))
(ok '(exclaim1 '(fixnums and bignums and floats))
'(FIXNUMS AND BIGNUMS AND FLOATS OH MY GOODNESS))))
(testing "P.28, place to quote 2"
(flet ((exclaim2 (expression)
(append expression (list 'oh 'my))))
(ok '(exclaim2 '(lions and tigers and bears))
'(LIONS AND TIGERS AND BEARS OH MY))
(ok '(nconc * '(goodness))
'(LIONS AND TIGERS AND BEARS OH MY GOODNESS))
(ok '(exclaim2 '(fixnums and bignums and floats))
'(FIXNUMS AND BIGNUMS AND FLOATS OH MY))))
|
apply, funcall
| ;; 以下は等価
(+ 1 2)
(apply #'+ '(1 2))
(apply (symbol-function '+) '(1 2))
(apply #'(lambda (x y) (+ x y)) '(1 2))
(apply #'+ 1 '(2))
(funcall #'+ 1 2)
|
do, dolist, dotimes
do
| (do (variable-definition*)
(end-test-form result-form*)
statement*)
|
dolist
| ;;; (dotimes (var limit result) S式)
(dolist (x '(0 1 2 3 4)) (print x))
|
dotimes
| ;;; (dolist (var init-form result) S式)
(dotimes (x 5) (print x))
|
例: フィボナッチ
| (do ((n 0 (1+ n))
(cur 0 next)
(next 1 (+ cur next)))
((= 10 n) cur))
|
例
次の二つは同じ.
| (dotimes (i 4) (print i))
(do ((i 0 (1+ i)))
((>= i 4))
(print i))
|
fold
Common Lisp では reduce
.
| (reduce #'max '(1 2 3 4))
|
基本
| (format t "hello, world")
(format t "hello, ~a" '(1 2 3))
(format t "x: ~d y: ~d" 20.1 3)
|
注意
直接数は渡せないので "~a" の仲介が必要.
値の文字列化
(format t "hello, world")
で t
を nil
にすると数値を文字列化できる.
loop
いろいろな使い方ができる化け物マクロなので, 少しずつためていく.
整数からなるリストを作る
| (loop :for i :below 5 :collect i)
(loop for i from 1 to 10 collecting i)
|
二重ループ
| (loop for x downfrom 999 to 900
append (loop for y downfrom 999 to 900
collect (format nil "~a" (* x y))))
|
while
| (let ((i 0) (fibval 0) (fibs ())
(xs ())
(lastval 4000000))
(loop while (< fibval lastval)
do (progn
(setq fibval (fib-memo i)
i (incf i))
(when (< fibval lastval)
(setq fibs (cons fibval fibs))))))))
|
MISC
| (loop for x from 1 to 10 summing (expt x 2)) ;==> 385
(loop :for i :from 3 :upto 5 :do (print i))
(loop :repeat 5 :do (format t "~&five"))
(loop :for i :upto 5 :do (format t "~&~A" i))
;;; This counts the number of vowels in a string:
(loop for x across "the quick brown fox jumps over the lazy dog"
counting (find x "aeiou"))
|
mapcar
詳しくは hyperspec 参照. map
だと書式が違う.
| (print (mapcar #'1+ '(1 2 3)))
|
remove-if-not: いわゆる filter
| (remove-if-not #'(lambda (x) (if (oddp x) (1+ x)))
'(1 2 3 4))
|
paredit
progn: 一箇所に処理をたくさん書きたいとき
loop while do
の do
のように, 1 つのフォームしか書けないところでたくさん処理を書きたいときは, progn
でくくった中に書けばいい.
roswell
quicklispでのインストール先
.roswell/lisp/quicklisp/dists/quicklisp/software
SLIME
有用コマンド
関数のクォート
| (defun sq (x) (* x x))
(mapcar #'sq '(1 2 3 4))
|
述語式
=
, eq
, equal
, equalp
条件文
cond
| (cond
((equal (mod x 3) 0) x)
((equal (mod x 5) 0) x))
(t x))
|
if
when
数学関係
累乗
配列
| (make-array 3)
(make-array 3 :element-type 'list :initial-element nil)
(make-array 3 :initial-contents '(1.0 2.0 3.0))
(let ((a #(1.0 2.0 3.0)))
(format nil "~A" a))
|
ハッシュテーブル・連想リスト
Python でいう dictionary
のこと.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | ;;; ハッシュテーブル
(let ((hash (make-hash-table)))
(setf (gethash 'color hash) 'red)
(setf (gethash 'height hash) 185)
(setf (gethash 'weight hash) 110)
(setf (gethash 'name hash) "Mukku")
(maphash #'(lambda (k v) (format t "~a => ~a~%" k v)) hash)
(loop for key being each hash-key of hash
using (hash-value value)
do (format t "~A => ~A~%" key value))
)
;;; 連想リスト
(let ((alst '()))
(push '(:color :red) alst)
(push '(height 185) alst)
(push '(weight 110) alst)
(format t "~&~a" (assoc :color alst))
(format t "~&~a" (assoc 'height alst))
(format t "~&~a" (assoc 'weight alst))
(format t "~&~a" alst))
|
マクロ展開
Backquote Syntax | Equivalent List-Building Code | Result |
`(a (+ 1 2) c) | (list 'a '(+ 1 2) 'c) | (a (+ 1 2) c) |
`(a ,(+ 1 2) c) | (list 'a (+ 1 2) 'c) | (a 3 c) |
`(a (list 1 2) c) | (list 'a '(list 1 2) 'c) | (a (list 1 2) c) |
`(a ,(list 1 2) c) | (list 'a (list 1 2) 'c) | (a (1 2) c) |
`(a ,@(list 1 2) c) | (append (list 'a) (list 1 2) (list 'c)) | (a 1 2 c) |
メモ化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | ;;; https://takeokunn.xyz/blog/post/common-lisp-fibonacci
;;; フィボナッチ数列
(defun memo (fn)
(let ((table (make-hash-table :test 'equal)))
#'(lambda (&rest rest)
(multiple-value-bind (val found-p) (gethash rest table)
(if found-p
val
(setf (gethash rest table) (apply fn rest)))))))
(defun memoize (fn-name)
(setf (symbol-function fn-name)
(memo (symbol-function fn-name))))
(defmacro defun-memo (fn args &body body)
`(memoize (defun ,fn ,args . ,body)))
(defun fib (n)
(if (<= n 1) 1
(+ (fib (- n 1)) (fib (- n 2)))))
(defun-memo fib-memo (n)
(if (<= n 1) 1
(+ (fib-memo (- n 1)) (fib-memo (- n 2)))))
|
文字列
文字を数値化
文字列を数値化
| (parse-integer "1")
(parse-integer "11" :radix 2)
(parse-integer "11" :radix 8)
(parse-integer "11" :radix 10)
(parse-integer "11" :radix 16)
(read-from-string "1/10")
(read-from-string "1.2")
(read-from-string "#c(1 1)")
|
反転
リストとその処理
最大値を取る
| (reduce #'max '(1 2 3 4))
|