狠狠撸

狠狠撸Share a Scribd company logo
) の品格
@emasaka
どう見ても
出オチです
本当にありがとうございました
自己紹介
● @emasaka
● 本名:高橋正和
● 駄洒落を検索結果にしてTwitterに流すメソッドの(たぶん)元祖
● ja.wikipedia.orgで「Locator/Identifier Separation Protocol」の
ページを立てた人
● 代表作:Bash on Rails
● 40代 フリーター
● ブログ
「本を読む」http://emasaka.blog65.fc2.com/
本题
「Lispはカッコが多い」
などと申しまして
(defun?fact?(n)
??(if?(zerop?n)
??????1
????(*?n?(fact?(??n?1)))?))
階乗(factorial)をこんなふうに
書いたりします
これを
より厳密に書くと
(defun?.?(fact?.?((n?.?
nil)?.?((if?.?((zerop?.?(n?
.?nil))?.?(1?.?((*?.?(n?.?
((fact?.?((??.?(n?.?(1?.?
nil)))?.?nil))?.?nil)))?.?
nil))))?.?nil))))
点対表記(Dotted pair notation)
たしかにカッコが多い!
(拍手!)
命令型プログラマーならfor文か
類似のループで問題を解く
(defun?fact?(n)
??(let?((i?1)?(r?1))
????(while?(<=?i?n)
??????(setq?r?(*?r?i)
????????????i?(+?i?1))?)
????r?))
ループで書くと
(defun?.?(fact?.?((n?.?nil)?.?
((let?.?(((i?.?(1?.?nil))?.?
((r?.?(1?.?nil))?.?nil))?.?
((while?.?((<=?.?(i?.?(n?.?
nil)))?.?((setq?.?(r?.?((*?.?
(r?.?(i?.?nil)))?.?(i?.?((+?.?(i?
.?(1?.?nil)))?.?nil)))))?.?
nil)))?.?(r?.?nil))))?.?nil))))
これを点対表記に
これではLispに
拒絶反応を示す人が
いてもおかしくない
“Lisp??No!”
の恐怖
でも、
Lisperなら
(3?(5?(7)?11))
このS式を見たとき
(3?.?((5?.?((7?.?
nil)?.?(11?.?
nil)))?.?nil))
これを飛ばして
こうイメージする
nil
nil
nil
3
5
7 11
木構造
(ツリー)
ツリーを巡回する
● 全要素を出力する
● 全要素を合計する
● 特定の要素を探す
● …
※ブログねたの焼き直しです
方法1
● car方向とcdr方向をそれぞれ再帰的に辿る
● いちばんシンプルな方法
(defun?traverse?tree?(tree?func)
??(if?(atom?tree)
??????(or?(null?tree)?(funcall?func?tree))
????(traverse?tree?(car?tree)?func)
????(traverse?tree?(cdr?tree)?func)?))
Emacs Lispで書くと
(defun?traverse?tree?(tree?func)
??(mapc?#'(lambda?(x)
????????????(if?(atom?x)
????????????????(or?(null?x)?(funcall?func?x))
??????????????(traverse?tree?x?func)?))
????????tree?))
cdr方向をmapやループにしても
car方向は再帰が必要
方法2
● ループで辿る
● 戻る場所を外部のデータ構造に覚えておく
● 深さ优先ならスタック、幅优先ならキュー
実装は割爱
方法3
● 再帰も外部データも使わない方法
● 通ったコンスセルを破壊的に「120度回転」さ
せながら進む
● 3方向(car方向、cdr方向、戻り)
= 3回120度回転 = 360度回転 = 元に戻る
図解
car cdr
こっちに進む
car
cdr
こっち(元のcar)
に進みながら
120度回転
戻ったら次
(新しいcar)
car
cdr
戻ったら次
(新しいcar)
こっち(元のcar)
に進みながら
120度回転
car cdr
こっち(元のcar)
に進みながら
120度回転
carを辿っていくだけで
ツリーを一巡する
         ,. -‐'''''""¨¨¨ヽ
         (.___,,,... -?ァ?|          あ…ありのまま 今 起こった事を話すぜ!
          |i i|    }! }} //|
         |l?{   j} /,,?//|       『おれはcarを辿っていたと
        i|:!ヾ?_?/ u {:}//?        思ったらいつのまにかツリーを一周していた』
        |? u' }  ,? _,!V,? |
       /?fト?_{?{,ィ'e? , ?人        な… 何を言ってるのか わからねーと思うが
     /'   ヾ|宀| {?,)⌒`/ |<ヽ?iゝ        おれも何をされたのかわからなかった…
    ,?  / )ヽ iL?  u' | | ヾl??〉
     |/_/  ? !ニ? '/:}  V:::::ヽ        頭がどうにかなりそうだった…
    // 二二二7'T'' /u' __ /:::::::/`ヽ
   /'?r -—一?‐?T? '"? /::::/-‐  \    再帰だとかスタックだとか
   / //   广¨?  /'   /:::::/? ̄`ヽ ⌒ヽ    そんなチャチなもんじゃあ 断じてねえ
  ? ' /  ノ:::::`ー-?___/::::://       ヽ  }
_/`丶 /:::::::::::::::::::::::::: ̄`ー-{:::...       ?  もっと恐ろしいものの片鱗を味わったぜ…
(defun?traverse?tree:spin?(cns?prev)
??(let?((next?(car?cns)))
????(rplaca?cns?(cdr?cns))
????(rplacd?cns?prev)
????next?))
(defun?traverse?tree?(tree?func)
??(let*?((marker?"dummy")???????????????;?unique?object
?????????(cns?tree)?(prev?marker)?next?)
????(while?(not?(eq?(setq?next
??????????????????????????(traverse?tree:spin?cns?prev)?)
????????????????????marker?))
??????(if?(consp?next)
??????????(setq?prev?cns?cns?next)
????????(or?(null?next)?(funcall?func?next))
????????(setq?prev?next)?))))
Emacs Lispで書くと
● 元ネタは、20年ぐらい前に雑誌(bit?)の
エッセイかなにかでアイデアを見た記憶
● 詳細はぜんぜん覚えてない
● ご存知の方、教えてください
● 実践的ではない
● いくら関数型じゃなくても、無駄な破壊的操作はい
まどき流行らない?
DEMO
まとめ
● カッコは単なる格好
● ツリーですた
● 【缓募】元ネタの情报

More Related Content

)の品格