Scheme入門 第10章 λ ~ラムダ~
次のような関数を考えてみませう。
(define (f p) (p 1 2))
なんでしょうこれは。何をする関数なんでしょうか。渡された p
を、あたかも関数のように呼び出しています。これは例えば次のように使います。
(display (f +))
(newline)
(display (f *))
(newline)
最初のやつだと、関数 f
の引数 p
には +
を渡してますから、(p 1 2)
は (+ 1 2)
で 3
になります。2番目のも同様に考えると (* 1 2)
で 2
です。納得しました?そう、関数に関数を渡してもいいんです。関数を受け取る関数を「高階関数」とか言います。Scheme には標準で map
という高階関数が用意されています。これを使ってみましょう。map
は、リストの各要素に関数を適用する関数です。
(define (inc x) (+ x 1))
(display (map inc '(1 5 10)))
inc
はわかりますね。値を 1 だけ増やす関数です。
で、実行すると次のように出ます。
(2 6 11)
リストの各要素に inc
が適用されて、1 ずつ増えたわけです。値が数値かどうか判定する number?
を使ってみますと、
(display (map number? '(2 4.5 "Hello")))
次のように、それぞれの要素が数値かどうか判ります。
(#t #t #f)
渡す関数を別の関数に取り替えるだけで色々なことが出来る、便利な関数です。ちゃんと作られた高階関数は、すべからく便利なのです。
さて、高階関数には、関数を渡すわけですが、たった一度しか使わないような関数でも、いちいち名前を考えて define
で定義しなきゃならんわけです。それは面倒だということで、define
を使わずに無名の関数を作れるようになっています。無名関数は、例えば次のように書きます。
(lambda (x) (+ x 1))
先程の inc
と同じ、値を1だけ増やす関数です(相変わらず芸のない…)。lambda
(ラムダと読む)は、無名関数を作る構文です(※)。試しにその無名の関数を、この前のように display
で表示させてみましょうか。
(display (lambda (x) (+ x 1)))
実行結果:
#<procedure>
ふむ。確かに関数(手続き)のようです。次のように変数に代入すれば、普通に呼ぶことも出来ます。
(define inc (lambda (x) (+ x 1)))
(display (inc 5))
おっと、元々の目的は、map
に渡す一度きりの関数を作ることでした。では早速。
(display (map (lambda (x) (+ x 1)) '(1 5 10)))
実行結果:
(2 6 11)
期待通り。問題なしです。
第10章・完
第11章へ
※:ところで何故ラムダなのだろう?それどころか、魔法言語リリカル☆LispにもDrSchemeのロゴにもλと言うアイコンが表れているし、それどころか、多くの関数型言語と呼ばれるプログラミング言語でもλが共通のマークとして使われている。不思議に思った人も多い筈だ。
「λはそんなにエラいのか?」
と。
実はラムダ計算と言われる数学の一理論がある。内容はかなり高度で、論理学とも接しているし、ある種メタ数学の一種と捉えることも出来るが、興味のある人は調べてみてほしい。
今、ここで重要なのは、Schemeの元となったプログラミング言語、Lispは、元々「プログラミング言語として設計されたモノではない」と言う事だ。あくまで数学理論の「ラムダ計算」の研究の一環として出てきたもので、偶然これを
「プログラミング言語として実際プログラムしてみたらどうだろう?」
と思いついた人間がいた、と言うだけの事だ。これがプログラミング言語Lispの誕生の瞬間である。ちなみに、その「思いついた人間」とは世界ではじめてのビデオゲームを作ったスティーヴ・ラッセルその人である。
LispやSchemeがC言語やBASIC等と決定的に違うのは、後者はあくまで「工学上の要請により"人為的に"」設計されたモノだが、前者は元々「数学そのもの」であった。要するに、ルーツが全然違うワケだ。そう言う意味では「関数型言語」といわゆる「プログラミング言語」は同じ土俵にはいない。また、工学上での「言語設計に於けるデザインの問題」と言うのも数学では生じない。LispやSchemeは本質的には既に"あるべきデザイン"なのである。
なお、本当に「高校生の為の実用的プログラミング入門」を考えるのだったらBASICは向かない、と言う意見には変わりはないが、Schemeも実は向かないと思う。「実用的なプログラミングの基礎を学ぶ」事を考えた場合、BASICとSchemeには共通の問題点が存在する。
と言うのも、「就職」だ何だ、と考えたとき、結局ベストな選択は「良く使われている言語」を学ぶか、もしくは「良く使われている言語に似た簡易版言語」を学ぶ、とならざるを得ないだろう。それが「実用的」と言う意味だし、英語を学んだ方がマイナーな、例えばヨルバ語を学ぶよりマシだ、と言う理由と同じである。前者は比較的「理解してくれる人が多い」が後者を使える人間は限られている。ちなみに、ヨルバ語とはボビー・オロゴンの母国語である。おい、ふざけんなよ。
かつ、ここで重要なのは、コンピュータはインストールさえされていれば「どんな言語だろうと」理解してくれるが、実はネックになってるのは「人間の方」である。人間はインストールさえされていればどんな言語も理解してくれる、と言うワケにはいかない。つまり、いわゆる「実用性」とは本質的には「何が出来る/出来ない」とは全く関係が無いのだ。コンピュータの方に問題があるのではなく、「広い範囲での共通言語を欲しがっている」のはあくまで人間の側である。
しかしながら「高校生の数学の為のプログラミング入門」と言う限定トピックだったら間違いなくSchemeが一番適している。高校数学の窓と言うサイト向きのプログラミング言語なのだ。
と言うのも
「数学を記述するには数学が一番向いているから」
と言う至極単純な判断による。反面、「数学を記述するのに工学を用いる」と言うのは不自然極まりない。また、Schemeは元々「プログラミング初学者用の教育用言語」としてシンプルに設計されてもいる。
餅はやっぱり餅屋なのだ。
- DrScheme での Language Pack の選択
- Scheme の単純な式「(+ 3 2)」, 「(- 10 4)」
- Scheme の単純な式(括弧の入れ子)
- Scheme の単純な式 (DrScheme の定義ウインドウ)
- 関数 area-of-disk の定義と,関数適用
- 関数 area-of-disk,変数 PI の定義と,関数適用(1)
- 関数 area-of-disk,変数 PI の定義と,関数適用(2)
0 コメント:
コメントを投稿