2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 1/99
Lispの同図像性とその周辺Lispの同図像性とその周辺
leaf.el, seml-mode.elの内部構造に触れながらleaf.el, seml-mode.elの内部構造に触れながら
山下直哉(@conao3)山下直哉(@conao3)
2019-05-082019-05-08
東京Emacs勉強会- 端午の節句at LINE株式会社東京Emacs勉強会- 端午の節句at LINE株式会社
1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 2/99
Table of ContentsTable of Contents
はじめに
Lispの評価器について
use-package by jwiegley
leaf.el
cort-test.el
seml-mode.el
まとめ
2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 3/99
はじめにはじめに
3 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 4/99
自己紹介自己紹介
山下直哉(conao3)
学業
広島大学工学部第2類
量子材料科学研究室(進振り失敗の結果、二回目の)4年
生
金や銅の基板に薬品をかけ、ナノレベルの計測/評
価
趣味
Emacsのパッケージ開発
資格取得(応用情報(AP)/CCNP/情報科教員免許)
GitHubに草を生やす
3 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 5/99
GitHubの草GitHubの草
3 . 3
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 6/99
普段、Emacsをどんなことに使っていますか?普段、Emacsをどんなことに使っていますか?
3 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 7/99
普段、Emacsをどんなことに使っていますか?普段、Emacsをどんなことに使っていますか?
Emacsのために
Emacsを使っている
3 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 8/99
やることスタックやることスタック
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 9/99
やることスタックやることスタック
競プロしたい!
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 10/99
やることスタックやることスタック
競プロしたい!
当然Emacs
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 11/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 12/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 13/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 14/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 15/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 16/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 17/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
feather-melpa 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 18/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
feather-melpa 開発
feather-server.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 19/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
feather-melpa 開発
feather-server.el 開発
leaf-browser.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 20/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
feather-melpa 開発
feather-server.el 開発
leaf-browser.el 開発
seml-mode.el 開発
3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 21/99
やることスタックやることスタック
競プロしたい!
当然Emacs
init.el編集
use-package
leaf.el 開発
cort-test.el 開発
feather.el 開発
feather-recipes.el 開発
feather-melpa 開発
feather-server.el 開発
leaf-browser.el 開発
seml-mode.el 開発
orglyth.el 開発 3 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 22/99
いろんなパッケージをElispで書いてみていろんなパッケージをElispで書いてみて
3 . 6
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 23/99
いろんなパッケージをElispで書いてみていろんなパッケージをElispで書いてみて
同図像性ってすごい!!
3 . 6
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 24/99
いろんなパッケージをElispで書いてみていろんなパッケージをElispで書いてみて
同図像性ってすごい!!
同図像性を使わずにElispのパッケージを書くほうが難しい
3 . 6
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 25/99
同図像性とは同図像性とは
3 . 7
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 26/99
同図像性とは同図像性とは
データとプログラムが
同じ形式で書ける
3 . 7
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 27/99
今回の目的今回の目的
3 . 8
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 28/99
今回の目的今回の目的
俺、いま同図像性使って
書いてんなー汗
3 . 8
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 29/99
今回の目的今回の目的
俺、いま同図像性使って
書いてんなー汗
くらいの知ったかぶり認識ができるようになる
3 . 8
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 30/99
evalとbackquote - 初級編evalとbackquote - 初級編
eval とbackquote の相性は悪魔的
'(+ 1 2 3 4 5 (+ 1 2 3 4 5))
;; => (+ 1 2 3 4 5 (+ 1 2 3 4 5))
`(+ 1 2 3 4 5 ,(+ 1 2 3 4 5))
;; => (+ 1 2 3 4 5 15)
(eval
`(+ 1 2 3 4 5 ,(+ 1 2 3 4 5)))
;; => 30
3 . 9
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 31/99
evalとbackquote - 中級編evalとbackquote - 中級編
(number-sequence 1 5)
;; => (1 2 3 4 5)
`(+ 1 2 3 4 5 ,(number-sequence 1 5))
;; => (+ 1 2 3 4 5 (1 2 3 4 5))
`(+ 1 2 3 4 5 ,@(number-sequence 1 5))
;; => (+ 1 2 3 4 5 1 2 3 4 5)
(eval
`(+ 1 2 3 4 5 ,@(number-sequence 1 5)))
;; => 30
3 . 10
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 32/99
evalとbackquote - 上級編evalとbackquote - 上級編
`(+ (+ ,@(number-sequence 1 5))
(+ ,@(number-sequence 11 15))
(+ ,@(number-sequence 21 25)))
;; => (+ (+ 1 2 3 4 5) (+ 11 12 13 14 15) (+ 21 22 23 24 25))
`(+ ,@(mapcar (lambda (elm)
`(+ ,@(number-sequence (car elm) (cdr elm))))
'((1 . 5) (11 . 15) (21 . 25))))
;; => (+ (+ 1 2 3 4 5) (+ 11 12 13 14 15) (+ 21 22 23 24 25))
(eval
`(+ ,@(mapcar (lambda (elm)
`(+ ,@(number-sequence (car elm) (cdr elm))))
'((1 . 5) (11 . 15) (21 . 25)))))
;; => 195
3 . 11
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 33/99
つまりつまり
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 34/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 35/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 36/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
すべての問題解決をリスト操作に還元する
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 37/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
すべての問題解決をリスト操作に還元する
evalした結果もS式を返す場合、
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 38/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
すべての問題解決をリスト操作に還元する
evalした結果もS式を返す場合、
結果たちをかき集めて、目的のS式を構築できる!
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 39/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
すべての問題解決をリスト操作に還元する
evalした結果もS式を返す場合、
結果たちをかき集めて、目的のS式を構築できる!
S式の構築フェイズとS式の実行フェイズを分けられる
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 40/99
つまりつまり
目的のS式を全力で構築した後にeval できる!
Lisp - LISt Processing 言語の本領発揮
すべての問題解決をリスト操作に還元する
evalした結果もS式を返す場合、
結果たちをかき集めて、目的のS式を構築できる!
S式の構築フェイズとS式の実行フェイズを分けられる
マクロへ
3 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 41/99
Lispの評価器についてLispの評価器について
参考 , , , ,1 2 3 4 5
4 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 42/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 43/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 44/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 45/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
2. それ以外なら、それ自身の値を返却
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 46/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
2. それ以外なら、それ自身の値を返却
2. 評価したS式がList の場合、リストの先頭要素が、
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 47/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
2. それ以外なら、それ自身の値を返却
2. 評価したS式がList の場合、リストの先頭要素が、
1. スペシャルフォーム→ 引数を評価せずに固有の操作
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 48/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
2. それ以外なら、それ自身の値を返却
2. 評価したS式がList の場合、リストの先頭要素が、
1. スペシャルフォーム→ 引数を評価せずに固有の操作
2. マクロ→ 引数を評価せずにマクロ評価、その後eval
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 49/99
S式の定義と評価S式の定義と評価
Atom Number / String / Symbol (t / nil / :symbol / 'a)
Cons-cell (Atom . Atom)
List (Atom . nil) / (Atom . … (Atom . nil))
S-exp Atom / Cons-cell / List
1. 評価したS式がAtom の場合
1. Symbol なら、そのシンボルの値を返却
2. それ以外なら、それ自身の値を返却
2. 評価したS式がList の場合、リストの先頭要素が、
1. スペシャルフォーム→ 引数を評価せずに固有の操作
2. マクロ→ 引数を評価せずにマクロ評価、その後eval
3. 関数→ 引数を評価し、関数適用
4 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 50/99
特殊形式特殊形式
条件分岐と繰り返し
and or if cond while
大域脱出とエラー処理
catch condition-case unwind-protect
Lispオブジェクト生成と束縛
quote function lambda setq setq-default defvar defconst
シーケンス
prog1 prog2 progn
ローカル変数
let let*
Emacsに特有の操作
interactive save-current-buffer save-excursion save-
restriction track-mouse
4 . 3
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 51/99
3種類のマクロ3種類のマクロ
4 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 52/99
3種類のマクロ3種類のマクロ
リーダマクロ(Elispにはない。。。)
4 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 53/99
3種類のマクロ3種類のマクロ
リーダマクロ(Elispにはない。。。)
マクロ
4 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 54/99
3種類のマクロ3種類のマクロ
リーダマクロ(Elispにはない。。。)
マクロ
コンパイラマクロ
4 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 55/99
時間がないので時間がないので
カット
4 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 56/99
use-package by jwiegleyuse-package by jwiegley
5 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 57/99
use-package by jwiegleyuse-package by jwiegley
:if :disabled で無効化しているのに読み込む
5 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 58/99
use-package by jwiegleyuse-package by jwiegley
:if :disabled で無効化しているのに読み込む
新しいキーワードを追加するのが困難
5 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 59/99
use-package by jwiegleyuse-package by jwiegley
:if :disabled で無効化しているのに読み込む
新しいキーワードを追加するのが困難
あるパッケージだけ違うディストリビューションにできな
い
5 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 60/99
use-package by jwiegleyuse-package by jwiegley
:if :disabled で無効化しているのに読み込む
新しいキーワードを追加するのが困難
あるパッケージだけ違うディストリビューションにできな
い
(init.elをEmacs-22, 23で読み込めない)
詳しい苦悩は を参照Qiita記事
5 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 61/99
leaf.elleaf.el
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 62/99
leaf.elleaf.el
内部構造の一新
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 63/99
leaf.elleaf.el
内部構造の一新
圧倒的な見通しやすさ
use-package: 11ファイル1800行
leaf.el: 1ファイル600行(33%)
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 64/99
leaf.elleaf.el
内部構造の一新
圧倒的な見通しやすさ
use-package: 11ファイル1800行
leaf.el: 1ファイル600行(33%)
キーワード追加の簡便さ
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 65/99
leaf.elleaf.el
内部構造の一新
圧倒的な見通しやすさ
use-package: 11ファイル1800行
leaf.el: 1ファイル600行(33%)
キーワード追加の簡便さ
use-packageに勝る、引数入力の柔軟さ
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 66/99
leaf.elleaf.el
内部構造の一新
圧倒的な見通しやすさ
use-package: 11ファイル1800行
leaf.el: 1ファイル600行(33%)
キーワード追加の簡便さ
use-packageに勝る、引数入力の柔軟さ
leafに渡す引数の自由な評価
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 67/99
leaf.elleaf.el
内部構造の一新
圧倒的な見通しやすさ
use-package: 11ファイル1800行
leaf.el: 1ファイル600行(33%)
キーワード追加の簡便さ
use-packageに勝る、引数入力の柔軟さ
leafに渡す引数の自由な評価
Emacs-22からの動作を保証
(Docker imageが用意できないのでEmacs-22はDropする
かも。。)
6 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 68/99
マクロ定義マクロ定義
簡単のために、次のマクロを定義
(defmacro p (form)
`(progn
(pp (macroexpand-1 ',form))
nil))
(defmacro po (form)
`(progn
(pp ,form)
nil))
6 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 69/99
leafの例leafの例
(p
(leaf yasnippet
:ensure t
:custom ((yas-indent-line . 'fixed))
:bind (:map yas-minor-mode-map
("C-c y i" . yas-insert-snippet)
("C-c y n" . yas-new-snippet))
:config
(leaf yasnippet-snippets :ensure t)
(leaf yatemplate :ensure t)
(yas-global-mode 1)))
;; => (progn
;; (use-package-ensure-elpa 'yasnippet '(t) 'nil)
;; (customize-set-variable 'yas-indent-line 'fixed)
;; (autoload #'yas-insert-snippet "yasnippet" nil t)
;; (autoload #'yas-new-snippet "yasnippet" nil t)
;; (eval-after-load 'yasnippet
;; '(progn
;; (leaf yasnippet-snippets :ensure t)
;; (leaf yatemplate :ensure t)
;; (yas-global-mode 1)))
;; (bind-keys :package yasnippet :map yas-minor-mode-map
;; ("C-c y i" . yas-insert-snippet)
;; ("C-c y n" . yas-new-snippet)))
6 . 3
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 70/99
use-packageの実装use-packageの実装
use-package-core?
use-package-concat?
(defmacro use-package (name &rest args)
(declare (indent 1))
(unless (memq :disabled args)
(macroexp-progn
(use-package-concat
(when use-package-compute-statistics
`((use-package-statistics-gather :use-package ',name nil)))
(if (eq use-package-verbose 'errors)
(use-package-core name args)
(condition-case-unless-debug err
(use-package-core name args)
(error
(ignore
(display-warning
'use-package
(format "Failed to parse package %s: %s"
name (error-message-string err)) :error)))))
(when use-package-compute-statistics
`((use-package-statistics-gather :use-package ',name t)))))))
6 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 71/99
use-package-normalize-keywords?
use-package-process-keywords?
(defmacro use-package-core (name args)
`(let* ((args* (use-package-normalize-keywords ,name ,args))
(use-package--form
(if (eq use-package-verbose 'debug)
(concat "nn"
(pp-to-string `(use-package ,name ,@,args))
"n -->nn"
(pp-to-string `(use-package ,name ,@args*))
"n ==>nn"
(pp-to-string
(macroexp-progn
(let ((use-package-verbose 'errors)
(use-package-expand-minimally t))
(use-package-process-keywords name args*
(and (plist-get args* :demand)
(list :demand t)))))))
"")))
(use-package-process-keywords name args*
(and (plist-get args* :demand)
(list :demand t)))))
6 . 5
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 72/99
(handler (concat "use-package-handler/" (symbol-name
keyword)))?
(defun use-package-process-keywords (name plist &optional state)
(declare (indent 1))
(unless (null plist)
(let* ((keyword (car plist))
(arg (cadr plist))
(rest (cddr plist)))
(unless (keywordp keyword)
(use-package-error (format "%s is not a keyword" keyword)))
(let* ((handler (concat "use-package-handler/" (symbol-name keyword)))
(handler-sym (intern handler)))
(if (functionp handler-sym)
(funcall handler-sym name keyword arg rest state)
(use-package-error
(format "Keyword handler not defined: %s" handler)))))))
6 . 6
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 73/99
キーワードの数だけnormalize とhandler を関数として定義
当然defalias の嵐
(defalias 'use-package-normalize/:config 'use-package-normalize-forms)
(defun use-package-handler/:config (name _keyword arg rest state)
(let* ((body (use-package-process-keywords name rest state))
(name-symbol (use-package-as-symbol name)))
(use-package-concat
(when use-package-compute-statistics
`((use-package-statistics-gather :config ',name nil)))
(if (or (null arg) (equal arg '(t)))
body
(use-package-with-elapsed-timer
(format "Configuring package %s" name-symbol)
(funcall use-package--hush-function :config
(use-package-concat
(use-package-hook-injector
(symbol-name name-symbol) :config arg)
body
(list t)))))
(when use-package-compute-statistics
`((use-package-statistics-gather :config ',name t))))))
6 . 7
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 74/99
いや、、、いや、、、
疲れた
6 . 8
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 75/99
leafの独自性- <同図像性>leafの独自性- <同図像性>
同図像性によりメイン関数を小さく出来た
leaf-process-keywords?
(defmacro leaf (name &rest args)
(declare (indent defun))
(let* ((leaf--autoload)
(args* (leaf-sort-values-plist
(leaf-normalize-plist
(leaf-append-defaults args) 'merge 'eval)))
(body (leaf-process-keywords name args*)))
(when body
`(progn
,@body))))
6 . 9
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 76/99
(plist-get (cdr leaf-keywords) key)?
leaf-normarize?変数?
(defun leaf-process-keywords (name plist)
(when plist
(let* ((leaf--name name)
(leaf--key (pop plist))
(leaf--value (leaf-normarize-args leaf--name leaf--key (pop plist)))
(leaf--body (leaf-process-keywords leaf--name plist))
(leaf--rest plist))
(eval
(plist-get (cdr leaf-keywords) leaf--key)))))
(defun leaf-normarize-args (name key value)
(let ((leaf--name name)
(leaf--key key)
(leaf--value value))
(eval
`(cond
,@leaf-normarize))))
6 . 10
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 77/99
同図像性により、実装をデータとして記述できる
(defvar leaf-keywords
'(:dummy
:bind `(,@(mapcar (lambda (elm) `(bind-keys ,@elm)) value) ,@body)
:bind* `(,@(mapcar (lambda (elm) `(bind-keys* ,@elm)) value) ,@body)
:pre-setq `(,@(mapcar (lambda (elm) `(setq ,(car elm) ,(cdr elm))) value) ,@body)
:init `(,@value ,@body)
:require `(,@(mapcar (lambda (elm) `(require ',elm)) value) ,@body)
:setq `(,@(mapcar (lambda (elm) `(setq ,(car elm) ,(cdr elm))) value) ,@body)
:setq-default `(,@(mapcar (lambda (elm) `(setq-default ,(car elm) ,(cdr elm))) value) ,@body)
:config `(,@value ,@body)))
(defvar leaf-normarize
'(((memq key '(:require))
(let ((ret (leaf-flatten value)))
(if (eq nil (car ret))
nil
(delete-dups (delq nil (leaf-subst t name ret))))))
((memq key '(:load-path :commands :after :defvar))
(delete-dups (delq nil (leaf-flatten value))))
...))
6 . 11
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 78/99
実装をデータとして記述するメリット実装をデータとして記述するメリット
細々とした条件分岐部分を切り出す
大きな流れが捉えやすくなる
キーワード追加の心理的障壁を減らす
新しいキーワードとその変換を追加すれば良い
パッケージ外からのキーワード追加
変数へのpushで可能
関数のアドバイスや再定義による混乱を防ぐ
6 . 12
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 79/99
実装をデータとして記述するデメリット実装をデータとして記述するデメリット
バイトコンパイラの恩恵を受けられない
leafはそもそもバイトコンパイル中に動作するので影響
は最小限
6 . 13
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 80/99
cort-test.elcort-test.el
軽量ユニットテストフレームワーク
cort-test.el: 250行(10%) vs ert.el: 2500行
本質的な行は3行のみ。あとはオプション用の変数定義
(defun cort-test-test (test)
(let ((_name (nth 0 test))
(method (nth 1 test))
(expect (nth 2 test))
(given (nth 3 test)))
(if (eq method :cort-error)
(eval `(condition-case err (eval ,given) (,expect t)))
(funcall (intern
(substring (symbol-name method) 1))
(eval given) (eval expect)))))
7 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 81/99
テストフレームワークの仕事テストフレームワークの仕事
7 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 82/99
テストフレームワークの仕事テストフレームワークの仕事
何かの式/操作を評価/実行したとき
期待する値と等しいかどうか確かめる
7 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 83/99
テストフレームワークの仕事テストフレームワークの仕事
何かの式/操作を評価/実行したとき
期待する値と等しいかどうか確かめる
結果を見やすく表示する
7 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 84/99
テストフレームワークの仕事テストフレームワークの仕事
何かの式/操作を評価/実行したとき
期待する値と等しいかどうか確かめる
結果を見やすく表示する
失敗した場合、デバッグの援助となる情報を出力する
7 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 85/99
7 . 3
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 86/99
cort-de estcort-de est
テストの宣言を行ったときにテストを実行してはいけない
あくまでもテストの宣言であり、テストを保存するのみ
同図像性がなかったらどうやって定義するのか。。
(cort-deftest arith
'((:= 9 (+ 4 5))
(:= -1 (- 4 5))
(:= 20 (* 4 5))
(:= 0 (/ 4 5))
(:= 0.8 (/ 4.0 5))
(:= 4 (mod 4 5))))
7 . 4
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 87/99
seml-mode.elseml-mode.el
HTML用テンプレートエンジン
SEMLはS-Expression Markup Language の略
Emacs組み込みでHTML → Sexpは存在したが、逆がない
作ってしまえ
8 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 88/99
SEMLファイルの例SEMLファイルの例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>sample page</title>
<link rel="stylesheet" href="sample1.css"/>
</head>
<body>
<h1>sample</h1>
<p>
text sample
</p>
</body>
</html>
(html ((lang . "en"))
(head nil
(meta ((charset . "utf-8")))
(title nil "sample page")
(link ((rel . "stylesheet") (href . "sample1.css"))))
(body nil
(h1 nil "sample")
(p nil "text sample")))
8 . 2
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 89/99
SEMLの利点- 同図像性の利用SEMLの利点- 同図像性の利用
8 . 3
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 90/99
まとめまとめ
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 91/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 92/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 93/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 94/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
よりパワフルになる!
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 95/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
よりパワフルになる!
LispプログラムがLispプログラムである利点を活かす!
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 96/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
よりパワフルになる!
LispプログラムがLispプログラムである利点を活かす!
今日紹介したパッケージはすべてGitHubで公開
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 97/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
よりパワフルになる!
LispプログラムがLispプログラムである利点を活かす!
今日紹介したパッケージはすべてGitHubで公開
ぜひPRをお願いします!
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 98/99
まとめまとめ
同図像性を利用することにより、Lispプログラムは
より理解しやすく
より自由に
よりパワフルになる!
LispプログラムがLispプログラムである利点を活かす!
今日紹介したパッケージはすべてGitHubで公開
ぜひPRをお願いします!
できたらスターを押して頂けると、励みになります
9 . 1
2019/5/8 Lispの同図像性とその周辺
localhost:8000/slide/lisp-homoiconicity.html?print-pdf#/sec-title-slide 99/99
補足リンク補足リンク
- Yet another use-package
- Simplify Elisp unit test framework
- Major-mode for editing SEML files
- Parallel thread modern Emacs package manager
参考資料
東京大学-
Paren-holic -
STUART C. SHAPIRO -
Harold Abelson 他著和田栄一訳-
Richard Stallman 他著Ayatakesi 訳-
Github
leaf.el
cort-test.el
seml-mode.el
feather.el
Twitter
ソフトウェア第三講義資料- Lisp処理系, リスト処理
3つのLisp 3つの世界
Common lisp - An Interacive approach
計算機プログラムの構造と解釈
GNU Emacs Lisp Reference Manual
9 . 2

Lispの同図像性とその周辺