SlideShare ist ein Scribd-Unternehmen logo
1 von 39
Downloaden Sie, um offline zu lesen
続・SECDマシン
@t-sin
2021-03-25
lispmeetup #96
自己紹介 (t-sin)
●
Common Lispがお好きなWebプログラマ
●
興味のあること
– 言語処理系
– 音やグラフィクス
●
SNS
– GitHub: @t-sin
– Twitter: @sin_clav
発表の背景
●
lispmeetup #91でSECD機械の発表しました
– https://www.slideshare.net/t-sin/secd
●
上の発表にもでてくるLispKit Lisp本を読んでると
自分の理解が間違ってたことがわかったので
●
SECD機械の正しい説明をします
– 一部のみ誤りなので訂正を兼ねた復習です
●
前回答えられなかった質問も話します
– dumとrapの命令は何のためにあるか
もくじ
●
LispKit LispとSECD機械の概要
– SECD機械の関数の引数 (訂正ポイント)
●
dumとrap命令はなぜあるか (質問回答)
●
おまけ: LispKit Lisp本のおもしろかった章
– 手続き型プログラムを関数型のそれに変換する話
– 並列化を実現する拡張を入れる話
LispKit LispとSECD機械の概要
LispKit Lisp本について
●
Peter Henderson “Functional Programming: Application
and Implementation”
– 関数型プログラミングの利点や方法論の解説
– 関数型プログラミング言語の実装に関するトピック
– プログラム意味論や非決定性、並行性などのトピックもある
●
関数型プログラミングの説明では数学っぽい言語を使用
●
機械が処理するための言語としてS式のプログラムが登場
LispKit Lisp (1/3)
●
Peter Hendersonが著書内で定義したLisp処理系
●
純粋関数型言語で教育用なので代入や入出力はない
●
特殊形式16個と定数式と関数適用がある
●
この言語のターゲットアーキテクチャがSECD機械
LispKit Lisp (2/3)
●
特徴
– レキシカルスコープ
– 第一級の関数オブジェクト
●
高階関数が使える
– 関数の引数は1個のみ ← 前回発表の誤り
●
関数は固定長の引数を取れる
LispKit Lisp (3/3)
●
16個の特殊形式
– クォート: quote
– 算術演算: add, sub, mul, div, rem
– 比較演算: eq, lem
– コンスセル系: cons, car, cdr, atom
– フロー制御など: if, lambda, let, letrec
SECD機械
●
ラムダ計算を機械的に実行するための抽象機械
– Peter Landinが提唱
●
Landinの原論文のSECD機械はとても抽象的
●
機械語っぽい命令はLispKit Lispのものが有名
– 初なのかは不明
SECD機械の特徴
●
スタックマシン
– データはすべてスタックに積む
– 4本のスタックを持つ
●
スタック以外に状態を持たない
– 入出力もない
SECD機械のスタック
●
4つのスタック
– Stack: 命令や関数に渡すデータ置き場
– Environment: 引数と値のマッピング
– Control: 実行対象となる機械語列
– Dump: 関数適用や条件分岐時の復帰先を保持
●
スタックの実現にはコンスセルを用いる
– ので、SECD機械語もコンスセルで構成される
SECD機械の命令
●
数値演算: add, sub, mul, div, rem
●
比較演算: eq, leq
●
コンスセル系: cons, car, cdr
●
ロード系: ld, ldc, ldf
●
フロー制御: sel, join
●
関数適用: ap, rtn, dum, rap
dumとrap命令はなぜあるか
SECD機械での再帰 (1/2)
●
自分自身を再帰の間参照し続けられればよい
●
再帰する関数をスターター関数に渡せば
引数に束縛されっぱなしになることを利用
●
dumとrapは不要
SECD機械での再帰 (2/2)
●
こういうイメージ(Common Lisp)
これをSECD機械語でやるだけ
CL-USER> (funcall (lambda (f) (funcall f f 10))
(lambda (f n)
(if (= n 1)
1
(* n (funcall f f (- n 1))))))
3628800
SECD機械での相互再帰 (1/2)
●
再帰する関数の定義時に他の関数が定義されて
いる必要がある
●
単純な再帰で使ったテクニックは使えない
●
LispKit Lispではletrecを用いる
SECD機械での相互再帰 (2/2)
●
LispKit Lispのletrec
このletrecを実現するのにdumとrapが必要
(letrec (even? 10) ; 本体
(even? . (lambda (n) ; 本体だけで有効な定義1
(if (eq n 0)
t
(odd? (- n 1)))))
(odd? . (lambda (n) ; 本体だけで有効な定義2
(if (eq n 0)
Nil
(even? (- n 1))))))
letrec実現に必要な知識
●
SECD機械における関数オブジェクト
●
環境(Eスタック)の構造
●
通常の関数適用: ap命令
●
dumとrapのふるまい
SECD機械の関数オブジェクト
●
ldf命令を用いて定義する
●
ldf命令によって関数オブジェクトがSスタックトップに置かれる
– このときその時点のEスタックの内容 (環境) がコピーされる
●
関数オブジェクトは以下2つの要素で構成される
– 関数本体の機械語
– ldf実行時の環境
ldf (関数本体の機械語... rtn)
SECD機械の環境
●
関数の実引数リストのスタック
●
たとえばこんな感じ
●
参照するときは位置(n番目リストのm番目)で指定する
●
引数の名前から位置を求める計算はSECD機械語への
コンパイル時に済んでいると仮定する
;; 関数呼び出しが2段ネストしている状況
((10) (<関数1> 10))
通常の関数適用: ap命令 (1/2)
●
こんな動作をする:
– 関数と実引数リストをSスタックから取得
– 現在の実行コンテキスト(S, E, C)をDに退避
– Cスタックを関数の本体機械語に設定
– Eスタックを関数の環境に設定
– Eスタックトップに実引数リストをプッシュ
通常の関数適用: ap命令 (2/2)
●
各スタックは以下のように変化する
;; ap命令の実行前の状態
(S E C D) = ((本体コード . 関数の環境) (引数1 引数2))
(適用時点の環境)
(ap 適用後のコード)
(適用時点のダンプ))
;; ap命令の実行前の状態
(S E C D) = (()
((引数1 引数2) 関数の環境 …)
本体コード
((適用後のコード
適用時点の環境
適用時点のダンプ)))
dumとrapのふるまい: dum命令
●
現在の環境にダミー値をプッシュする
●
ダミー値はrapで置換するのでなんでもよい
相互再帰を実現するには
●
再帰する関数の定義時に他の関数が定義されてい
る必要がある
→再帰する関数の環境に他の関数が入っている 
必要がある
●
再帰する関数の環境にダミー値を入れておき
あとで他の関数の入ったリストで置き換える
 
