高校数学の窓過去問検索

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






  1. DrScheme での Language Pack の選択

  2. Scheme の単純な式「(+ 3 2)」, 「(- 10 4)」

  3. Scheme の単純な式(括弧の入れ子)

  4. Scheme の単純な式 (DrScheme の定義ウインドウ)

  5. 関数 area-of-disk の定義と,関数適用

  6. 関数 area-of-disk,変数 PI の定義と,関数適用(1)

  7. 関数 area-of-disk,変数 PI の定義と,関数適用(2)


0 コメント: