1

再帰呼び出しの間、変数の値を静的に保ちたい。たとえば、fooがパラメーターとして受け取る関数の場合 、最初の呼び出しからのname値を変数に保存し、変数はすべての値を保持するfoo への再帰呼び出し。namefoo

def run_app (name, startr)
  if startr==1
    constant_var=name
  end

  some_name = modify name
  diff = compare some_name, constant_var

  # recursive call
  run_app some_name, 0
end

最初の呼び出しはrun_app "john", 1、呼び出し中にconstant_varの値を保持したいというようなものです。どうすればそれを達成できますか?

4

3 に答える 3

5

まず、コードに冗長性があります。diff割り当てられていますが、使用されていません。あなたはそれを取り除くことができます:

def run_app(name, startr)
  constant_var = name if startr == 1

  some_name = modify name
  compare(some_name, constant_var)

  # recursive call
  run_app(some_name, 0)
end

これを解決する標準的な方法は、その追加情報を渡すための追加パラメーターを追加することです。

def run_app(name, startr, constant_var)
  some_name = modify name
  compare(some_name, constant_var)

  # recursive call
  run_app(some_name, 0, constant_var)
end

次に、次のようにメソッドを呼び出す必要があります。

run_app(tmp = 'john', 1, tmp)

# or

run_app('john', 2, nil)

ただし、これにより大量の内部実装の詳細が呼び出し元に漏洩、呼び出し元に大きな負担がかかります。たとえば、最初と 3 番目の引数が同じオブジェクトである必要があることを知る必要があります。1ただし、2 番目の引数として渡された場合のみです。以外のものを渡す場合は、3 番目の引数として1渡す必要があります。nil

誰かが電話をかけないようにする方法

run_app('john', 1, 'ringo')

# or 

run_app(tmp = 'john', 2, tmp)

オプションのパラメータとデフォルトの引数を使用することで、これをわずかに改善できます。

def run_app(name, startr, constant_var = name if startr == 1)
  some_name = modify name
  compare(some_name, constant_var)

  # recursive call
  run_app(some_name, 0, constant_var)
end

これで、好きなように呼び出すことができます:

run_app('john', 1)

# or

run_app('john', 2)

ただし、次のように呼び出すこともできます

run_app('john', 1, 'ringo')

# or 

run_app(tmp = 'john', 2, tmp)

そこで、そのロジックをprivateヘルパー メソッドに移動し、パブリック メソッドに必要な API を提供します。

def run_app(name, startr)
  constant_var = name if startr == 1

  run_app_r(name, startr, constant_var)
end

private

def run_app_r(name, startr, constant_var)
  some_name = modify name
  compare(some_name, constant_var)

  # recursive call
  run_app_r(some_name, 0, constant_var)
end

次のように呼び出します。

run_app('john', 1)

# or

run_app('john', 2)

もちろん、今でも通話できます

run_app_r('john', 1, 'ringo')

# or 

run_app_r(tmp = 'john', 2, tmp)

しかし、少なくとも、YARD のタグを使用するか、RDoc のタグを使用してドキュメントから完全に除外するなど、明確に文書化できる別の方法があります。private@private:nodoc:

run_app_rメソッドが内部でのみ呼び出されることを意図しているにもかかわらず、どこからでもメソッドを呼び出すことができるという事実は、run_appかなり面倒です。ネストされたメソッドをサポートする Scala のような言語では、run_app_rメソッドをメソッド内に配置するだけですがrun_app、Ruby はネストされたメソッドをサポートしていないため、別の方法を見つける必要があります: Procs はメソッド内でネストできます!

def run_app(name, startr)
  constant_var = name if startr == 1

  (run_app_r = ->(name, startr, constant_var; some_name) {
    some_name = modify name
    compare(some_name, constant_var)

    # recursive call
    run_app_r.(some_name, 0, constant_var)
  }).(name, startr, constant_var)
end

次のように呼び出します。

run_app('john', 1)

# or

run_app('john', 2)

ブロックはクロージャであるため、明示的に渡す必要さえありませんconstant_var

def run_app(name, startr)
  constant_var = name if startr == 1

  (run_app_r = ->(name, startr; some_name) {
    some_name = modify name
    compare(some_name, constant_var)

    # recursive call
    run_app_r.(some_name, 0)
  }).(name, startr)
end

次のように呼び出します。

run_app('john', 1)

# or

run_app('john', 2)

ただし、再帰には基本ケースがなく、無限にループするため、これはすべて意味がありません。というか、Ruby は適切な末尾呼び出しを保証していないため、スタック オーバーフローが発生します。

于 2013-08-15T10:36:52.993 に答える