SlideShare a Scribd company logo
On Lisp読書会2014
第3回
2章 関数(つづき)
hnagamin
2014.07.02 KMC部室
labels
● 局所変数を使った再帰関数を定義できる
– 関数は自分の名前がないと自分を呼び出せない
● いや不動点コンビネータ使えよ
– ローカルな束縛はdefunでは捉えられない
● letを超えるスコープを実現
(labels ((<名前> <引数> . <本体>) … )
<手続き> ...)
labels
● 顧客の要求
– 「1個のオブジェクトと1個のリストを取り, そのリストの要素内に
オブジェクトが何個あったかの回数のリストを返す関数がほしい」
(count-instances 'a '((a b c) (d a r p a) (d a r) (a a)))
→(1 2 1 2)
● lambdaだと自分の名前を使った再帰ができない
● let式だとそもそも関数定義できない
● objを引数に取り、リストを引数にとってその中にobjが出てきた回数を返す
関数をdefun …で定義 (できるのでしょうか)?
labelsを使ったcount-instancesの実
装
(defun count-instances (obj lsts)
(labels ((instances-in (lst)
(if (consp lst)
(+ (if (eq (car lst) obj) 1
0)
(instances-in (cdr lst)))
0)))
(mapcar #'instances-in lsts)))
自分自身を
呼び出すことができる
labelsはただの関数letじゃない
● スコープの違い
– let式の定義部では、同時に定義されている他の変数
を見ることができない
– let* ” ”式だと自分より 左側 で定義された変数を見るこ
とができる
– labelsは同時に定義された他の変数もすべて見るこ
とができる
末尾再帰
● 最後の処理が「自分自身の呼び出し」である関数
– 呼び出したあと戻ってきた値は即座に返さないとダメ
● 末尾再帰のここが偉い
– スタックを消費しない(こともある)
– 高速になる(こともある)
● 明示的に宣言を行う必要がある処理系もある
● Schemeでは言語仕様が末尾再帰最適化を要求しています
末尾再帰じゃない例
(defun our-length (lst)
(if (null lst)
0
(1+ (our-length (cdr lst)))))
● 自分自身を呼び出したあと、戻り値を1+に適用
している→即座に返してない
末尾再帰の例
(defun our-length (lst)
(labels ((rec (lst acc)
(if (null lst)
acc
(rec (cdr lst) (1+ acc)))))
(rec lst 0)))
● 再帰されたrecの戻り値を即座に返している
● 余分な引数accに値を保存することで1+を使わなくてもよくなる
継続渡し
● 余分な引数として関数を渡す
; Scheme
(define (fact n)
(letrec ((I (lambda (x) x))
(F (lambda (m continuation)
(if (<= m 1)
(continuation m)
(F (- m 1) (lambda (x)
(* m (continuation x))))))))
(F n I)))
実演
● 前ページのfactとナイーブに実装したfactで速度
を比べた
● 結果、どちらもまあまあ高速に動作するという
知見を得た
● 階乗なら、いちいち継続渡し使わなくても普通
に計算途中の値を余分な引数として保存してお
けばシンプルに末尾再帰できるので、継続渡し
の例としては不適切だったかもしれないorz
コンパイル
● 関数がコンパイルできる(!)
– 関数1個からコンパイルできる
● プログラム実行中に構成したlambda式もコン
パイルできる(!)
コンパイル
● …名前がある関数 名前をcompileに与える
– (compile 'foo)
● lambda …式 第1引数にnil、第2引数にコンパイルし
たい式を与える
– (compile nil '(lambda (x) (+ x 2)))
– 名前をつけてコンパイルすることもできる
– (progn (compile 'bar '(lambda (x) (* x 3)))
リストから関数を作る
● 関数がリストとして表現されている方言があっ
た
– プログラムが自分自身でプログラムを構成できる
(!)
● Common Lispは違う
– しかし、それでもなおプログラムを構成するプログ
ラムを作ることができる

More Related Content

What's hot

Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)
洋史 東平
 
โปรแกรมย่อยและฟังก์ชันมาตรฐาน
โปรแกรมย่อยและฟังก์ชันมาตรฐานโปรแกรมย่อยและฟังก์ชันมาตรฐาน
โปรแกรมย่อยและฟังก์ชันมาตรฐานP'pim Quaintz
 
[ Grasshopper ] interpolate curve basic #02 j
[ Grasshopper ] interpolate curve basic #02 j[ Grasshopper ] interpolate curve basic #02 j
[ Grasshopper ] interpolate curve basic #02 j
onioncraft
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
Hideyuki Tanaka
 
2011年12月9日
2011年12月9日2011年12月9日
2011年12月9日nukaemon
 
Kotlinのlet/run/applyのよもやま話
Kotlinのlet/run/applyのよもやま話Kotlinのlet/run/applyのよもやま話
Kotlinのlet/run/applyのよもやま話
Masaya Yashiro
 

What's hot (6)

Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)Rubyの御先祖CLUのお話(原本)
Rubyの御先祖CLUのお話(原本)
 
โปรแกรมย่อยและฟังก์ชันมาตรฐาน
โปรแกรมย่อยและฟังก์ชันมาตรฐานโปรแกรมย่อยและฟังก์ชันมาตรฐาน
โปรแกรมย่อยและฟังก์ชันมาตรฐาน
 
[ Grasshopper ] interpolate curve basic #02 j
[ Grasshopper ] interpolate curve basic #02 j[ Grasshopper ] interpolate curve basic #02 j
[ Grasshopper ] interpolate curve basic #02 j
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
2011年12月9日
2011年12月9日2011年12月9日
2011年12月9日
 
Kotlinのlet/run/applyのよもやま話
Kotlinのlet/run/applyのよもやま話Kotlinのlet/run/applyのよもやま話
Kotlinのlet/run/applyのよもやま話
 

Viewers also liked

計算数学
計算数学計算数学
計算数学
blackenedgold
 
灘校パソコン研究部(NPCA)におけるLispの活用について
灘校パソコン研究部(NPCA)におけるLispの活用について灘校パソコン研究部(NPCA)におけるLispの活用について
灘校パソコン研究部(NPCA)におけるLispの活用について
stibear (stibear1996)
 
床下からCommon Lisp
床下からCommon Lisp床下からCommon Lisp
床下からCommon Lisp
Kazuhiro Hishinuma
 
Lisperの見る世界
Lisperの見る世界Lisperの見る世界
Lisperの見る世界
fukamachi
 
Lisp講義1
Lisp講義1Lisp講義1
Biomas y ecosistemas terrestres del perú
Biomas y  ecosistemas  terrestres del  perúBiomas y  ecosistemas  terrestres del  perú
Biomas y ecosistemas terrestres del perú
Giuliana Tinoco
 
Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
Lispmeetup #39 MGLの紹介: Common LispによるディープラーニングLispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
Satoshi imai
 

Viewers also liked (7)

計算数学
計算数学計算数学
計算数学
 
灘校パソコン研究部(NPCA)におけるLispの活用について
灘校パソコン研究部(NPCA)におけるLispの活用について灘校パソコン研究部(NPCA)におけるLispの活用について
灘校パソコン研究部(NPCA)におけるLispの活用について
 
床下からCommon Lisp
床下からCommon Lisp床下からCommon Lisp
床下からCommon Lisp
 
Lisperの見る世界
Lisperの見る世界Lisperの見る世界
Lisperの見る世界
 
Lisp講義1
Lisp講義1Lisp講義1
Lisp講義1
 
Biomas y ecosistemas terrestres del perú
Biomas y  ecosistemas  terrestres del  perúBiomas y  ecosistemas  terrestres del  perú
Biomas y ecosistemas terrestres del perú
 
Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
Lispmeetup #39 MGLの紹介: Common LispによるディープラーニングLispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
Lispmeetup #39 MGLの紹介: Common Lispによるディープラーニング
 

More from Hideaki Nagamine

PietでLISP処理系を書くのは難しい
PietでLISP処理系を書くのは難しいPietでLISP処理系を書くのは難しい
PietでLISP処理系を書くのは難しい
Hideaki Nagamine
 
Pietでlisp処理系を書くのは難しい 進捗報告
Pietでlisp処理系を書くのは難しい 進捗報告Pietでlisp処理系を書くのは難しい 進捗報告
Pietでlisp処理系を書くのは難しい 進捗報告
Hideaki Nagamine
 
フェーザとか
フェーザとかフェーザとか
フェーザとか
Hideaki Nagamine
 
Pietソースコード精読
Pietソースコード精読Pietソースコード精読
Pietソースコード精読
Hideaki Nagamine
 
競技プログラミング練習会2015 Normal 第4回
競技プログラミング練習会2015 Normal 第4回競技プログラミング練習会2015 Normal 第4回
競技プログラミング練習会2015 Normal 第4回
Hideaki Nagamine
 
競技プログラミング練習会2015 Normal 第3回
競技プログラミング練習会2015 Normal 第3回競技プログラミング練習会2015 Normal 第3回
競技プログラミング練習会2015 Normal 第3回
Hideaki Nagamine
 
競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回
Hideaki Nagamine
 
競技プログラミング練習会2015 Normal 第2回
競技プログラミング練習会2015 Normal 第2回競技プログラミング練習会2015 Normal 第2回
競技プログラミング練習会2015 Normal 第2回
Hideaki Nagamine
 
Gaucheでマクロを書こう
Gaucheでマクロを書こうGaucheでマクロを書こう
Gaucheでマクロを書こう
Hideaki Nagamine
 

More from Hideaki Nagamine (9)

PietでLISP処理系を書くのは難しい
PietでLISP処理系を書くのは難しいPietでLISP処理系を書くのは難しい
PietでLISP処理系を書くのは難しい
 
Pietでlisp処理系を書くのは難しい 進捗報告
Pietでlisp処理系を書くのは難しい 進捗報告Pietでlisp処理系を書くのは難しい 進捗報告
Pietでlisp処理系を書くのは難しい 進捗報告
 
フェーザとか
フェーザとかフェーザとか
フェーザとか
 
Pietソースコード精読
Pietソースコード精読Pietソースコード精読
Pietソースコード精読
 
競技プログラミング練習会2015 Normal 第4回
競技プログラミング練習会2015 Normal 第4回競技プログラミング練習会2015 Normal 第4回
競技プログラミング練習会2015 Normal 第4回
 
競技プログラミング練習会2015 Normal 第3回
競技プログラミング練習会2015 Normal 第3回競技プログラミング練習会2015 Normal 第3回
競技プログラミング練習会2015 Normal 第3回
 
競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回競技プログラミング練習会2015 Normal 第1回
競技プログラミング練習会2015 Normal 第1回
 
競技プログラミング練習会2015 Normal 第2回
競技プログラミング練習会2015 Normal 第2回競技プログラミング練習会2015 Normal 第2回
競技プログラミング練習会2015 Normal 第2回
 
Gaucheでマクロを書こう
Gaucheでマクロを書こうGaucheでマクロを書こう
Gaucheでマクロを書こう
 

On Lisp読書会2014 第3回「第2章 関数 (つづき)」