(Lambdaだけで) 
純LISPのような 
ナニかを作る 
@maruuusa83 
Daichi Teruya 
Okinawa National Collage of Technology
λ 2 
自己紹介 
• まるさ(@maruuusa83) 
• 沖縄高専メディア科5年生
λ 3 
自己紹介
λ 4 
自己紹介
λ 5 
自己紹介
アジェンダ 
• 自己紹介 
• 今回やることとか色々 
• 特殊形式の定義 
• CONS, CAR, CDR 
• COND 
• データ構造の定義 
• CONDの定義 
• EQ 
• 値の定義 
• EQの定義 
λ 6
• かなりいい加減な独自研究に満ちています! 
• 初心者の嘘だと思って聞いてください・・・ 
λ 7
λ 
λ 8
휷 λ 9 
今回やること
(Lambdaだけで) 
純LISPのような 
ナニかを作る 
λ 10
λ 11
予約語4つの言語 
でLISPを作る 
lambda, ., quote, ::= 
λ 12
どんな言語?? 
λ 13
どんな言語?? 
• 今回は、Lambda項を用いたLambda計算を指す 
λ 14
どんな言語?? 
• 今回は、Lambda項を用いたLambda計算を指す 
• こういうやつ: 
λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 
훽 
λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 
훽 
λ푧. 푧푎푏 λ푥푦. 푥 
훽 
λ푥푦. 푥 푎 푏 
훽 
푎 
λ 15
どんな言語?? 
• 今回は、Lambda項を用いたLambda計算を指す 
• こういうやつ: 
λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 
훽 
λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 
훽 
(λ푧. 푧푎푏) λ푥푦. 푥 
훽 
(λ푥푦. 푥) 푎 푏 
훽 
푎 
λ 16
どんな言語?? 
• 今回は、Lambda項を用いたLambda計算を指す 
• こういうやつ: 
λ푧. 푧 λ푥푦. 푥 λ푥푦푧. 푧푥푦 푎 푏 
훽 
λ푥푦푧. 푧푥푦 푎 푏 λ푥푦. 푥 
훽 
(λ푧. 푧푎푏) λ푥푦. 푥 
훽 
(λ푥푦. 푥) 푎 푏 
훽 
푎 
( ゚Д゚)ハァ? 
λ 17
どんな言語?? 
• Lambda項を言語らしく起こした(!) 
λ 18
どんな言語?? 
• Lambda項を言語らしく起こした(!) 
( ^ω^) <ここに項があるじゃろ? 
⊃ λ푥푦. 푥 푎 푏 ⊂ 
λ 19
どんな言語?? 
• Lambda項を言語らしく起こした(!) 
( ^ω^) <ここに項があるじゃろ? 
⊃ λ푥푦. 푥 푎 푏 ⊂ 
( ՞ਊ ՞) <こうじゃ! 
⊃ ((lambda x.(lambda y.x)) a) b) ⊂ 
λ 20
どんな言語?? 
• Lambda項を言語らしく起こした(!) 
( ^ω^) <ここに項があるじゃろ? 
⊃ λ푥푦. 푥 푎 푏 ⊂ 
_人人人人_ 
> 腕が< 
 ̄Y^Y^Y ̄ 
