2017-09-11 19 views
-1

MITのSICP講義に従っています。これは、アレキサンドリアの方法のHeronによる数の平方根近似を求めようとしたものです。これは初めてのことですが、lobを試してみました。エラー:(/)悪い引数タイプ:#<unspecified>チキンスキーム平方根近似

(define guess 1) 

(define (avg a b) 
    (/ (+ a b) 2)) 

(define (try guess x) 
    (if (goodEnough guess x) 
     guess 
     (improve guess x))) 

(define (improve guess x) 
    (define guess (avg guess (/ x guess))) 
    (try guess x) 
) 

(define (goodEnough guess x) 
    (= guess (avg guess (/ x guess)))) 

(print (try 1 25)) 

私はチキンスキームコンパイラを使用してこれを印刷しています。これが出力されます。

Error: (/) bad argument type: #<unspecified> 

    Call history: 

    1.a.SquareRootApproximation.scm:29: try 
    1.a.SquareRootApproximation.scm:17: goodEnough  
    1.a.SquareRootApproximation.scm:27: avg 
    1.a.SquareRootApproximation.scm:19: improve  <-- 

更新:私はより抽象化してlispのを使用してこの問題に向けて私のアプローチを変更した、まだ私は、この新しいエラーが意味することを望んでいるかを把握することはできません。すべての修正?ありがとう!

答えて

1

#<unspecified>は、他の言語では基本的に「無効」です。何らかの手続きに何も返されることがないときは常に、戻り値として使用されます(たとえば、printがこれを返します)。また、内部のdefineを処理する場合など、一時的なプレースホルダ値として使用される場合もあります。

通常、この一時的なプレースホルダは、言語のユーザーには表示されないようにしてください。ただし、言語の奇妙なケースが発生したようです(おめでとうございます! improveプロシージャ内の(define guess (avg guess (/ x guess)))が同時に変数を定義し、その変数を使用しているためにエラーが発生します。これを行う動作は明確ではなく、CHICKENが行っていること(Guile、Gauche、Gambit)ではいくつかのSchemeの実装が行われますが、MIT、Scheme48、Racketのような意味のエラーメッセージが表示されます。これが不適切である理由は、内部でdefineletrecに展開されているという事実と関係しています。これは、相互に再帰的なプロシージャを定義できるためですが、少し問題が生じます。例えば、(define a b) (define b a)の場合はどうなりますか?

あなたの意図は手順への入力として渡された古い推測変数を使用しているように見えるので、代わりにdefineを使用してのあなたはguessの新しい値をバインドするletを使用することができます(これはどのように振る舞うべきか、よく指定された場合)、またはnew-guessのように別の名前を使用してください。

+0

私はまだレッスンについて学んでいない、私はまだ最初の講義にあります。たぶん、新しい推測が正しい方法です。ありがとう。これは実際には新しい変数で機能しました。 –

+0

R5RS以前では 'lambda'(そして派生した形式)の' define'は、 'letrec'が本体の前でR6RSで評価され、後で' letrec * 'であることを許可していないので、すでに初期化された変数を評価することができます。もちろん、これらのどれも、同じ 'lambda'内の**任意の**ローカル' define'によってシャドウされる変数を評価することはできません。 'letrec'と' letrec * 'は再帰的な関数を作ることを許さなければならないため、バインディングはクロージャ作成時に存在する必要があります。 – Sylwester

+0

」フォームで直接「」の値を参照するのは「エラーです」という意味で明確に指定されています。しかし、これは基本的には「実装は自由であれば自由に行うことができます」という意味です。本質的には、Cの「未定義の動作」に似ています。「エラーです」という内容は仕様外にあり、そのようなエラーの原因となるプログラムは実行/コンパイルされない場合があります。私の例からわかるように、これは非常に実装依存です.MIT、Racket、Scheme48はCHICKEN、Guile、Gambit、Gaucheとはまったく違った動作をします。 – sjamaan