2011-08-17 14 views
2

変数が配列かどうかをチェックし、それ以外の場合は処理を続行する前に変数に変換する必要があります。だから、私のコードは次のようになります。奇妙なRubyの振る舞い

class Test < Struct.new(:args) 
    def eval 
     p "1. #{args}" 
     args = (args.instance_of? Array) ? args : [args] 
     p "2. #{args}" # woah! [nil]? 
     # ...other things, with "args" being an array for sure..or not?!? 
    end 
end 

私はルビーするのは非常に新しいですので、おそらくこれは非常に慣用的ではありませんが、私には、このコードすべき少なくとも仕事のように見えます。代わりに、args変数を2回目に印刷すると、[nil]となります。

def eval 
    p "1. #{args}" 
    a = args 
    args = (a.instance_of? Array) ? a : [a] 
    p "2. #{args}" 
end 

すべてが期待著作物として:私は少し方法を変更した場合evalこと 注意してください。ですから、Structクラスに固有の何かがありますか?それとも、何か怪物がここで起こっていますか? (rvmを使って、macosx上のruby 1.9.3-devを使用)

答えて

2

実際には、あなたがやろうとしているRubyイディオムがあります:[*args]。あなたは、配列を渡される場合

http://raflabs.com/blogs/silence-is-foo/2010/08/07/ruby-idioms-what-is-the-splatunary-operator-useful-for/

、スプラットはあなたが単一の引数を渡すと、それが一つになるだろう、新しいものへの配列を「フラット化」します:このコンテキストで*はスプラット演算子と呼ばれています要素配列。

奇妙な振る舞いについては、割り当てのLHS上にあるnilに初期化されるevalメソッドでローカル変数argsを作成するように見えます。 argsは配列ではないので、現在の値の配列を作成します。これはまだnilです。 argsがインスタンス変数(@args)になると、予想どおりに動作します。つまり、Structを継承すると、argsargs=のメソッドが返されますが、@argsというインスタンス変数はありません。

+0

ありがとう、私はスプラット演算子を試してみます。とにかく、何が起こっているのかまだ分かりません。 'args'変数は、問題なく印刷できるので、すでにインスタンス化されています。ローカル変数(作業コードの' a')に再割り当てできます。 。また、トップレベルの関数で同じコードを使用しようとしましたが、期待どおりに動作します。私の疑いは、 "args"は、私が期待していない何かを行うアクセサメソッドとして定義されていることです:) – cheng81

+0

はい、 'args'はアクセサーメソッドです(私の記事の最後の文で言及されているように)。 1.#{args} "'の内部で動作します。しかし、次の行ではローカル変数を定義し、Rubyがbarewordsを解決しようとすると、メソッド呼び出しとしてではなくローカル変数としてそれらを解決しようとします。 –

+0

うん、私は変数のように見えるアクセサメソッドで混乱している。つまり、一度定義されると、構造体のプロパティは変更不可能です。とにかく、私はコンストラクタをオーバーロードして単純に 'super([* args]) 'を呼び出すことで解決したと思います。照明スピードの答え、btwありがとう:) – cheng81