• ベストアンサー

Scheme 中置式から後置式へ

cametan_42の回答

回答No.6

>そこで早速#5でいただいた定義式をDr.Schemeに打ち込んでRunを押してみたのですが、evalが未定義ですとのエラーが表示されました。 う~ん、それはおかしいですね。 evalってのはLisp系言語の根底モデルの関数なんで「絶対ある」筈なのです。 (実際、ANSI Common Lispなんかではevalそのものは実装上「特に何が何でも必要のある関数」では無くなってるらしいんですが、いずれにせよ、Schemeなんかの「教育用Lisp」では概念説明上「絶対にある」手続きです) DrSchemeのヴァージョンは何でしょうか?また、DrSchemeでは[言語の選択...]ってのがある筈なんですけど、多分Pretty Bigを選んだ方がいいと思います。 僕はMzScheme(DrScheme、と言うかPLT SchemeのCLI版)4.1.3使用してて、提示コードは問題無く走ってるんで、恐らく走る筈だと思います。また、[言語の選択...]でR5RSを選択すると、tomotomo2309jpさんが記述した「モダンなスタイル」のSchemeコーディングだと走らない可能性があるんで([]が認識不可、として引っかかる)、Pretty Bigを選んだ方が無難でしょう。 注:ちなみに、提示コードは本当は古き良きcar、cdr、cadr、null?等を使って組み立てたんですが、tomotomo2309jpさんの記述に合わせて、全てEmacsでわざわざ置換して「モダンスタイル」に変更したモノです。Schemeユーザーはfirst、rest、second、empty?ってあんま使わないんじゃないのか、と思います。微小ですが、「旧来のスタイル」の方が文字数が少ない=タイピング量が減る、からです。意味は「モダンスタイル」の方が明解ではあるんですけどね(笑)。 >いま大学の図書館で「Structure and Interpretation of Computer Programs」をみてevalに関する記述を探してみたのですが、洋書な上、evalの定義式もかなり複雑なもので、理解できませんでした。 ああ、第4章でしょ? tomotomo2309jpさんは偉いです。早速本調べて、ってのはなかなか出来る事じゃありません。頭が下がります。 んで、定義式書いてるんでしょうが、実際問題SICPの第4章ってのは「LispでLispを作ろう」、現代っぽく言うと「仮想マシンの設計」やってんです。 従って、そこ見ても「理解出来ない」と言うのはtomotomo2309jpさんの責任じゃないです。初心者には複雑過ぎるんです。 >SICPではevalは二つの引数を要求するものでした。evalとはどのようなものなのでしょうか? 単純に言うと、S式とそれが定義された環境の二つを引数にして取るんですが、SICPは脇に置いておいて、恐らく次の文書辺りで理解に対しては十二分なんじゃないのかな、と思います。 フォームと評価: http://www.stdio.h.kyoto-u.ac.jp/~hioki/gairon-enshuu/SchemeNotes/eval-quote.html eval使ったのは、Lisp系の入門書にも色々あって、最初に概念モデルとしてevalを導入段階で説明する教科書と、「もっと難しいLispモデルの真髄」と言う扱いで後半で扱う教科書と、2タイプあるんですよ。んで、tomotomo2309jpさんの大学ではどっちなんだろ?ってちょっと分からなかったんですね。 >>#4の方でも示唆されていましたが、本来あんまevalそのものは「積極的に」使うべきものでもないんです。「評価(evaluate)」を概念的に説明する関数なんで。また、eval使うとコードが汚く(笑)見えるのも事実なんです。 僕の場合は、「Scheme習いたてだ」ってんで、Wikipediaの「レジスタ上での計算部分」を面倒無く提示出来ないか、と、要するにあくまで「手抜き」の意味で使ったんで、本来あまり褒められたやり方じゃない、と思います(笑)。だから、「evalが分からん」と言うのなら、無理して理解しないで結構です。 一応、例えば単なるS式、評価を止める(クオート付きの)S式、evalの使用例を以下に提示してみます。 > (+ 1 2) ;単なるS式は 3     ;自動で評価(evaluate)される > '(+ 1 2) ;引用符(クオート)すると、 (+ 1 2)  ;評価は避けられる > (eval '(+ 1 2)) 3 3番目見ると分かりますが、要するにevalってのは「強制評価の為の」関数です。 >ちなみに今は「Advanced student」を使っています。 ああ、やっぱそうでしょう。 [How to Design Programs]のカテゴリに含まれる選択言語は、MIT Pressの教科書、 How to Design Programs: http://www.htdp.org/ の「副教材」目的のパッケージじゃなかったかしら?だからテキスト準拠の制限かかってるんじゃなかったかな?そして、そのテキストを使わないとあまり意味が無いような気がします。 だから、通常使用する場合は、制限を開放した「Pretty Big」使った方が良いでしょう。