( ՞ਊ ՞) <こうじゃ! 
⊃ ((lambda x.(lambda y.x)) a) b) ⊂ 
λ 21
処理系書きました!!1 
• 対話型の処理系 
• ラムダ項を与えるとラムダ計算します 
λ 22 
URL : 
http://lmd.maruuusa.tk/ 
Github : 
maruuusa83/lambda_evaluator
予約語の数 
"lambda" { return (LAMBDA); } 
"quote " { return (QUOTE); } 
"::=" { return (DEFUN); } 
"." { return (PERIOD); } 
"(" { return (LP); } 
")" { return (RP); } 
"n" { return (CR); } 
[a-z][0-9]? { 
lambda.l 
yylval.identifier = lambda_create_identifier(yytext); 
return (IDENTIFIER); 
} 
[_A-Z][_A-Za-z0-9]* { 
yylval.name = lambda_create_identifier(yytext); 
return (NAME); 
} 
λ 23
予約語の数 
"lambda" { return (LAMBDA); } 
"quote " { return (QUOTE); } 
"::=" { return (DEFUN); } 
"." { return (PERIOD); } 
"(" { return (LP); } 
")" { return (RP); } 
"n" { return (CR); } 
[a-z][0-9]? { 
lambda.l 
yylval.identifier = lambda_create_identifier(yytext); 
return (IDENTIFIER); 
} 
[_A-Z][_A-Za-z0-9]* { 
yylval.name = lambda_create_identifier(yytext); 
return (NAME); 
} 
λ 24
純LISPってなんぞ 
λ 25
純LISPってなんぞ 
• 最小限の関数とプリミティブのみのLISP 
• これは自身の処理系を記述できる最低限の構 
成 
λ 26
純LISPってなんぞ 
• 最小限の関数とプリミティブのみのLISP 
• これは自身の処理系を記述できる最低限の構 
成 
λ 27 
5つの基本関数 
cons, car, cdr 
eq, atom 
4つの特殊形式 
lambda, cond, 
define, quote
Lambda計算について 
휷
Lambda項について 
• Lambda計算の対象となるのはLambda項のみ 
λ 29
Lambda項について 
• Lambda計算の対象となるのはLambda項のみ 
• 変数푥0,푥1,푥2,…は、lambda項 
• 푥が変数、푀がlambda項のとき、(λ푥. 푀)はlambda項 
• 푀と푁がともにlambda項のとき、(푀 푁)はlambda項 
λ 30
Lambda項について 
• Lambda計算の対象となるのはLambda項のみ 
• 変数푥0,푥1,푥2,…は、lambda項 
• 푥が変数、푀がlambda項のとき、(λ푥. 푀)はlambda項 
• 푀と푁がともにlambda項のとき、(푀 푁)はlambda項 
(項を定義するだけではよくわからない・・・) 
λ 31
Lambda計算規則 
λ 32
Lambda計算規則 
• β-簡約 
項がλ푥. 푀 푁のような形をとるとき、 
項푀の内部にある変数푥を푁で置き換える 
• 代入は次のように定義する 
• 푥 푥 ≔ 푁 ≡ 푁 
• 푦 푥 ≔ 푁 ≡ 푦 
• 퐿 푀 푥 ≔ 푁 ≡ 퐿 푥 ≔ 푁 푀 푥 ≔ 푁 
• λ푦. 푀 푥 ≔ 푁 ≡ λ푧. ( 푀 푦 ≔ 푧 푥 ≔ 푁 ) 
λ 33
計算例 
((lambda x.x) a) 
-> (a) 
単純に代入 
λ 34
計算例 
((lambda x.x) a) 
-> (a) 
単純に代入 
何でも代入できる 
((lambda x.x) (lambda y.y)) 
-> (lambda y.(y)) 
λ 35
計算例 
((lambda x.x) a) 
-> (a) 
単純に代入 
何でも代入できる 
((lambda x.x) (lambda y.y)) 
-> (lambda y.(y)) 
変数名が衝突すると 
その先置換しない 
((lambda x.(lambda x.x)) a) 
-> (lambda x.(x)) 
λ 36
間違えやすい例 
X(x y z) 
○((x y) z) 
含めるのは2項のみ。 
基本は左側結合 
λ 37
間違えやすい例 
X(x y z) 
○((x y) z) 
含めるのは2項のみ。 
基本は左側結合 
X(lambda xy.yx) 
○(lambda x.(lambda y.(y x))) 
省略は認めていない 
λ 38
間違えやすい例 
X(x y z) 
○((x y) z) 
含めるのは2項のみ。 
基本は左側結合 
X(lambda xy.yx) 
○(lambda x.(lambda y.(y x))) 
X(lambda x.(x)) 
○(lambda x.x) 
省略は認めていない 
ごめんなさい、 
処理系の仕様です; 
λ 39
LISPの定義:特殊形式 
휷 
λ 40
必要な特殊形式 
• lambda, quote, define, condが必要
必要な特殊形式 
• lambda, quote, define, condが必要 
• quoteは「評価しない」を指示 
• (quote ((lambda x.x) a)) -> ((lambda x.(x)) 
(a))
必要な特殊形式 
• lambda, quote, define, condが必要 
• quoteは「評価しない」を指示 
• (quote ((lambda x.x) a)) -> ((lambda x.(x)) 
(a)) 
• defineは無名関数に名前を与える 
• FUNC ::= (lambda x.x) 
• (FUNC a) -> (a)
必要な特殊形式 
• lambda, quote, define, condが必要 
• quoteは「評価しない」を指示 
• (quote ((lambda x.x) a)) -> ((lambda x.(x)) 
(a)) 
• defineは無名関数に名前を与える 
• FUNC ::= (lambda x.x) 
• (FUNC a) -> (a) 
あとはcondだけ!(笑)
condとな 
• cond:C言語でいうswitch-case文 
• かなり複雑になりそうなのでIF文に・・・ 
λ 45
condとな 
• cond:C言語でいうswitch-case文 
• かなり複雑になりそうなのでIF文に・・・ 
• λ푥푦푞. 푞푥푦って感じ? q:選択子x:THEN y:ELSE 
• IF ::= 
(lambda x.(lambda y.(lambda q.((q x) 
y)))) 
λ 46
condとな 
• cond:C言語でいうswitch-case文 
• かなり複雑になりそうなのでIF文に・・・ 
• λ푥푦푞. 푞푥푦って感じ? q:選択子x:THEN y:ELSE 
• IF ::= 
(lambda x.(lambda y.(lambda q.((q x) 
λ 47 
y)))) 
• TRUE ::= (lambda x.(lambda y.x)) 
• FALSE ::= (lambda x.(lambda y.y))
condとな 
• cond:C言語でいうswitch-case文 
• かなり複雑になりそうなのでIF文に・・・ 
TRUEは一つ目の引数、 
FALSEは二つ目の引数を返す 
• λ푥푦푞. 푞푥푦って感じ? q:選択子x:THEN y:ELSE 
• IF ::= 
ということに注目!!! 
(lambda x.(lambda y.(lambda q.((q x) 
y)))) 
• TRUE ::= (lambda x.(lambda y.x)) 
• FALSE ::= (lambda x.(lambda y.y)) 
λ 48
condとな 
• ついでに論理演算子も定義する 
λ 49
condとな 
• ついでに論理演算子も定義する 
• NOT ::= (lambda q.((q FALSE) TRUE)) 
λ 50
condとな 
• ついでに論理演算子も定義する 
• NOT ::= (lambda q.((q FALSE) TRUE)) 
• AND ::= (lambda p.(lambda q.((p q) 
FALSE))) 
• OR ::= (lambda p.(lambda q.((p TRUE) 
q))) 
λ 51
LISPの定義:標準関数 
휷 
λ 52
cons, car, cdr 
• car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ?
cons, car, cdr 
• car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ? 
• (CAR ((CONS a) b))という感じにしたい 
• が、最左(名前呼び)戦略なので 
CARの評価時点でCONSが未評価になってしまう
cons, car, cdr 
• car, cdrはλ푥푦. 푥とかλ푥푦. 푦という感じ? 
• (CAR ((CONS a) b))という感じにしたい 
• が、最左(名前呼び)戦略なので 
CARの評価時点でCONSが未評価になってしまう 
• λ푧. (푧 λ푥푦. 푥) としてCONSを左へ! 
• CAR ::= 
(lambda z.(z (lambda x.(lambda 
y.x))))
cons, car, cdr 
• consに値呼びを名前呼びに戻す力を持たせる 
• λ푥푦푧. 푧푥푦 として最後に評価項をとる 
CONS ::= 
(lambda x.(lambda y.(lambda z.((z x) 
y)))) 
λ 56
eqとequalの定義・・・ 
λ 57
eqとequalの定義・・・ 
かなりややこしい! 
(時間がない!!!!) 
λ 58
データ構造の定義:LIST 
• eq, atomを定義したい 
• が、(M N)がデータ構造だとかなり扱いにくい 
• CONSの定義を右側結合でそのまま使う! 
• ただし、必ず末尾にNIL::=FALSEを含む 
λ 59
データ構造の定義:LIST 
• eq, atomを定義したい 
• が、(M N)がデータ構造だとかなり扱いにくい 
• CONSの定義を右側結合でそのまま使う! 
• ただし、必ず末尾にNIL::=FALSEを含む 
• < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) 
• < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) 
훽 
퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 
훽 
λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) 
λ 60
データ構造の定義:LIST 
• eq, atomを定義したい 
• が、(M N)が定デ義ータす構る造LISPだとかでなは 
り扱いにくい 
• CONSの定義を右側結合でそのまま使う! 
全てのデータはLISTで表現! 
• ただし、必ず末尾にNIL::=FALSEを含む 
GEN_ATOM ::= (lambda x.((CONS x) NIL)) 
ADD_LIST ::= 
• < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) 
• < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) 
(lambda l1.(lambda l2.((CONS l2) 
훽 
퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 
훽 
λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) 
λ 61 
l1)))
データ構造の定義:LIST 
• eq, atomを定義したい 
• が、(M N)が定デ義ータす構る造LISPだとかでなは 
り扱いにくい 
• CONSの定義を右側結合でそのまま使う! 
全てのデータはLISTで表現! 
• ただし、必ず末尾にNIL::=FALSEを含む 
GEN_ATOM ::= (lambda x.((CONS x) NIL)) 
ADD_ATOM ::= 
• < 푀 > ≡ (퐶푂푁푆 푀 푁퐼퐿) = λ푧. ( 푧 푀 푁퐼퐿) 
• < 푀, 푁 > ≡ (퐶푂푁푆 푀 < 푁 >) 
(lambda l1.(lambda l2.((CONS l2) 
훽 
퐶푂푁푆 푀 (λ푧. ( 푧 푁 푁퐼퐿) 
훽 
λ푧. ( 푧 푀 푧. 푧 푁 푁퐼퐿 ) 
λ 62 
l1)))
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
λ 63
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
λ 64
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
λ 65
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
λ 66
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
< M, N > ::= 
(lambda z.((z M) (lambda z.((z n) 
NIL))) 
λ 67
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
< M, N > ::= 
(lambda z.((z M) (lambda z.((z n) 
NIL))) 
λ 68
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
atomの定義 
λ 69
atomの定義 
• アトムは、lambdaを一枚はがすとNIL 
• リストは、lambdaを1枚はがしてもリスト 
• リストならFALSEを返す感じの方針 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
• ATOM ::= (lambda x. 
(NOT (IS_LIST x)) ) 
λ 70
データの定義 
• eqを定義したい・・・ 
• 二つの引数が等しいか調べる 
• 識別子が同じか調べるのは言語仕様レベルの話? 
λ 71
データの定義 
• eqを定義したい・・・ 
• 二つの引数が等しいか調べる 
• 識別子が同じか調べるのは言語仕様レベルの話? 
• 値を定義して、同じか調べられるようにする 
⇒チャーチ数 
λ 72
チャーチ数とな 
• 関数適用の回数で数値を表現する 
• 0 ≔ λ푠푧. 푧, 1 ≔ λ푠푧. 푠푧, 2 ≔ λ푠푧. 푠 푠 푧 , … 
λ 73
チャーチ数とな 
• 関数適用の回数で数値を表現する 
• 0 ≔ λ푠푧. 푧, 1 ≔ λ푠푧. 푠푧, 2 ≔ λ푠푧. 푠 푠 푧 , … 
• 2つ目の引数zに1つ目の引数sをN回適用する 
• FALSEと0の表現が同じであることに注目 
λ 74
チャーチ数の比較 
• IS_ZERO ::= ((IF (lambda x.FALSE) 
TRUE)) 
• atomとほぼ同じ形(読み捨てが3個→1個に) 
λ 75
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
λ 76
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
λ 77
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
(lambda f.(lambda x.(f (f…(f a)))…) 
λ 78
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
• GREATER ::= 
(lambda m.(lambda n. 
((n (lambda z.(((IF (CDR z)) z) (CAR 
z))) 
(N_TRUE_APP m) ((CONS FALSE) 
FALSE) )) λ 79
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
• GREATER ::= 
(lambda m.(lambda n. 
((n (lambda z.(((IF (CDR z)) z) (CAR 
z))) 
(N_TRUE_APP m) ((CONS FALSE) 
FALSE) )) λ 80
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
• GREATER ::= 
(lambda m.(lambda n. 
((n (lambda z.(((IF (CDR z)) z) (CAR 
z))) 
(N_TRUE_APP m) ((CONS FALSE) 
FALSE) )) λ 81
チャーチ数の比較 
• MとNの大小比較! 
• trueをN個生成して、M回IFに食わせる 
⇒大きさの比較ができる! 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
• GREATER ::= 
(lambda m.(lambda n. 
((n (lambda z.(((IF (CDR z)) z) (CAR 
z))) 
(N_TRUE_APP m) ((CONS FALSE) 
FALSE) )) λ 82
比較ができるからeqができる 
• 等しければTRUEが返る 
⇒どちらで比較してもTRUEならば等しい! 
λ 83
比較ができるからeqができる 
• 等しければTRUEが返る 
⇒どちらで比較してもTRUEならば等しい! 
• EQ ::= (lambda n.(lambda m. 
((AND 
(NOT ((GREATER n) m))) 
(NOT ((GREATER m) n))) ) 
λ 84
比較ができるからeqができる 
• 等しければTRUEが返る 
⇒どちらで比較してもTRUEならば等しい! 
• EQ ::= (lambda n.(lambda m. 
((AND 
(NOT ((GREATER n) m))) 
(NOT ((GREATER m) n))) ) 
SIMPLE!! 
λ 85
휷 
まとめ 
λ 86
IFとそれに伴う諸々(COND) 
• IF ::= 
(lambda x.(lambda y.(lambda q.((q x) 
y)))) 
• TRUE ::= (lambda x.(lambda y.x)) 
• FALSE ::= (lambda x.(lambda y.y)) 
• NOT ::= (lambda q.((q FALSE) TRUE)) 
• AND ::= (lambda p.(lambda q.((p q) 
FALSE))) 
• OR ::= (lambda p.(lambda q.((p TRUE) q)))
CONS, CAR, CDR 
• CONS ::= 
(lambda x.(lambda y.(lambda z.((z x) 
y)))) 
• CAR ::= (lambda z.(z TRUE)) 
• CDR ::= (lambda z.(z FALSE)) 
λ 88
LISTとATOM 
• GEN_ATOM ::= (lambda x.((CONS x) NIL)) 
• ADD_ATOM ::= 
(lambda l1.(lambda l2.((CONS l2) 
l1))) 
• IS_LIST ::= (lambda x. 
((IF (lambda xyz.TRUE) 
FALSE) 
(CDR x) )) 
• ATOM ::= (lambda x.(NOT (IS_LIST x)) ) 
λ 89
チャーチ数とEQ 
• N_TRUE_APP ::= 
(lambda n.(lambda z. 
(n (lambda z.((CONS TRUE) z))) ) 
• GREATER ::= 
(lambda m.(lambda n. 
((n (lambda z.(((IF (CDR z)) z) (CAR 
z))) 
(N_TRUE_APP m) ((CONS FALSE) 
FALSE) )) 
• EQ ::= (lambda n.(lambda m. 
((AND 
(NOT ((GREATER n) m))) 
(NOT ((GλREATER m) n))) ) 90
予約語4つの言語 
でLISPを作る 
lambda, ., quote, ::= 
(16行くらい?) 
λ 91
λ 92
λ 93
Thank you 
for listening 
marusa (@maruuusa83) 
λ 94

(Lambdaだけで) 純LISPのような ナニかを作る