dumとrapのふるまい: rap命令 (1/4)
●
だいたいap命令と同じ
– 関数と実引数リストをSスタックから取得
– 現在の実行コンテキスト(S, E, C)をDに退避
– Cスタックを関数の本体機械語に設定
– Eスタックを関数の環境に設定
– Eスタックのダミー値を実引数リストで置換
●
これでdumとrapの間で定義されたすべての関数の
環境に実引数リストが入る
dumとrapのふるまい: rap命令 (2/4)
●
rapの前後でのスタックの変化
;; ap命令の実行前の状態
(S E C D) = (((本体コード . (ダミー値 関数の環境))
(引数1 引数2))
(適用時点の環境)
(rap 適用後のコード)
(適用時点のダンプ))
;; ap命令の実行前の状態
(S E C D) = (()
((引数1 引数2) 関数の環境 …)
本体コード
((適用後のコード
適用時点の環境
適用時点のダンプ)))
dumとrapのふるまい: rap命令 (3/4)
●
注意すべき点
– letrecでは複数の値や関数が定義される
– ダミー値の置換はコンスセルのcar部を書き換えることで行われる
●
replca関数などで
– SECD機械の扱うオブジェクトはすべてコンスセルである
●
循環リストやコンスセルの共有も可能
●
dumの後に定義された関数のダミー値はrapですべて実引数リ
ストに置き換わる
dumとrapのふるまい: rap命令 (4/4)
●
letrecを実現するには
– dum命令を実行し
– 相互に再帰する関数を引数リストとして
– 最初の関数適用をキックする関数を用意し
– キックする関数をrapで呼ぶ
●
letrecできあがり!!!!!
LispKit Lisp本おまけ話
おもしろかった章の概要
手続き型→関数型変換 (1/2)
●
ALGOLのような手続き型言語の式・文を考える
●
LispKit Lispでインタプリタを書く
●
手続き型の各式・文の関数型言語での対応物を考える
– 式・文をLispKit Lispの関数に対応させる
●
状態から値への関数
– 表示的意味論というそうな
手続き型→関数型変換 (2/2)
●
フローチャートで表現されたプログラム
– ループや分岐などでグラフになる
●
フローチャートをループを含まない形にする
– ループを切って再帰にする
●
LispKit Lispの関数が得られる
並行性の導入
●
評価を遅延させられればコルーチンつくれる
– 中断・再開ができる関数
●
delay/forceを関数で実現
– “On Lisp”にもあるあの話
●
SECD機械全体を遅延評価するように改造
●
遅延評価の威力を体感 (未読)
– (コルーチンは……??)
まとめ
まとめ
●
SECD機械の上には純粋関数型言語を構成できる
●
dumとrap命令は相互再帰を実現するためにある
●
LispKit Lisp本にはほかにも以下のことが書かれている
– 手続き型プログラムを関数型のプログラムに変換できる
– 遅延評価を導入すると並行性を入れられる、らしい…?
追記
発表でもらったコメント等
dum/rapなくても相互再帰できる
●
発表の質疑応答時にいただいたコメントより
– 以下をSECD機械語に落としこむとできそう
–
–
–
–
– dam/rapはプリミティブではない…!
CL-USER> (funcall (lambda (c) (funcall (car c) c 10))
(cons (lambda (c n) ; even?
(if (zerop n)
t
(funcall (cdr c) c (- n 1))))
(lambda (c n) ; odd?
(if (zerop n)
nil
(funcall (car c) c (- n 1))))))
T
LispKit Lisp本
●
実は邦訳がある (懇親会にて)
– Peter Henderson著 杉藤芳雄, 二木厚吉 訳『関数型
プログラミング <コンピュータ・サイエンス研究書
シリーズ 17>』
並行性について
●
遅延評価を導入する方法以外にもいくつかある
(懇親会にて)
– LispKit Lisp本の非決定性の章にも関連する
●
“第11回 クロージャによる超軽量並行プロセスの簡単実
装法 | 日経クロステック(xTECH)”
https://xtech.nikkei.com/it/article/COLUMN/20070612/2742
31/

