• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:scheme でのスコープについて)

schemeでのスコープについて

このQ&Aのポイント
  • schemeでのスコープについて説明します。
  • schemeのconsとcarの定義に関して説明します。
  • dispatchの有効範囲について疑問があります。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

この辺、「関数を返す関数を書ける」ってのがちょっと混乱するんですよね(笑)。Lisp系言語ですと割に平気でそれやっちゃうんで。 ポール・グレアムの「ANSI Common Lisp」でもいきなり累積器(アキュムレータ)の例を出して、「どうだ?こんなの他の言語じゃ書けないだろ?」的な例として挙げてたりします。 (defun addn (n)   #'(lambda (x)     (+ n x))) この辺の「クロージャを返せる」ってのは意図しないとあまりやらないんで、コードを読む際、「あれれれれれ?」ってなる確率が高いんで、気を付けた方が良いですね。 特に、SICPは「アセンブリ言語的な事を」Schemeでやってみせる、ってノリなんで、かなりこの辺は難しいですよね。件のcons、car、cdrの例も、Schemeの手続きとしての説明、と言うよりもコンピュータ上のデータ構造の解説、って感じですし。 (実際、データと手続きの区別が無い、ってのはアセンブリ言語の特徴、だそうです。) ちなみに、クロージャを返す、って事を徹底的に利用したサンプルに次のブログで紹介されているコードがあります。これ見た時僕はひっくり返りました(笑)。ネタはクダラない(って言っちゃえばアレなんですが・笑)んですが、プログラムの命令を人間が読める形式にクロージャを駆使して持ち込んでる、ってのが凄いな、と思いました。 http://d.hatena.ne.jp/yshigeru/20080418/1208523696

pikacha
質問者

お礼

schemeを始めてまだ間もないもので、関数を返す関数や、関数を引数にとる関数というのに少し混乱してしまいます。 ブログの紹介ありがとうございます。 schemeは本当に何でもできてしまうんですね! 引数や戻り値に関数をとることができることはとても抽象度の高いことなんですね! これから慣れていけたらと思います。 細かなことまで教えていただきありがとうございました。

その他の回答 (1)

回答No.1

「計算機プログラムの構造と解釈」でしょ? 最初のコードって一行足りないんじゃないですか? (define (cons x y)  (define (dispatch m)   (cond ((= m 0) x)      ((= m 1) y)      (else (error "Argument not 0 or 1 -- CONS" m))))    dispatch) ;; ここが足りない 多分この辺のかなり難易度の高い教科書に関しての質問はここにポストするより、例えば……そうだなあ、 SICP Reading Wiki: http://www.csus4.net/hiki/SICPReading/ 辺りにでもポストした方が有用だとは思うんですけどね。難しすぎて(笑)。 有効範囲は仰るとおり、だと思いますよ。 ただし、SICPのconsの例だとクロージャを返してるから、でしょうね。だから「環境を閉じ込めて」そのまま返している。 SICPに次の記述がありますね。 >気をつけるべきは(cons x y)の返す値が「手続き」(※ここが重要)であることだ。つまり内部的に定義された手続きdispatchで、これは一つの引数をとり、引数が0か1かによってxかyを返す。これに対応して(car z)はzを0に作用させると定義している。 つまり、上の例だと(car (cons 1 2))ってのは ((cons 1 2) 0) ってのが内訳でしょうね。これは形式的にはラムダ式で次の計算 ((lambda (m) (if (= m 0) 1 2)) 0) を行っている事と同じになると思います。

pikacha
質問者

お礼

回答をありがとうございます。 おっしゃる通りSICPです。 質問文に対するご指摘ありがとうございます。 consの定義の最後にdispatchが抜けていました。 なるほど! dispatchという手続きを返していますが、それは内部的には (define dispatch (lambda (m)   (cond ((= m 0) x)      ((= m 1) y)      (else (error "Argument not 0 or 1 -- CONS" m))))) という定義になっていますから、その内部定義においてdispatchを返すということは (lambda (m)   (cond ((= m 0) x)      ((= m 1) y)      (else (error "Argument not 0 or 1 -- CONS" m)))) を返すことに他ならない訳ですね! 詳しい丁寧な説明をありがとうございました。