tomotomo2309jp
質問者

お礼

本当に何度も何度もご回答ありがとうございます! 教科書は書き忘れましたが、「How to Design Programs」となっています。ちなみに授業はこれに沿ってやっているだけで生徒で実際にこの本を持っている人はいないです。 Bの問題ですが、教えていただいた定義分を元に、自分なりに書き換えてみました↓ (define (stackM m s)      (cond       [(empty? m) s]       [(number? (first m)) (stackM (rest m) (cons (first m) s))]       [else (stackM (rest m) (cons (eval (list (first m) (first (rest s)) (first s))) (rest (rest s))))])) そして言語を"Pretty Big"にしたらついに動きました!! evalについての説明はとてもわかりやすかったです! あと、Aについてですが、下のように途中まではできました。 (※eはemptyとします) (define (revP l e)   (cond    [(empty? l) e]    [(number? (first l)) (revP (rest l) (cons (first l) e))]    [else (revP (rest l)...)] と、ここまで打って気づいたのですが、これってlの最初の要素がリストだったらうまく動きませんね。。。どうにかこれを回避できないでしょうか? できるだけ自分で解けるようになりたいのでもう少し考えてみたいと思います。もしよろしければこの点にお答えいただければとてもうれしいです。

関連するQ&A

  • schmeスキームのプログラミングについて質問です

    listから条件に合わない数を消すfilter1という関数をつくりたいです。 ただ条件があって次のseries関数を使わなければいけません。 (define (reduce op base L) (cond [(empty? L) base] [else (op (first L) (reduce op base(rest L)))])) 自分は以下のような補助関数を含むプログラムを作ったのですが、****の部分をどうすればいいかわかりませんでした。 (define(filter1 rel_op L t) (cond [(empty? L) empty] [(rel_op (first L) t) (reduce f1 0 L)])) (define (f1 L t) (cond [(empty? L) empty] [***** (cons (first L)(rest L))] [else (rest L)])) もしよろしければ回答お願いします。 根本的に間違っているのなら、どのような道筋でプログラムを作るかだけでもいいので教えてください。

  • Lispについてわからないことが(Scheme)

    あるLispの勉強ソフトで、 「関数lを『引数としてxを受け取ると、xの要素の数を返す関数』として定義しなさい。」 という問題があるのですが、私は以下のようにしました。 (define l (lambda (x) (if (= x null?) 0 (+ 1 (l (cdr x)))))) しかしこれだとオーバーフローと表示されて強制終了されてしまいました。 そこで答えをネットで検索したところ以下のものが見つかりました。 (define l (lambda (x) (cond ((null? x) 0) (else (+ 1 (l (cdr x))))))) これが正解なようですが、この2つのリストの違いがわかりません。 初歩的なことですがifの使い方を間違っているんでしょうか?

  • scheme でのスコープについて

    次のようなcar,consの定義をします. ;;consの定義 (define (cons x y)  (define (dispatch m)   (cond ((= m 0) x)      ((= m 1) y)      (else (error "Argument not 0 or 1 -- CONS" m)))) ;;carの定義 (define (car z) (z 0)) ここで、 (car (cons 1 2)) を評価したいのですが、次のような置き換えモデルで考えてみました。 (car (cons 1 2)) (car dispatch) ;まず引数を評価 (dispatch 0) ;car を評価して引数に作用させる 1 質問は、dispatchの有効範囲についてです。 dispatchはconsの内部定義なので(cons 1 2)を評価後、carに引数として渡すには,その時点でdispatchが有効でなくなりエラーになると考えたのですが、実際は動きました。 どこがおかしいのでしょうか。環境モデルでも考えてみたのですが分かりませんでした。よろしくお願いします。

  • Schemeの質問

    最近Schemeを習い始めたのですがlambdaの概念がよく分かりません。 適当に見つけた例題やらを見ながら、末尾再帰法でリストの中から一番小さい数を表示する関数を書きました。リストが空なら'()を返します。 (define (small List) if (null? List a) '() (small2 List 0))) (define small2 (lambda (list a) (cond ((null? List) a) (or (= head 0) (> head (car List))) (small2 (cdr List) (car List))) (else (small2 (cdr List) a))))) 一応ちゃんと動くのですが、無駄にいっぱい書いている気がします。lambdaを使わない方が短くできるんでしょうか?lambdaを使うべきなのか使わないべきなのかの判断がうまくできません。

  • Schemeについての問題

    今大学でSchemeについて学んでいるのですが、そこで出た問題がわからなくて困っています。 よければ、教えていただけないでしょうか。 問題は以下の通りです。 問1 次に示すScheme プログラムについて以下の問に答えよ。 (define (subtree? t1 t2) (cond ((atom? t1) (eq? t1 t2)) (#t (cond ((atom? t2) #f) (#t (or (and (subtree? (car t1) (car t2)) (subtree? (cdr t1) (cdr t2))) (or (subtree? t1 (car t2)) (subtree? t1 (cdr t2))))))))) 関数subtree?は二つのS 式(S 表現) t1, t2 を入力とし、真偽値(#t あるいは #f) を返す関数である。 関数subtree?が真(#t) を返すための必要十分条件は何であるか答えよ。 また、関数subtree?が実際そのような関数であることをS 式に関する帰納法を用いた議論によって示せ。 考えたのですが、わからなくて。こんな質問してしまって申し訳ないです。 よければよろしくお願いしますm(_ _)m

  • [Scheme] リストへの破壊的代入について

    以下のプログラムが動かない理由がわかりません. (define cdrlst  (lambda (lst)   (set! lst (cdr lst)))) 内容としては,引数で与えられたリストの先頭を取り除くというものです. 対話的な方法で以下のように実行すると,上記と同様の方法でも動作しますが,ラムダ式の中に入れると動作しなくなります. > (define cdrlst ... (略)) > (define l (list 1 2 3 4)) > (set! l (cdr l)) > l (2 3 4) > (define lst (list 1 2 3 4 5) > (cdrlst lst) > lst (1 2 3 4 5) どうか,よろしくお願いします. 処理系 : DrScheme version 370 [3m] ;Standard(R5RS)

  • 式をC言語で立てれません

    式をC言語で立てれません 式をC 言語で立てれません こんにちは。私は今実験で円板振動子の中心軸上の音圧分布を求めています。 そこで写真のような図をプロットするために与えられた式をC言語で書いています。 式の詳細は P/2ρcV = |sinπ(√(r/λ)^2 + (a/λ)^2)(√はここまで)-(r/λ))| です。 しかしうまくプロットできません。 プログラムは ------------------------------------- #include <stdio.h> #include <math.h> #define F 120 //周波数(Hz) #define C 1500 //音速(m/s) #define A 0.2 // 半径(m) int main() { double x, m, s, p, o, w, l; int i; for (i=0; i<100; i++) { x= (double)i; //観測点までの距離を表しました。距離が変化することで音圧が変わるためです。 l = C/F; //λをlとして音速÷周波数で定義できます。 m = x/l; //x軸です。 o = m*m + (A/l)*(A/l); //式のsinの中身です。 s = sin(M_PI*(sqrt (o) - m)); //sin全体を定義します。 w = fabs(s); //sin全体を絶対値に置き換えます。 p = w; //新しい変数に入れます。 printf("%9.9f %9.9f\n", m, p); } return 0; } ------------------------------ といった感じです。先生からはx軸のプログラムだけいじれば勝手に y軸も出てくるとヒントを頂いているのでx軸についてのプログラムを 書いています。コンパイルはできても写真のようにいきません。 半径やλや周波数はa/λ=2.5と書いてあったので値は推測です。 C言語はあまり得意ではないので困っています。 お分かりになる方、ご教授お願い致します。 ※式が間違っていたので新しく質問します。

  • Schemeのプログラミング うるう年関連

    Schemeのプログラミング うるう年関連 Schemeで、 「(1)閏年かどうかを判定する関数leap?(number -> boolean)を定義した後、(2)○年○月の日数は何日かを求める関数num-of-days(number number -> number)を定義せよ」 という内容の課題を出されたのですが、(例えば 2009年の7月→31日 2012年の2月→29日) どうもエラーが出て実行できません。 自分は以下のように組みました。 ;;(1)の関数 (define (leap? year) (cond [(= (remainder year 400) 0) #t] [(and (= (remainder year 4) 0)(> (remainder year 100) 0)) #t] [else #f] ) ) ;;(2)の関数 (define (num-of-days year month) (cond [(and (= month 2)(= (leap? year) #t)) 29] [(and (= month 2)(= (leap? year) #f)) 28] [(or (= month 1)(= month 3)(= month 5) (= month 7)(= month 8)(= month 10) (= month 12)) 31] [else 30] ) ) これを例えば (num-of-days 2008 4) や (num-of-days 1995 12) などとして実行すると、それぞれ30,31という正しい値を返してくれるのですが、 (num-of-days 2008 2) や (num-of-days 1995 2) など、閏年・非閏年に関係無く、2月が絡むと =: expects type <number> as 1st argument, given: false; other arguments were: true というエラーを吐いてしまいます。 何度も見直しましたが、どこが間違っているのか見付けきれません…。どなたか間違いを指摘して頂けると幸いです。

  • 式をC言語で立てれません

    式をC言語で立てれません こんにちは。私は今実験で円板振動子の中心軸上の音圧分布を求めています。 そこで写真のような図をプロットするために与えられた式をC言語で書いています。 式の詳細は P/2ρcV = |sinπ(√(r/λ)^2 + (a/λ)^2)(√はここまで)-(r/λ)^2)| です。 しかしうまくプロットできません。 プログラムは ------------------------------------- #include <stdio.h> #include <math.h> #define F 120 //周波数(Hz) #define C 1500 //音速(m/s) #define A 0.2 // 半径(m) int main() { double x, m, s, p, o, w, l; int i; for (i=0; i<100; i++) { x= (double)i; //観測点までの距離を表しました。距離が変化することで音圧が変わるためです。 l = C/F; //λをlとして音速÷周波数で定義できます。 m = x/l; //x軸です。 o = m*m + (A/l)*(A/l); //式のsinの中身です。 s = sin(M_PI*(sqrt (o) - m)); //sin全体を定義します。 w = fabs(s); //sin全体を絶対値に置き換えます。 p = w; //新しい変数に入れます。 printf("%9.9f %9.9f\n", m, p); } return 0; } ------------------------------ といった感じです。先生からはx軸のプログラムだけいじれば勝手に y軸も出てくるとヒントを頂いているのでx軸についてのプログラムを 書いています。コンパイルはできても写真のようにいきません。 半径やλや周波数はa/λ=2.5と書いてあったので値は推測です。 C言語はあまり得意ではないので困っています。 お分かりになる方、ご教授お願い致します。

  • この関数がどのような計算を行うものか教えて下さい。

    #define NULLC(char) 0 #define YES 1 #define NO 0 int string_compare(char *s1, char*s2){ while(*s1==*s2) if(*s1==NULLC) if(*s2==NULLC) return YES; else return NO; else if(*s2==NULLC) return NO; else{++s1;++s2;} return NO; }