「関数型プログラミングに目覚めた! IQ145の女子高校生の先輩から受けた特訓5日間」の解釈
はじめに
旬は過ぎてしまいましたが、「関数型プログラミングに目覚めた! IQ145の女子高校生の先輩から受けた特訓5日間」の僕なりの解釈を書いてみることにしました。僕の理解が及ばないところもまだまだ残っているのですが。
ただし、他の方のレビューと違い、以下を意識しています。
- 著者の言いたいことを解釈することを目的とする
- 意味の揺れや技術的間違いなどはひとまず置いておく
- ラノベとして面白いかどうかもこの際どうでもいい
また、全部読んではいるのですが、時間的制約から全体で400ページある中のp.151までとしています。全部書こうとするといつになるかわからないので…
目次
- Day1 それは「関数型プログラミング」という新しい世界の幕開けだった…p.5
「セキヤ」が書いたダサいコードに対し、クールなコードを書いた「サクラ」による関数型プログラミングの説明。
- Day2 『論理世界』と『物質世界』の狭間を見据える『神の眼』レベル1…35
「物質世界」の命令型プログラミングの世界を離れ、「論理世界」の関数型プログラミング〜宣言型プログラミングへ。
- Day3 論理を世界の中心に据える世界観 世界のすべてを見透す『神の眼』レベル2…115
宣言型のコードはイミュータブルで見透しが良い参照透過な論理の世界。
- Day4 神はあまねく存在する 『神の眼』レベル3【最終レベル】…215
アラン・ケイが提唱したオブジェクト指向のMVCに対応する「論理」「物質」「精神」の三元論に対し、関数型プログラミングは「物質」は「論理」の影であり「精神」は「物質」の一部である「論理」中心の一元論。
- Day5 『今』が大事…379
関数型プログラミングとオブジェクト指向は相いれない存在。
結論
結論から言うと、著者言いたいことは下記です。
- 「論理」=「問題の本質」をフロー(逐次実行・条件判断・繰り返し)によらずそのままコードに表せる関数型(宣言型)プログラミングはクール
本書を読むと、「0〜9までの数をすべて足すコード」をクールに書けるようになります。すごいですね。
要旨
一般的なプログラマは「論理世界」「物質世界」などというものを考えないので、「ハードウェアモード」で「物質世界」のコンピュータのハードウェアに命令を出す命令型プログラミングを使用している。
宣言型プログラミング(関数型プログラミングをしていると自動的に宣言型プログラミングになる)として、「論理(問題の本質)」を「論理世界」のものであるソフトウェアで書けば、「フロー(繰り返しや条件判断)」に惑わされず「論理」に集中してコードを書くことができる。
「論理」は「計算」されることで人が見えるように「物質化」される。
宣言型プログラミングは「論理世界」のものであるので、イベントが発生しない限りは静止しているイベント駆動である。
※ p.151以降、「物理世界」の時刻を関数の引数としてユーザを含めた世界全体を扱う関数の話やReactの使い方と続き、著者のライブラリの説明となります。
※ 特に技術的部分について僕の理解では誤りと思われる部分が多く含まれるのですが、著者は「無知の知」を強調していますので自ら気付いていると思います。本を書いたという「権威主義」に陥らないことを期待します。
解釈
これから本書で重要であろう文章・言葉について僕の解釈について解説してみようと思います。
以下にずらずらと書きますが、基本的に「文章・言葉」「僕の解釈」「参考とした引用部分」という構成になっています。
0から9までの数をすべて足すコードを書け
これは、p.7から始まり何度も出てきます。
「セキヤ」が書いたコードは下記です。
var s = 0; for (var n = 0; n < 10; n++) { s = s + n; } console.log(s);
一方、「サクラ」が書いたコードが下記です。
var plus = function(a, b) { return a + b; }; var s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .reduce(plus); // をすべて足す console.log(s);
「セキヤ」が書いたコードは命令型でダサいコード、「サクラ」が書いたコードは関数型でクールなコードという意味合いです。
参考
p.14
全く同じ「サクラ」のコード
p.19〜22
全く同じ「サクラ」のコードのplus関数
p.27
全く同じ「サクラ」のコード
p.43
全く同じ「サクラ」のコード
p.46
全く同じ「サクラ」のコード
p.54
全く同じ「サクラ」のコード
p.86
全く同じ「セキヤ」と「サクラ」のコード
p.133
全く同じ「セキヤ」のコード
p.141
全く同じ「セキヤ」のコード
フロー
「フロー」とは「繰り返しや条件判断(p.11)」です。
問題の「論理」には関係のないもので、「フロー」があることでバグが紛れ込みデバッグの手間が激増します。
引用
p.10
この「フロー」があることにより、「コードにすぐバグが紛れ込む(p.10)」
p.11
「『0から9までの数をすべて足す』という問題にはフローがない。ならば、コードもそのままフローなしにかければいい」
p.12
フローなしで書くことにより「プログラミングの最大の課題であるデバッグの手間が激減する」
p.12
「フローがない、フローの設計が必要ないということは、問題の論理だけに集中している」
p.14
「これまで問題の論理を上手にフローに変換してフローを設計する作業こそがプログラミングだと勘違いしていた」
p.25,p.26
「問題の論理とは一切関係もなく、フローの中で何度も計算されて刻々と値が変化して、フローの制御に組み込まれてしまっているsとか、nみたいな変数のことを状態変数と呼ぶの。こんな、問題の論理とはまるで関係ない分際で、刻々と変化するような状態変数なんてものはなくしてしまいなさい。論理を設計する上で邪魔だわ。フローがバグの元凶であるのと同様に、状態変数もバグの元凶よ」
フローを書かずに論理をそのままコードに書き写せ
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていく」も同様の意味です。
「問題には繰り返しや条件判断が出てこないのだから、そのままコードに書き写せ」ということです。ここで「論理」というのが問題になってくるのですが、それは後述します。
引用
p.12
「問題の論理そのものを書き写しただけなんだから、バグが介入する余地なんて最初からどこにもあるはずがない」
p.14, p.15
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていく」
p.54
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていくとき、並べるものは、『計算の命令』ではなくて『論理』となる」
p.56
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていく事 → 論理の宣言=宣言型のコードを書くプログラミング」
論理
「問題の本質(数式など)」で、人間とは関係なく存在し、それを人間が明らかにする行為が「計算」です。
「計算」すれば必ず解ける問題のロジックで、人間が「計算」する前に答えは自明に決まっています。
そして、「問題の論理には結果など含まれていない」ことにより「論理」には結果は含みません。結果は「計算」の副産物です。「論理」は「論理世界」のもので、「計算」は「物理世界」のものです。
ただし、p.61では「1+1=2という『論理』」と出てきます。ここでは結果まで含めて『論理』とされているので誤りかと思います。
また、p.65以降にあるように「コードとソフトウェア」も「論理」、「論理世界」のものです。
「論理」の最小単位は関数なので、関数を組み合わせて「論理」を設計します。
「論理」と「計算」を合わせて「数学」と呼びます。
「証明」とは「論理」の「計算」のことです。
引用
p.12
「問題の論理そのものを書き写しただけなんだから、バグが介入する余地なんて最初からどこにもあるはずがない」
p.13
「論理のみで構成された、これ以上望めないほど見透しの良いクールなコードを書くことは、ダサいコードを平気で書く常人プログラマーの想像を超えた『コードを見透せる眼』を持つことに等しい」
p.14
「これまで問題の論理を上手にフローに変換してフローを設計する作業こそがプログラミングだと勘違いしていた」
p.14, p.15
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていく」
p.15
「0から9までの数という論理があるならば、フローでごちゃごちゃやることなど考えないで、単純に[0, 1, … , 9]とそのままのデータをまるごと用意してしまう」
「『をすべて足す』という論理操作をしてやるのね」
「これを合わせると『0から9までの数をすべて足す』という論理をコードに書き写したことになる」
p.17
「炊飯器というマシンOUTPUT(出力)である炊飯器(米と水)とは炊きたてのご飯なので、炊きたてのご飯=炊飯器(米と水)という論理操作の関係、論理構造になっている」
p.18
「Before(ビフォー)の『様々な問題を抱えた家』は『匠』の手が加わると、After(アフター)の『なんということでしょう!!』に『大変身』する」
「『匠』はFUNCTION・関数よ」
「『様々な問題を抱えた家』をINPUT(入力)すれば、匠がその問題を『抱える』ことになり、匠(様々な問題を抱えた家)となり、その『大変身』したAfterは『なんということでしょう!!』なので、なんということでしょう!!=匠(様々な問題を抱えた家)という論理操作の関係、論理構造になっている」
p.19
「関数は、レゴ・ブロックのような最小単位の部品なのよ。論理の最小単位としての部品。」
p.23
「問題の論理には結果など含まれていない」
p.25,p.26
「問題の論理とは一切関係もなく、フローの中で何度も計算されて刻々と値が変化して、フローの制御に組み込まれてしまっているsとか、nみたいな変数のことを状態変数と呼ぶの。こんな、問題の論理とはまるで関係ない分際で、刻々と変化するような状態変数なんてものはなくしてしまいなさい。論理を設計する上で邪魔だわ。フローがバグの元凶であるのと同様に、状態変数もバグの元凶よ」
p.26
「手順を分割して、逐一結果を小出しにしながら実行するのをプログラミングだと思い込んでいる〜それに対してクールなプログラマーは論理を分割しようとしている〜論理の最小単位である関数という論理操作を自在に組み合わせて論理を設計していく」
p.27
「『万能のスーパー匠』を組み上げることこそが問題の論理であり、それはそのまま問題の解決になる」
「『万能のスーパー匠』はすべてやり方を知っており、その行動についてこちらはいちいち口出ししない」
p.27
「reduceとplusという2つの関数が組み合わさって『//をすべて足す』という関数になっているわね?この2つの関数が、『匠』よ。これは、それぞれ逐一実行しろ、という計算の手順書ではないわ。2つの関数を組み合わせて『//をすべて足す』という『スーパー匠』を設計してやっているのよ」
「論理操作の組み合わせの設計だけで、Afterという結果や、フローも、途中の計算手順も、変化し続ける状態変数も何ひとつないんですね」
「そう。手続きを分割して結果を小出しにするループのフローを書くのではなく、論理を分割し論理だけを構成しなさい。」
p.54
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていくとき、並べるものは、『計算の命令』ではなくて『論理』となる」
p.55
・計算の命令 ではなくて ⇒ 論理
・マシン操作手順書 ではなくて ⇒ 論理の宣言書
p.58
「『論理』と『計算』は別物 『論理』は人間とは関係なくただそこにある存在、それを人間が明らかにする行為が『計算』
「この『論理』と『計算』を全部ひっくるめたものを『数学』と呼ぶ」
p.59
・式と計算
・数量関係
・比率
これこそが『計算』の背後に存在する『論理』のこと」
「『計算』の背後には『論理』が存在する」
p.61
「計算していないから、2という計算の結果としてわかる『論理』は消えてなくなってしまうのかしら?」
「もちろん、そんなことはないです。この電卓が1+1=を計算しようとしまいと、計算の結果2になるという事実は、あらかじめ決まっていることである」
「1+1=2という『論理』は、この電卓で計算しようとしまいと影響を受けません」
p.62
「実は『計算』すべき『問題』なんてものは最初からどこにも存在しない。だって『論理』っていうのは、最初からあらかじめ決まっていること、なのだから」
「『問題』というのは人間が、この『論理』は難しい!って勝手に思うから、それが『問題』になるのであって、だから『計算』して明らかにしてやる必要が生じる。それはあくまで人間の勝手な都合が発端となる行為」
p.64,65
「プログラミングっていうのはもちろん『ソフトウェア』であるわけ。『論理』の世界のおはなし。ところが『論理』を『計算』するのがコンピュータ、電卓というマシンなの。これは『ハードウェア』ね」
「プログラムのコードは、ソフトウェア。実際に『計算』してくれるハードウェアに依存している。つまり、『論理』を『物質化』してくれる『物質世界』にあるマシンが絶対に必要なのよ。『論理世界』の中だけで、ひとりで完結するような『計算』なんてものはどこにも存在しないから。さっき電卓でやったように、『計算』っていうのは人間のための人間による勝手な行為であって、そもそも『論理世界』にはどこにも存在しない概念なのよ」
p.65
「コードは、ソフトウェアであり『論理』なのよ。コンピュータというマシンは、ハードウェアであり『物質』。コンピュータでコードを実行するのが『計算』であり『論理』の『物質』化。」
p.66,67
「コンピュータは、ソフトウェアとハードウェアの複合体で、『論理』と『物質』の間をやりとりする極めて特殊な作業をするのね。それが『計算』ってことよ。『計算』するマシン。計算機=コンピュータ。論理を物質化するマシン。論理を物質化するマシン操作手順書が命令型のコードね。論理操作は、あくまで論理世界の中での仕事、計算は、物質世界での仕事、ハードウェアモードの作業よ」
p.67
「論理世界と物質世界の関係性はクールなコーディングでは重要な視点なの。だって、『論理』に集中してコーディングしていく方針ならば、もう一方の『物質』との関係を常に見極めておく必要があるから。」
p.71
「関数型プログラミングでは、『論理世界』と『物質世界』と関係性を見据えるから、『物質世界』のマシンの操作手順書である命令型のコードは大昔のアセンブラでコードを書くのと大差ないと考えている。」
『物質世界』のマシン操作に労力なんて費やさないので、『論理世界』の論理操作に集中できる、ということになる。それが『論理』を組み立てる関数型プログラミングであり、宣言型プログラミングなの」
p.72
「関数型プログラミングで、その筋では有名なものとしてHaskell(ハスケル)というプログラミング言語があるんだけど、もうこういうのは、最初から徹頭徹尾、『論理』そして『計算』の総称としての『数学』理論でつくられているの。
p.72
「あらゆるプログラミング・パラダイムは、関数型プログラミングのパラダイム、言い換えれば純粋論理である数学に近づこうとしながら進化しているの。そして『数学』みたいな純粋論理の関数型のパラダイムであるならば、論理的にこれよりも進化したパラダイムなんてあるわけがないじゃない」
p.76
「中学校でも数学の授業で証明って習ったとおもうけど、あれはあくまで論理の計算なのね」
p.143
「『インクリメント』は『計算』で『論理』を物質化する命令」
p.144
宣言型のコードは問題の論理のみを扱い、計算結果は扱わない 問題の論理には結果など含まれていない
「確かにこれは論理ではないです。方程式の左辺と右辺の値が異なります(p.143のn=n+1のこと)」
論理世界・物質世界
「論理世界」
問題の論理、本質が存在する世界で、ソフトウェアもここに存在します。
宣言型プログラミングは「論理世界」にコードを組み上げていき、イベントが発生しない限り常に静止しています。
「物質世界」
問題の「論理」に関係ない、フロー(繰り返しや条件判断)が存在する世界で、ハードウェアはここに存在します。「計算」するということは「論理世界」の「論理」を「物質世界」に「物質化」することです。
命令型プログラミングは「物理世界」でハードウェアモードでコンピュータに命令することでコードを実行します。
引用
p.64,65
「プログラミングっていうのはもちろん『ソフトウェア』であるわけ。『論理』の世界のおはなし。ところが『論理』を『計算』するのがコンピュータ、電卓というマシンなの。これは『ハードウェア』ね」
「プログラムのコードは、ソフトウェア。実際に『計算』してくれるハードウェアに依存している。つまり、『論理』を『物質化』してくれる『物質世界』にあるマシンが絶対に必要なのよ。『論理世界』の中だけで、ひとりで完結するような『計算』なんてものはどこにも存在しないから。さっき電卓でやったように、『計算』っていうのは人間のための人間による勝手な行為であって、そもそも『論理世界』にはどこにも存在しない概念なのよ」
p.66,67
「コンピュータは、ソフトウェアとハードウェアの複合体で、『論理』と『物質』の間をやりとりする極めて特殊な作業をするのね。それが『計算』ってことよ。『計算』するマシン。計算機=コンピュータ。論理を物質化するマシン。論理を物質化するマシン操作手順書が命令型のコードね。論理操作は、あくまで論理世界の中での仕事、計算は、物質世界での仕事、ハードウェアモードの作業よ」
p.67
「論理世界と物質世界の関係性はクールなコーディングでは重要な視点なの。だって、『論理』に集中してコーディングしていく方針ならば、もう一方の『物質』との関係を常に見極めておく必要があるから。」
p.71
「関数型プログラミングでは、『論理世界』と『物質世界』と関係性を見据えるから、『物質世界』のマシンの操作手順書である命令型のコードは大昔のアセンブラでコードを書くのと大差ないと考えている。」
『物質世界』のマシン操作に労力なんて費やさないので、『論理世界』の論理操作に集中できる、ということになる。それが『論理』を組み立てる関数型プログラミングであり、宣言型プログラミングなの」
関数
関数は「論理操作」であり、「関数=function=機能、動作、操作、作用」です。
著者の言葉では
f(x)…論理操作
y=f(x)…論理操作の関係、論理構造
です。
関数は論理の最小単位の部品として最上の扱いを受けます。
注意点として、著者が「コード」と呼ぶ場合、命令型の場合はコード全てを指しますが、宣言型の場合は関数の実装はコードには含まれず、関数を組み合わせて実装した部分のみをコードと呼びます。
「サクラ」のクールなコードで使用されているreduceやplusといった関数を作成するためには、ハードウェアモードで命令型のダサいコードを書かなければなりません。「物質世界」の命令型のコードは関数で包み込むことにより、再び「論理世界」の「論理」の最小単位である「関数」となります。
引用
p.15
「関数=function=機能、動作、操作、作用」
p.16
「これにxをINPUT(入力)としてやると、fが持ち合わせる機能により作用され変化したOUTPUT(出力)が出てくる」
「このOUTPUT(出力)はfで作用して変化したという印(しるし)としてf(x)と書き表す習わしになっている」
p.16
「工場にあるマシンみたいなもの」
「炊飯器、電子レンジみたいなマシンもFUNCTION・関数なの。炊飯器という名前のFUNCTIONがあるわね。これに米と水をINPUT(入力)してやると、炊飯器が持ち合わせる機能によって作用され変化した炊きたてのご飯というOUTPUT(出力)が出てくるわ。」
p.18
「Before(ビフォー)の『様々な問題を抱えた家』は『匠』の手が加わると、After(アフター)の『なんということでしょう!!』に『大変身』する」
「『匠』はFUNCTION・関数よ」
「『様々な問題を抱えた家』をINPUT(入力)すれば、匠がその問題を『抱える』ことになり、匠(様々な問題を抱えた家)となり、その『大変身』したAfterは『なんということでしょう!!』なので、なんということでしょう!!=匠(様々な問題を抱えた家)という論理操作の関係、論理構造になっている」
p.19
「関数・functionというものは、作用して変化させる、という論理操作」
p.19
「関数は論理の最小単位の部品として最上の扱いを受ける」
「関数は、レゴ・ブロックのような最小単位の部品なのよ。論理の最小単位としての部品。」
p.20, p21
「plusという変数とは、これこれこういう『足す』という論理操作の関数である!!と定義してやってる」
「この{}中括弧の中でその関数の論理操作、機能の説明、つまり論理の設計をしてやるコードを各わけ」
p.23
「ファーストクラスな部品である関数は、ファーストクラスなので第一級、最上級のクールな扱いを受ける。『足す』という論理操作は、それ自体が最小単位として独立しており、きちんとファーストクラスの最上級の扱いを受ける資格がある」
p.33
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていくときには、関数はファーストクラスの部品としてバラバラに取り扱えるし、部品としてのそれぞれの関数も、問題の論理に必要なように想定して設計していくんですね。関数単位のコードつてなんか素晴らしい」
p.70
「抜け落ちているのは、すでにその命令型のコードっていうのは誰かが書いてくれているってこと」
p.151
計算や入出力の命令というハードウェアモードのマシン操作は論理の物質化だが、関数でラッピングしてふたたび論理化せよ
手順を分割するな、論理を分割せよ
「手順の分割」として下記が例としてあげられています。
1. 匠に玄関を直させる
⇒ 結果(プチAfter)『なんということでしょう!!』
2. 匠に台所を直させる
⇒ 結果(プチAfter)『なんということでしょう!!』
3. 匠に階段を直させる
⇒ 結果(プチAfter)『なんということでしょう!!』
これは結果を小出しにしながら実行しています。
「論理の分割」の例としては下記です。
1. 『玄関の専門的なスキルをもつ匠』を設計する
2. 『台所の専門的なスキルをもつ匠』を設計する
3. 『階段の専門的なスキルをもつ匠』を設計する
「論理の分割」は「論理の最小単位である関数という論理操作を自在に組み合わせて論理を設計していく」です。
著者の考えでは、「手順の分割」とは関数を逐次実行する関数に分割すること。
「玄関の結果 + 台所の結果 + 階段の結果」であり、「論理」ではない「結果」が含まれています。
「論理の分割」とは「問題の本質」を分割すること。
「専門的なスキルを持つ匠=関数」で「論理」を組み立てています。
引用
p.26
「手順を分割して、逐一結果を小出しにしながら実行するのをプログラミングだと思い込んでいる〜それに対してクールなプログラマーは論理を分割しようとしている〜論理の最小単位である関数という論理操作を自在に組み合わせて論理を設計していく」
p.27
「『万能のスーパー匠』を組み上げることこそが問題の論理であり、それはそのまま問題の解決になる」
「『万能のスーパー匠』はすべてやり方を知っており、その行動についてこちらはいちいち口出ししない」
p.27
「reduceとplusという2つの関数が組み合わさって『//をすべて足す』という関数になっているわね?この2つの関数が、『匠』よ。これは、それぞれ逐一実行しろ、という計算の手順書ではないわ。2つの関数を組み合わせて『//をすべて足す』という『スーパー匠』を設計してやっているのよ」
「論理操作の組み合わせの設計だけで、Afterという結果や、フローも、途中の計算手順も、変化し続ける状態変数も何ひとつないんですね」
「そう。手続きを分割して結果を小出しにするループのフローを書くのではなく、論理を分割し論理だけを構成しなさい。」
p.33
「問題の論理そのものをコードに単純に書き写す事を徹底的にやっていくときには、関数はファーストクラスの部品としてバラバラに取り扱えるし、部品としてのそれぞれの関数も、問題の論理に必要なように想定して設計していくんですね。関数単位のコードつてなんか素晴らしい」
『まとまり』は美しい単一の論理構造
関数「y=f(x)」も「論理構造」だが、それとは別の「論理構造」です。
[0, 1, … , 9]は『まとまり』で極めて単純で美しい論理構造です。単一の論理構造は、これ以上分割する余地はありません。
問題に出てくるデータを表す文言をそのまま表したデータ構造です。
0〜9の場合は列挙で構いませんが、0〜999の場合には命令型のダサいコードでrange関数を実装することにより、宣言型のクールなコードを保っています。
reduce(range(1000), plus)のrange(1000)は自然数(0〜999)の『まとまり』ですが、setInterval(f, 1000)は時間軸上の毎秒間隔のイベントという『まとまり』です。
引用
p.139,140
「このsetIntervalっていうのは高階関数ですよね。〜これも『まとまり』を扱う関数ですか?」
「鋭い洞察ね。そのとおり。〜そう。reduce(range(1000), plus)っていうのは、数直線上の0から999までの数という『まとまり』を用意してまとめて操作するための関数だけれども、setInterval(f, 1000)っていうのは、時間軸上の毎秒間隔のイベントという『まとまり』を用意してまとめて操作するための関数なのよ」
「たとえば、コードが解釈実行されてからある時間後のイベント1回だけ、という『まとまり』であれば、setTimeoutということになるし、マウスポインタが動いた瞬間のイベントの『まとまり』クリックされた瞬間のイベントの『まとまり』などなど『まとまり』として処理したい時間軸上のイベントの種類のパターン」
p.149
命令前後の時間で値を変化させていくのではなく、同時に値の複数バージョンをもつ『まとまり』の論理構造を宣言し、まとめて操作する
関数型プログラミング
関数という論理の最小単位の部品を組み合わせてプログラムを作ること。
注意点として、著者は高階関数に関数を渡すことを「関数型プログラミング」と呼んでいます。
論理だけで構成しているため、バグが入り込む余地がありません。
関数型プログラミングでは「車輪の再発明」はしません。
関数型プログラミングより上のプログラミング・パラダイムは原理的に存在しません。
関数型プログラミングで使用する関数を作成(車輪の再発明)するためには、ハードウェアモードで命令型のダサいコードを書かなければなりません。
引用
p.33
「この関数という論理の最小単位で、問題の論理そのものをコードに単純に書き写す事を徹底的にやっていくというクールな方法を世間では関数型プログラミングと呼んでいる」
p.55
「関数型プログラミングをやっていれば自動的に宣言型プログラミングになっていく」
「論理の最小単位の部品としての関数をレゴブロックみたいに組み上げていけば、自動的にフローではない論理の宣言の集合体になるので、勝手に宣言型のコードになっていくのよ。関数型プログラミングをやっていけば自動的に、宣言型プログラミングになっていくってことね」
p.71
「関数型プログラミングでは、『論理世界』と『物質世界』と関係性を見据えるから、『物質世界』のマシンの操作手順書である命令型のコードは大昔のアセンブラでコードを書くのと大差ないと考えている。」
『物質世界』のマシン操作に労力なんて費やさないので、『論理世界』の論理操作に集中できる、ということになる。それが『論理』を組み立てる関数型プログラミングであり、宣言型プログラミングなの」
p.72
「関数型プログラミングは、その意味において、あらゆるプログラミングパラダイムの極致としての存在。ハードウェアモードのアセンブリ言語から、もっとも進化した位置にある。関数プログラミングより上のプログラミング・パラダイムは存在しないわ。原理的に」
p.72
「関数型プログラミングで、その筋では有名なものとしてHaskell(ハスケル)というプログラミング言語があるんだけど、もうこういうのは、最初から徹頭徹尾、『論理』そして『計算』の総称としての『数学』理論でつくられているの。
p.72
「あらゆるプログラミング・パラダイムは、関数型プログラミングのパラダイム、言い換えれば純粋論理である数学に近づこうとしながら進化しているの。そして『数学』みたいな純粋論理の関数型のパラダイムであるならば、論理的にこれよりも進化したパラダイムなんてあるわけがないじゃない」
p.76
「あくまで関数型プログラミングの延長として、定理証明支援系言語っていうものが存在する」
p.90
「そう、宣言型の見透しのよいクールなコードになった。reduceがマシンに命令するハードウェアモードの作業を、完全に水面下に隠蔽してくれているの」
p.93
「実際やってみたら、reduceという『匠』のスキル=関数を設計してやるのは、あなたが最初にダサいコードでフローを書いたような手間とさほど違いなんてなかったでしょ?」
p.106
「答えが合うのは当たり前よ。全部論理だけで構成しているんだから。関数同士の組み合わせがいくら複雑になっても、バグが出る余地なんて全くないから」
p.110
『まとまり』という論理構造をまるごと操作する関数ライブラリは、『神の眼』が見透す、宣言型のコードを書くために必須の関数@ハードウェアモード大全集
p.140
「なるほどなぁ。関数型プログラミングでは、そういう時間軸上のイベントの『まとまり』を操作するという関数で宣言していくコードを書くことで、イベント駆動させていく」
「もう全部が全部『まとまり』とそれを操作する関数だけでコードができあがっていく、時間軸上のイベントの『まとまり』を操作する関数をもって駆動する、かなり一貫したやり方ですね。」
「そのとおり。クールなやり方よ。時間のフローで勝手に動く。コードの論理は静止している」
p.148
破壊的代入する命令は、関数にする
命令型プログラミング
計算の手順を並べるコード。手順通り上から下に並べたものです。
マシンに向けて計算しろという『命令』になっていて、ハードウェアモードで逐次実行されます。
命令型プログラミングのコードには同じ変数が異なる時間をもって異なる値で存在します。
参照透過性をろくに考慮しない、論理に極めて無頓着な原始的なプログラミングパラダイムです。
引用
p.50, 51
「電卓に自動的にやらせたい計算の手順を順序良く並べて、事前にまとめて電卓に受け渡しておく」
「手順通りに上から下に並べたもの」
「マシンに向けて計算しろという『命令』になっている。」
「これはマシンに順番に逐一命令していくコード」
p.52
「命令型プログラミングのコードは『マシン操作手順書』であり『フローは不要』のフローそのもの」
p.68
『物質世界』密着型の命令型プログラミングという原始的パラダイム
「命令型プログラミングというのは、コンピュータというハードウェアがソフトウェアの『論理世界』の存在ではなくて、『物質世界』に存在するマシンなのでうまく操作するために順序良く命令する、という当然の発想から出てきた歴史的な必然。つまり原始的プログラミング・パラダイムと言えるわね。」
p.132,133,134
命令型のコードは『フロー』で駆動する『フロー駆動』
「『物質世界』密着型の命令型プログラミングのコードでは、このようにフローが明確でそのとおり計算されていくハードウェアモードだってことがわかります。でも『論理世界』密着型の宣言型プログラミングのコードでは、突き詰めていくと、その計算の順番っていうのはいったいどうなるのかな?と。」
p.145
命令型プログラミングのコードの上下左右に、同じ変数が異なる時間をもって異なる値で存在している混乱
「命令型のコードでの問題は、『物質世界』の時間要素がコードの中に紛れ込んじゃうことよ。n=n+1という方程式の右辺にあるnは、命令前の値。左辺にあるnは、命令後の値。つまり『時間』が違うの。方程式という論理に『時間』が違う『同じ変数』があり、=とされてしまっている」
p.147
「命令型プログラミングは、参照透過性をろくに考慮しない、論理に極めて無頓着なプログラミングパラダイム」
宣言型プログラミング
『フローのない論理の宣言書』である宣言型のコード。「論理」をそのまま書き写したものです。
関数型プログラミングをやっていれば自動的に宣言型プログラミングになっていきます。
宣言型のコードは常に静止していて、必ずイベントで駆動する「イベント駆動」です。
引用
p.55
「『フローのない論理の宣言書』である宣言型のコード『宣言型プログラミング』」
p.55
・計算の命令 ではなくて ⇒ 論理
・マシン操作手順書 ではなくて ⇒ 論理の宣言書
p.55
「関数型プログラミングをやっていれば自動的に宣言型プログラミングになっていく」
「論理の最小単位の部品としての関数をレゴブロックみたいに組み上げていけば、自動的にフローではない論理の宣言の集合体になるので、勝手に宣言型のコードになっていくのよ。関数型プログラミングをやっていけば自動的に、宣言型プログラミングになっていくってことね」
p.56
「宣言型のコードこそが『コードを見透せる眼』が見透せているコード」
p.56
「『神の眼』のコードは宣言型のコード」
p.68
『論理世界』密着型の宣言型プログラミング
「宣言型プログラミングは、なによりまず『論理』を最初に考える『論理世界』密着型」
p.77
「数学の証明の形式が、そのまま宣言型のコードとなっていく。コードとして矛盾がない証明を完成させれば、それがすなわちプログラミングとなってしまう。『論理世界』密着型の宣言型プログラミング」
p.134
宣言型のコードは『イベント』で駆動する『イベント駆動』
「宣言型のコードはすべてイベントで駆動するのよ。イベント駆動」
p.137
「fはハードウェアモードを包み込む関数。現在の時刻を取得して、あるフォーマットでコンソールに表示する。『物質世界』とのやりとりで、命令型のコードね。そしてキモの部分は、もちろん、var clock = setInterval(f, 1000);で、ここが宣言型のコード」
p.137
「var clock = setInterval(f, 1000);は、単に『論理世界』の論理の宣言でしかない宣言的のコードよね?これは『物質世界』の時間軸上のイベントと結びついており、そのイベントで駆動されるわけよ。時間軸上のイベントが『論理世界』と『物質世界』の唯一の接点」
p.138
時間のフロー(流れ)が宣言型のコードを駆動するイベント駆動は、時間フロー駆動
「うーん、時間軸上のイベントが『論理世界』と『物質世界』の唯一の接点、ですか。ということはコンピュータのソフトウェアとハードウェアが、時間の流れで接点を持っているという構造になるんですかね・・・」
p.138
「ここがまさにクールなコーディングの神髄なのよ。var clock = setInternal(f, 1000);っていう宣言型コードは、『静止している』わよね?静かで静的な『論理世界』よ。ただそこでじっと『静止している』」
「『物質世界』密着型の命令型プログラミングのフローのコードに慣れてしまっていると、なかなか気付けないけど、『論理世界』密着型の宣言型プログラミングのコードでは、フローがないってことは、つまり『静止している』わけ」
「コードのほうは『静止している』。動くのは、時間の流れのほうなのよ」
「なるほど!『論理世界』ではフローは不要になって、どこにいっちゃったのか?っていうと、『物質世界』の時間のフロー(流れ)になっていて、それが宣言型のコードを駆動させるんですね!」
「そのとおり。ここで重要なのは、私達はまったく『物質世界』の時間のフロー(流れ)のことは気にする必要ないのよ。だってそれは最初から『物質世界』の一部として組み込まれているから」
「そうですよね。イベント駆動っていうのは、時間フロー駆動だ!」
p.147
宣言型プログラミングは参照透過である
p.149
命令前後の時間で値を変化させていくのではなく、同時に値の複数バージョンをもつ『まとまり』の論理構造を宣言し、まとめて操作する
ソクラテスの「無知の知」
まわりの皆を、本当は何も知らないだろう?と論破していったら死刑になったそうです。
著者はそれを自分になぞらえています。
また、「無知の知」がない訳知り顔のプログラマはダサくて面倒くさい連中です。それはソクラテスを死刑にしたような連中と同類です。
『計算』とは『論理』の物質化、ハードウェアモード
すでに存在する「論理」を人間が「問題」と認識し、答えをメモリやモニタなどの物質として見える化すること。
『計算』は『論理』であるソフトウェアを『物質』であるハードウェアが実行すること。
ほとんどのプログラマは気にもせず、計算理論を勉強したプログラマでもわかったつもりの人が多い。
計算以外にも『ユーザー・インターフェース』『コンピュータの入出力』『サーバの実装方法』『並列コンピューティング』『オブジェクト指向』なども『論理』の物質化です。
引用
p.58
「『論理』と『計算』は別物 『論理』は人間とは関係なくただそこにある存在、それを人間が明らかにする行為が『計算』
「この『論理』と『計算』を全部ひっくるめたものを『数学』と呼ぶ」
p.63
「実際ここはほとんどのプログラマがまったく気にしていない部分ね」
「説明したところで、妙な顔をされるだけのパターンが多いでしょうね。チューリングマシンだのなんだの、そういう計算理論でわかったつもりの人も多いし」
p.63
「『論理』を人間が明らかにする行為が『計算』。明らかにする、っていうのは具体的にいうと『物質化』よ。『論理』を人間が『物質化』する行為が『計算』。言い換えると、『計算』とは『論理』の物質化」
p.64
「『計算』っていうのは、『論理』と『物質』の狭間にある。その証拠にコンピュータ=計算機というのは『ハードウェア』と『ソフトウェア』の2つが貼り合わされて構成されている存在よね?」
p.64,65
「プログラミングっていうのはもちろん『ソフトウェア』であるわけ。『論理』の世界のおはなし。ところが『論理』を『計算』するのがコンピュータ、電卓というマシンなの。これは『ハードウェア』ね」
「プログラムのコードは、ソフトウェア。実際に『計算』してくれるハードウェアに依存している。つまり、『論理』を『物質化』してくれる『物質世界』にあるマシンが絶対に必要なのよ。『論理世界』の中だけで、ひとりで完結するような『計算』なんてものはどこにも存在しないから。さっき電卓でやったように、『計算』っていうのは人間のための人間による勝手な行為であって、そもそも『論理世界』にはどこにも存在しない概念なのよ」
p.65
「コードは、ソフトウェアであり『論理』なのよ。コンピュータというマシンは、ハードウェアであり『物質』。コンピュータでコードを実行するのが『計算』であり『論理』の『物質』化。」
p.66,67
「コンピュータは、ソフトウェアとハードウェアの複合体で、『論理』と『物質』の間をやりとりする極めて特殊な作業をするのね。それが『計算』ってことよ。『計算』するマシン。計算機=コンピュータ。論理を物質化するマシン。論理を物質化するマシン操作手順書が命令型のコードね。論理操作は、あくまで論理世界の中での仕事、計算は、物質世界での仕事、ハードウェアモードの作業よ」
p.67
「論理世界と物質世界の関係性はクールなコーディングでは重要な視点なの。だって、『論理』に集中してコーディングしていく方針ならば、もう一方の『物質』との関係を常に見極めておく必要があるから。」
p.67
「これはなにも『計算』に限らないのよ?『論理』の物質化について、論理世界と物質世界の関係性は、コンピューティング全般にわたる非常に重要な問題なの。『ユーザー・インターフェース』『コンピュータの入出力』『サーバの実装方法』『並列コンピューティング』『オブジェクト指向』もうこういうものは全部がぜーんぶ、『論理』の物質化、『論理世界』と『物質世界』の関係の話になるのよ」
p.110
『まとまり』という論理構造をまるごと操作する関数ライブラリは、『神の眼』が見透す、宣言型のコードを書くために必須の関数@ハードウェアモード大全集