2017-02-17 4 views
0
irb(main):001:0> def some_method 
irb(main):002:1> begin 
irb(main):003:2*  xyz = 5 
irb(main):004:2>  zyx = 6 
irb(main):005:2> end 
irb(main):006:1> puts xyz 
irb(main):007:1> puts zyx 
irb(main):008:1> end 
=> :some_method 
irb(main):009:0> 
irb(main):010:0* some_method 
5 
6 
=> nil 

この単純な例では、begin/end 'ブロック'(実際には式)は、begin/endの外側からアクセス可能な2つの変数(xyzとzyx)を作成します。もちろん、開始/終了は式です。Ruby:メソッドのコンテキストでコードを実行する

私がやりたいことは何とかbegin/endを変換してbegin/endでコードを分解し、別の場所に置くことができますが、some_methodで変数を作成することができます。私はこれを行うには範囲を平坦化する必要があると思うが、私はそれを行う方法を把握することはできません。

def some_method 
    create_variables_here 
    puts xyz 
    puts zyx 
end 

define_method :create_variables_here do 
    xyz=5 
    zyx=6 
end 

質問:私は私のような何かをしたいと思います

  1. は、私は可能な限り何をしたいですか?私はバインディングを使って調査しましたが、うまくいかないようです。少なくとも私のためではない。
  2. Rubyコードの特定の場所に字句を入れるためにC#のようなことをすることはできますか?私は考えていない負荷またはがそれを行うことができますが必要です。
+0

いいえ、私はそれができるとは思わない(ローカル変数で) –

+1

私の頭の上から離れて、あなたがすることができる最高のものは、代入変数です。 'xyz、zyx = create_variables'です。もっと読みやすいコードにもなります:) –

+1

ユースケースは何ですか?私はあなたのxyz、zyx値を返すメソッドを作成するだけではどうですか?あなたが望む方法は、私が知る限りグローバル変数でのみ動作します。 – haffla

答えて

0

あなたはそうしたくありません。あなたが求めているのは、副作用です。戻り値以外の処理を行い、独自のオブジェクトやパラメータを変更する関数です。さらに悪いことに、それは発信者に直接影響します。副作用は、保守可能なコードの欠点です。カプセル化を中断し、すべての関数呼び出しを慎重に検討し、その副作用を考慮する必要があります。

これは、値を戻してこれを変数に割り当てることで、より適切に解決されます。 Ruby even supports returning multiple valuesであるため、2つの値の配列ではなく2つの値として返すことができます。

def create_variables_here 
    xyz=5 
    zyx=6 

    return xyz, zyx 
end 

def some_method 
    xyz, zyx = create_variables_here 
    puts xyz 
    puts zyx 
end 

戻り値が通常関連しているので、あなたはこれだけを見ていない、と彼らは関連している場合、彼らはおそらく、単一のオブジェクトとして返されなければなりません。彼らが関連していない場合、これは機能があまりにも多くのことをしていることを示す良い指標かもしれません。

これは、必要なものすべてを実行し、呼び出し元が変数の名前を決定できるようにします。それは重要です。なぜなら、A)は呼び出し側が覚えておくことが少ないからです。B)関数内の変数との競合を避けます。C)変数がどこから来たのかを明示します。


逆の例として、これがあったとします。 xyzzyxから来たの

def some_method 
    do_this 
    do_that 
    do_some_other_thing 

    puts xyz 
    puts zyx 
end 

... ?!通常、答えは簡単です:彼らは初期化されていません。しかし、提案された機能では、読者はxyzzyxに設定されていた可能性のある副作用について、それぞれのdo_blah関数呼び出しを慎重に調べなければなりません。

(ただし、副作用変数を使用する関数はcreate_vars_for_blahのような名前にする必要があります)はい、そうすべきですが、それは信頼できません。誰もが信じるよりも、最初は慎重にそれを使用します。)

さらに悪い場合はどうすればすべてxyzzyxを異なる値に設定しますか?今あなたは葛藤しています。

def some_method 
    do_this 
    this_xyz = xyz 
    this_zyx = zyx 

    do_that 
    that_xyz = xyz 
    that_zyx = zyx 

    do_some_other_thing 
    some_other_xyz = xyz 
    some_other_zyx = zyx 

    ... 
end 

アイデアは、ローカル変数を壊していると別の問題:呼び出し側はこの競合を見つけ、など回旋何かを持っています。ローカル変数の最も重要な側面の1つは、それに影響を与えるすべてのコードを一目で見ることができることです。例えば。

def some_method 
    xyz = 10 
    zyx = 20 

    do_this 
    do_that 
    do_some_other_thing 

    puts xyz 
    puts zyx 
end 

通常のRubyでは、10と20を印刷するという事実を知っています。この提案された機能では、誰が何をするのか分かりますか?

あなたが求めているのは、関数の最後に消えるグローバル変数です。

+0

私はあなたのすべての応答に感謝します。 はい、あなたはかなり正しいですが、この特定のケースでは副作用以外は何もしたくありません。 – RalphShnelvar

+0

私はあなたのすべての応答に感謝します。 はい、あなたはかなり正しいですが、この特定のケースでは副作用以外は何もしたくありません。 ある意味では、私がやりたいことはできないことを知っておくと良いです。もう一つは、それは私をイライラさせます。 @hafflaは、私が念頭に置いているユースケースを尋ねました。 私のコードでは、コントローラの後にコントローラに一定のパターンがあります。パラメータを検証し、検証中に同時に他のデータ構造を構築します。コードを複製することはできますが、もちろん、コードはDRYではありません。 – RalphShnelvar

+0

@RalphShnelvar問題があり、別の関数の途中にコードを挿入して解決しようとすると、今は2つの問題があります。代わりに、おそらくその機能を再構築する必要があります。 – Schwern

関連する問題