• ベストアンサー

Scheme 中置式から後置式へ

cametan_42の回答

回答No.5

>>#4 >「演算子の優先順位をどう取り扱うか」について全く触れられていません. >#1 では「普通の式」を想定して「演算子順位文法」に触れたんだけど, そうでないならまたそれなりに考える必要があります. そう。実はそうなんですよね。 ですから、「Scheme習いたて、はじめたばかりの大学一年生」である以上、どこまでが出題意図なのかちょっと分かんなかった、ってのがあります。 つまり、本格的に「演算子順位文法」が必要なのか、それとも題材的にリストの要素をreverseと同様に「並べ替えろ」だけが出題意図なのか。 本当に「Scheme習いたて、はじめたばかりの大学一年生」なら、恐らくそこまで複雑な出題意図は無いだろう、と読みました。 まあ、Bの出題に関しても触れましたが、全体的に「穴がある」問題なのは間違い無いです。従って、Wikipediaの例も照らし合わせながらどうなんだ、とやってたわけです(笑)。 >「正確に 2個」です. そうでしょうね。Wikipedia見てても「そうならざるを得ないだろう」とは思いました。 と言うわけで、 >"局所手続き"というものがどのようなものなのか これは>>#4の方で書かれていた通りです。defineの中にdefine突っ込んだ形、ですね。 一応、どんな教科書使ってるのか不明だったんで、どう書こうかな、って悩んだんですが、大学で使われる由緒正しい教科書、SICPの表現例に合わせました。が、一般には局所関数、とかローカル関数、って言った方が通りが良いかもしれません。また、defineの中にdefineを突っ込んだ形はSICPの中でも比較的早く登場するんで、その形に準じました。 一般に、Lisp系言語では、プログラムの単位を「関数」と表現しますが、Schemeではどう言うわけか、正確には「手続き」(プロシージャ)と表現します。この二つは工学上の概念は若干違うんですが、一般には同じ、と考えてまあいいでしょう。出題でも「関数」と表現されていますね。 例えば#3のコードは次のように書いても全く同じように動作します。 (define (stackM m) (foo m '())) (define (foo m s) (cond [(empty? m) s] [(number? (first m)) (foo (rest m) (cons (first m) s))] [else (foo (rest m) (cons (eval (list (car m) (cadr s) (car s))) (cddr s)))])) これだと初心者的に「見慣れた形」でしょう。 ただし、#3との違いと言うのは、上記の形で書くと、手続きfooを直接呼び出せる事です。当たり前ですよね。 > (foo '(2 4 1 - *) '()) (6) > 一方、#3のスタイルで書くと、fooは直接には「呼び出せません」。これがdefineの内側にdefineをぶち込む効果で、文字通り手続きを「局所化」してるんです。つまり、局所手続き状態のfooは「手続きstackM内に"於いて"のみ有効な」手続きとなる。まさしく「ローカル」な手続きになる、んです。 defineの中にdefineぶち込むのが気持ち悪い場合は、代わりにこう言う風にも書けます。 (define (stackM m)  (letrec ((foo       (lambda (m s)        (cond         [(empty? m) s]         [(number? (first m))          (foo (rest m) (cons (first m) s))]         [else          (foo (rest m)           (cons (eval (list (car m) (cadr s) (car s))) (cddr s)))]))))   (foo m '()))) こう言う「letrec」と言う専用に局所関数を作り出すものもあります。 (既に習ってるかしら?)

tomotomo2309jp
質問者

お礼

ご回答ありがとうございます! 毎回詳しい回答を下さって本当に感謝です。 局所手続きについて、してくださった説明で理解できました。 そこで早速#5でいただいた定義式をDr.Schemeに打ち込んでRunを押してみたのですが、evalが未定義ですとのエラーが表示されました。 いま大学の図書館で「Structure and Interpretation of Computer Programs」をみてevalに関する記述を探してみたのですが、洋書な上、evalの定義式もかなり複雑なもので、理解できませんでした。。また、SICPではevalは二つの引数を要求するものでした。evalとはどのようなものなのでしょうか? もしかして使っている言語が悪いのかもしれないですが、どれを使えばいいのでしょうか?ちなみに今は「Advanced student」を使っています。

関連する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; }