スキームの初期の短い回路を返し"?
-
19-09-2019 - |
質問
ようにしているのかいができる"早帰りでスキームの手続き なし トップレベルの if
または cond
のように施工性が向上します。
(define (win b)
(let* ((test (first (first b)))
(result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
(enumerate (length b)))))
(when (and (not (= test 0)) result) test))
0)
例えば、上記のコードのい win
を返す test
の場合 when
条件を満たし、それ以外は0を返す.しかし、その手続き 常に return0の結果にかかわらず、当 when
ます。
その理由を私は構造化マーコードでは、こでこの手順が必要な多くの複雑なチェック(複数のブロックと同様の let*
の例では、何もかも大きな cond
はかり不格好になる。
解決
ここでは、自分自身をreturn
構築するために呼び出し/ ccのを使用する方法である。
(define (example x)
(call/cc (lambda (return)
(when (< x 0) (return #f))
; more code, including possible more calls to return
0)))
いくつかの方式を使用すると、ラムダのノイズの一部をドロップすることができますLET / ccで呼ばれるマクロを定義します:
(define (example x)
(let/cc return
(when (< x 0) (return #f))
0))
あなたのスキームがない場合は、もちろん、/ CCを書くのは簡単ですしましょう。
<時間>の呼び出し/ ccのは、それが継続として呼び出された時点を節約するため、これは動作します。それは、その関数の引数にその継続を渡します。関数は、その継続を呼び出すと、スキームは、それがこれまでに築いていたものは何でも、コールスタック放棄し、呼び出し/ ccの呼び出しの終わりから続いています。機能は継続を呼び出すことはありません場合はもちろん、それだけで正常に返します。
あなたはその機能からそれらを返すか、あるいはグローバルなデータ構造に格納し、後でそれを呼び出しを開始するまで、継続は本当に心曲げ得ることはありません。そうでなければ、彼らは他の言語の構造化のgoto文(しばらく/ため/休憩/復帰/継続/例外/条件)のようにしている。
<時間>私はあなたの完全なコードがどのようなものかわかりませんが、指揮で行くことにし、別の関数に複雑なチェックを考慮した方がよいかもしれません。 return
とlet*
を必要とすることは、通常、過度に不可欠コードの症状です。しかし、呼び出し/ ccの方法は今のために働いて、あなたのコードを取得する必要があります。
他のヒント
一つの方法は、早期終了はさらに再帰的にしないことによって達成され、ループの代わりに再帰を使用することです。
この場合は、あなたがもし、いえないトップレベルをしたいときには、したくない。
(define (win b)
(let* ((test (first (first b)))
(result (every (lambda (i) (= (list-ref (list-ref b i) i) test))
(enumerate (length b)))))
(if (and (not (= test 0)) result)
test
0)))
それは常にゼロを返した理由は、かどうかを実行してしまった、その結果の身体が床に落下するだろうということです。あなたはラムダ定義関数内の暗黙のフォームが暗黙的に作成し、参照あまりにブロックを開始するので、
(define foo
(lambda (b)
(begin
(let ...)
0)))
と道作品を始めるには、床の上のすべての中間結果を滴下しながら、それは、内部の最後のフォームの結果を返すことです。これらの中間結果は、副作用を有することが意図されています。あなたは(!)偉大である、というのいずれかを使用していない、しかし、あなただけの関数定義内で(その結果、あなたが本当にしたい)一つの形態を持つように注意する必要があります。
Grem