2

[解決済み]

、、、の4つの関数に似たものbaseinitありfuncますsome。はfunc再帰的であり、それ自体を呼び出します。「停止の場合」では、呼び出しsomeてその値を返し、次に制御を「init」に戻し、そこから呼び出されます。後者はかつてから呼び出されましbaseた。

base
  -> init
       -> func
            -> init
                 -> func
                      -> some
                    |
           _________+
          |
          v
          ; should continue from here (in `func`)

[もう違います]

代わりに、への最初の呼び出しの後、someコントロールはに直接渡され、中間ペアの呼び出しbaseであると予想されるものをスキップします。(init,func)

私は実際に、、および再帰(たとえば、「相互末尾再帰」)を使用していくつかのより単純なケースを試しましblockreturnfactorial、すべてうまくいきました。私はそれがヘルパー関数をfunc使用していることを述べています(しかし、私はの例でさえ試しました、そしてそれは大丈夫でした); 私の実際のプログラムが問題を引き起こしている可能性があるものは何でもそうです。testcatchthrow(catch 'test (throw 'test 0))

これはelisp:それぞれがdefunで始まり、次のようにblockすべての関数がを使用returnします。

defun[" / block"から" "に切り替えましたdefun*]

(defmacro 4+ (number)
  "Add 4 to NUMBER, where NUMBER is a number."
  (list 'setq number (list '1+ (list '1+ (list '1+ (list '1+ number))))))

(defmacro 4- (number)
  "Subtract 4 from NUMBER, where NUMBER is a number."
  (list 'setq number (list '1- (list '1- (list '1- (list '1- number))))))

(defun mesg (s &optional o)
  "Use ATAB to tabulate message S at 4-multiple column; next/prev tab if O=1/0."
  (when (null o) (setq o 0))
  (case o (0 (4- atab)) (1 nil))
  (message (concat "%" (format "%d" (+ atab (length s))) "s") s)
  (case o (0 nil) (1 (4+ atab))))

(defun* base ()
  (let (pack)
    (setq atab 0)
    (mesg "base->" 1)
    (setq pack (init))
    (mesg "<-base")))

(defun* init ()
  (mesg "init->" 1)
  (return-from init (progn (setq temp (func)) (mesg "<-init") temp)))

(defun* func (&optional pack)
  (mesg "func->" 1)
  (when (not (null pack)) (return-from func (progn (mesg "<+func") pack)))
  (when (< 0 (mod (random) 2)); stop case
    (return-from func (progn (setq temp (some)) (mesg "<-func") temp)))
  (setq pack (init))
  (case (mod (random) 2)
    (0 (return-from func (progn (mesg "<0func") pack)))
    (1 (return-from func (progn (setq temp (func pack)) (mesg "<1func") temp))) ; use tail-recursion instead of `while'
    (t (error "foo bar"))))

(defun* some ()
  (mesg "some->" 1)
  (return-from some (progn (mesg "<-some") (list 2 3 4))))

(base)

pack変数は私の値です-listデータ構造として。また、 「命令型」funcを回避するために、特別な累積パラメーターを使用して(末尾再帰呼び出しで)自分自身を繰り返すために使用します。 while

だから私が期待するものの代わりに(それぞれ>はによってペアになってい<ます)

base->
    init->
        func->
            init->
                func->
                    some->
                    <-some
                <-func
            <-init
            func-> ; tail-recursion
            <+func
        <1func
    <-init
<-base

私のプログラムは次のように動作します。

base
  -> init
       -> func
            -> init
                 -> func
                      -> some
                           |
 __________________________+
|
v
; control yielded here (to `base`)

[もう違います]

制御がプログラムの開始に戻るのが早すぎfuncて、2回目returnの呼び出しからの最初の呼び出しで続行されないのはinitなぜですか?

助けに感謝します、

セバスチャン

4

2 に答える 2

1

あなたのコードを見ると、のブロックの範囲が何であるかは私にはわかりませんfunc。ブロックに定義全体が含まれている場合、funcはい、コントロールはfunc戻るときに到達しますが、ブロックは完全にスキップされるため、関数は完全に機能し、呼び出された場所(最終的にはbase)に戻ります。そうかもしれませんか?

その場合は、ブロックの後に戻った後に実行するコードを配置する必要があります。

編集:あなたのコードをもう一度見てください、私はあなたがreturnそれが使われるべきであるようにあなたが使っていないと思います。たとえば、initあなたは

(block nil
 ...

 (return (func ...)))

これはブロックを「キャンセル」し、「 」で呼び出された関数に。がない場合returnを除いて、ブロックがまったくない場合と同じ効果があります。したがって、ここでは、の可能なリターンポイントをキャンセルします。...return blockreturnfunc

于 2012-12-17T20:40:00.977 に答える
0

両方の回答に感謝します。説明のために追加したコードと同じように試したメッセージをプログラムに挿入すると、にdefun*問題がないことが明らかになりましelispたが、設計を間違えたことがいくつかあります。

于 2012-12-20T13:58:48.100 に答える