Weitere ähnliche Inhalte

Was ist angesagt?

いまさら聞けないRake入門
いまさら聞けないRake入門いまさら聞けないRake入門
いまさら聞けないRake入門Tomoya Kawanishi
 
Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-t-sin
 
Scapy presentation Remake(訂正)
Scapy presentation Remake(訂正)Scapy presentation Remake(訂正)
Scapy presentation Remake(訂正)ashigirl ZareGoto
 
Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cythonAtsuo Ishimoto
 
形式手法とalloyの紹介
形式手法とalloyの紹介形式手法とalloyの紹介
形式手法とalloyの紹介Daisuke Tanaka
 
import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28th0x0472
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perlJiro Nishiguchi
 
Scapyで作る・解析するパケット
Scapyで作る・解析するパケットScapyで作る・解析するパケット
Scapyで作る・解析するパケットTakaaki Hoyo
 
Perlと出会い、Perlを作る
Perlと出会い、Perlを作るPerlと出会い、Perlを作る
Perlと出会い、Perlを作るgoccy
 
あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話nullnilaki
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と MeltdownHirotaka Kawata
 
TensroFlow XLA : JIT編 (r1.3版)
TensroFlow XLA : JIT編 (r1.3版)TensroFlow XLA : JIT編 (r1.3版)
TensroFlow XLA : JIT編 (r1.3版)Mr. Vengineer
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code readingMasami Hiramatsu
 
プロセスとコンテキストスイッチ
プロセスとコンテキストスイッチプロセスとコンテキストスイッチ
プロセスとコンテキストスイッチKazuki Onishi
 

Was ist angesagt? (20)

Rust-DPDK
Rust-DPDKRust-DPDK
Rust-DPDK
 
Rust-DPDK
Rust-DPDKRust-DPDK
Rust-DPDK
 
いまさら聞けないRake入門
いまさら聞けないRake入門いまさら聞けないRake入門
いまさら聞けないRake入門
 
Glibc malloc internal
Glibc malloc internalGlibc malloc internal
Glibc malloc internal
 
SystemV IPC
SystemV IPCSystemV IPC
SystemV IPC
 
Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-
 
Scapy presentation
Scapy presentationScapy presentation
Scapy presentation
 
Scapy presentation Remake(訂正)
Scapy presentation Remake(訂正)Scapy presentation Remake(訂正)
Scapy presentation Remake(訂正)
 
Introduction to cython
Introduction to cythonIntroduction to cython
Introduction to cython
 
形式手法とalloyの紹介
形式手法とalloyの紹介形式手法とalloyの紹介
形式手法とalloyの紹介
 
import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28import dpkt したよ #ssmjp 2014/02/28
import dpkt したよ #ssmjp 2014/02/28
 
Write good parser in perl
Write good parser in perlWrite good parser in perl
Write good parser in perl
 
Scapyで作る・解析するパケット
Scapyで作る・解析するパケットScapyで作る・解析するパケット
Scapyで作る・解析するパケット
 
