1

「上級生」の言語設定でラケットを使用していますが、関数を実行する関数を作成しようとして問題があり、n回実行して時間を報告します実行ごとに経過した。これは私が今までに得たものです。パラメータとして関数を渡しても予期せぬ結果が出る

(define (many n fn) 
    (cond 
    [(= n 0) true] 
    [else (many (sub1 n) (local ((define k (time fn))) k))])) 

私は数値の階乗を計算するfactという関数を持っています。

(define (fact n) 
    (cond 
    [(= 0 n) 1] 
    [else (* n (fact (- n 1)))])) 

私は(time (fact 10000))を評価した場合、私は、CPUのための合理的な結果、現実とGC時間だけでなく、大規模な数を取得します。すべての井戸と良い。私は(many 3 (fact 10000))を評価しようとすると、

はしかし、私が取得:

cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
true 

はなぜ関数は、パラメータとして渡されているにもかかわらずfactを評価されていませんか?

+0

あなたは関数を渡すのではなく、式の評価の結果を '()'の中に入れます。 –

答えて

5

manyは何を調べてみましょう。まず、あなたはそれを定義した:

(define (many n fn) 
    (cond 
    [(= n 0) true] 
    [else (many (sub1 n) 
       (local ((define k (time fn))) 
         k))])) 

そして、それを呼び出す:

> (many 3 (add1 41)) 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
#t 
> 

をここで再帰的にmany呼び出し自体たときに、すべての繰り返しで何が起こるか:many

(define (many 3 42) 
    (cond 
    [(= 3 0) true] 
    [else (many (sub1 3) 
       (local ((define k (time 42))) 
         42))])) 

(define (many 2 42) 
    (cond 
    [(= 2 0) true] 
    [else (many (sub1 2) 
       (local ((define k (time 42))) 
         42))])) 

(define (many 1 42) 
    (cond 
    [(= 1 0) true] 
    [else (many (sub1 1) 
       (local ((define k (time 42))) 
         42))])) 

(define (many 0 42) 
    (cond 
    [(= 0 0) true] 
    [else (many (sub1 0) 
       (local ((define k (time 42))) 
         42))])) 

あなたの定義は再帰的に自分自身を呼び出します最初の(time fn)アプリケーションの結果値ですが、正しくはありません。なぜなら、あなたのタイミング情報を収集したいからですプロシージャのアプリケーションではなく、値(この場合は(add1 41)の値)ではありません。

(define (many n fn) 
    (cond 
    [(= n 0) fn] 
    [else (many (sub1 n) 
       (local ((define k (time fn))) 
       k))])) 

を、あなたは以下を得るでしょう::ちょうどmanyのあなたの定義でfntrueを代用

> (many 3 (add1 41)) 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
cpu time: 0 real time: 0 gc time: 0 
42 
> 

あなたはすべての再帰呼び出しのfn42に等しいことがわかります。これは、多くのFP言語で評価のApplicative orderが使用され、の最初の呼び出しが発生する前に(add1 41)が評価されるために発生します。それは第二引数(fn)だとして

したがって、私たちはに機能を確保するためにlambdaを使用する必要がありますが(が我々の場合にはサンク)の多くに渡されます。

(define (many n fn) 
    (time (fn)) 
    (if (= n 0) 
     true 
     (many (sub1 n) fn))) 

出力例:

> (many 3 (lambda() (fact 10000))) 
cpu time: 2734 real time: 2828 gc time: 1922 
cpu time: 906 real time: 953 gc time: 171 
cpu time: 891 real time: 953 gc time: 204 
cpu time: 938 real time: 984 gc time: 251 
#t 
> 

あなたが(fn)上記参照として機能(lambda() (fact 10000)(サンク)の結果のアプリケーションを実行し、timeすでにスキームにおける機能アプリケーションは式周り()として表現される知っていますあなたが渡したいもの(式)を正確に取得し、正しいタイミング情報を表示します。

希望に役立ちます。私が間違っているなら私を訂正してください。

+0

+1かなりかわいい答え: – leppie

+0

@レッピー:ありがとう!私はFPが大好きです。私はその勉強を励ますのが正当だと思います。 –

+0

こんにちはYasirさん、お返事ありがとうございます。私は今より良く理解しているので、評価の順番が私を邪魔しているようです。ただし、「中級」および「上級」の生徒設定では、「if」機能はありません。私が原因を理解している間、私はまだこの問題を解決することができません。あなたの忍耐と時間をありがとう。 – Greenhorn

関連する問題