Perlと出会い、Perlを作る
Perlと出会い、Perlを作るPerlと出会い、Perlを作る
Perlと出会い、Perlを作る
 
あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown
 
TensroFlow XLA : JIT編 (r1.3版)
TensroFlow XLA : JIT編 (r1.3版)TensroFlow XLA : JIT編 (r1.3版)
TensroFlow XLA : JIT編 (r1.3版)
 
Ylug 110th kpatch code reading
Ylug 110th kpatch code readingYlug 110th kpatch code reading
Ylug 110th kpatch code reading
 
プロセスとコンテキストスイッチ
プロセスとコンテキストスイッチプロセスとコンテキストスイッチ
プロセスとコンテキストスイッチ
 
Minix smp
Minix smpMinix smp
Minix smp
 

Ähnlich wie 続・SECDマシン

第2回品川Redmine勉強会(日本語全文検索)
第2回品川Redmine勉強会(日本語全文検索)第2回品川Redmine勉強会(日本語全文検索)
第2回品川Redmine勉強会(日本語全文検索)Masanori Machii
 
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』Nagi Teramo
 
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニング
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニングAWS Casual 02: ふつうのRedshiftパフォーマンスチューニング
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニングMinero Aoki
 
JellyBeanのソースをとりあえず眺めてみた(手抜き)
JellyBeanのソースをとりあえず眺めてみた(手抜き)JellyBeanのソースをとりあえず眺めてみた(手抜き)
JellyBeanのソースをとりあえず眺めてみた(手抜き)l_b__
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Ra Zon
 
ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜Taro Matsuzawa
 
Terraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as CodeTerraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as CodeTakahisa Iwamoto
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0Kiwamu Okabe
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1Ryosuke IWANAGA
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.jsYoshiiro Ueno
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目龍一 田中
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Ransui Iso
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Takuya Matsunaga
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on LinuxTakayoshi Tanaka
 
2014 11-20 Machine Learning with Apache Spark 勉強会資料
2014 11-20 Machine Learning with Apache Spark 勉強会資料2014 11-20 Machine Learning with Apache Spark 勉強会資料
2014 11-20 Machine Learning with Apache Spark 勉強会資料Recruit Technologies
 
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪崇之 清水
 

Ähnlich wie 続・SECDマシン (20)

第2回品川Redmine勉強会(日本語全文検索)
第2回品川Redmine勉強会(日本語全文検索)第2回品川Redmine勉強会(日本語全文検索)
第2回品川Redmine勉強会(日本語全文検索)
 
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』~knitr+pandocではじめる~『R MarkdownでReproducible Research』
~knitr+pandocではじめる~『R MarkdownでReproducible Research』
 
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニング
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニングAWS Casual 02: ふつうのRedshiftパフォーマンスチューニング
AWS Casual 02: ふつうのRedshiftパフォーマンスチューニング
 
JellyBeanのソースをとりあえず眺めてみた(手抜き)
JellyBeanのソースをとりあえず眺めてみた(手抜き)JellyBeanのソースをとりあえず眺めてみた(手抜き)
JellyBeanのソースをとりあえず眺めてみた(手抜き)
 
_rtld
_rtld_rtld
_rtld
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 
ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜
 
進化するArt
進化するArt進化するArt
進化するArt
 
Terraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as CodeTerraformで始めるInfrastructure as Code
Terraformで始めるInfrastructure as Code
 
スタート低レイヤー #0
スタート低レイヤー #0スタート低レイヤー #0
スタート低レイヤー #0
 
tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1tcpdump & xtrabackup @ MySQL Casual Talks #1
tcpdump & xtrabackup @ MySQL Casual Talks #1
 
ゆるかわPhp
ゆるかわPhpゆるかわPhp
ゆるかわPhp
 
並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js並列対決 Elixir × Go × C# x Scala , Node.js
並列対決 Elixir × Go × C# x Scala , Node.js
 
Web技術勉強会23回目
Web技術勉強会23回目Web技術勉強会23回目
Web技術勉強会23回目
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
 
Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版Dalvik仮想マシンのアーキテクチャ 改訂版
Dalvik仮想マシンのアーキテクチャ 改訂版
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux
 
2014 11-20 Machine Learning with Apache Spark 勉強会資料
2014 11-20 Machine Learning with Apache Spark 勉強会資料2014 11-20 Machine Learning with Apache Spark 勉強会資料
2014 11-20 Machine Learning with Apache Spark 勉強会資料
 
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪
 
Lisperはじめました
LisperはじめましたLisperはじめました
Lisperはじめました
 

続・SECDマシン