24

これが Ruby で可能かどうかは完全にはわかりませんが、これを行う簡単な方法があることを願っています。変数を宣言し、後で変数の名前を調べたい。つまり、この単純なスニペットの場合:

foo = ["goo", "baz"]

配列の名前 (ここでは「foo」) を取得するにはどうすればよいですか? 実際に可能である場合、これは任意の変数 (スカラー、ハッシュなど) で機能しますか?

編集:これが私が基本的にやろうとしていることです。私は 3 つの重要な変数を持つクラスをラップする SOAP サーバーを作成しています。検証コードは基本的に次のとおりです。

  [foo, goo, bar].each { |param|
      if param.class != Array
        puts "param_name wasn't an Array. It was a/an #{param.class}"
        return "Error: param_name wasn't an Array"
      end
      }

私の質問は次のとおりです。「param_name」のインスタンスを foo、goo、または bar に置き換えることはできますか? これらのオブジェクトはすべて配列であるため、これまでに受け取った回答は機能していないようです (すべてを再設計することを除いて ala dbr's answer )

4

11 に答える 11

40

問題をひっくり返してみたら?変数から名前を取得しようとする代わりに、名前から変数を取得します。

["foo", "goo", "bar"].each { |param_name|
  param = eval(param_name)
  if param.class != Array
    puts "#{param_name} wasn't an Array. It was a/an #{param.class}"
    return "Error: #{param_name} wasn't an Array"
  end
  }

変数がまったく定義されていない可能性がある場合 (配列ではない場合とは対照的に)、「param = ...」行の最後に「rescue nil」を追加して、eval を保持する必要があります。例外をスローすることから...

于 2008-09-15T14:41:51.843 に答える
28

ソリューションを再構築する必要があります。できたとしても(できなくても)、その質問には合理的な答えがありません。

get_name メソッドを想像してみてください。

a = 1
get_name(a)

これが「a」を返すことに誰もが同意するでしょう。

b = a
get_name(b)

「b」、「a」、または両方を含む配列を返す必要がありますか?

[b,a].each do |arg|
  get_name(arg)
end

'arg'、'b'、または 'a' を返す必要がありますか?

def do_stuff( arg )
  get_name(arg)
do
do_stuff(b)

「arg」、「b」、または「a」、またはそれらすべての配列を返す必要がありますか? 配列が返されたとしても、順序はどうなりますか?結果を解釈する方法はどうすればわかりますか?

上記のすべての質問に対する答えは、「そのときの特定の物による」です。Ruby でその問題をどのように解決できるかわかりません。

于 2008-09-14T23:43:22.643 に答える
8

はるかに簡単な解決策がある問題を解決しようとしているようです..

データをハッシュに保存しないのはなぜですか? もしあなたがそうするなら..

data_container = {'foo' => ['goo', 'baz']}

..その場合、「foo」の名前を取得するのはまったく簡単です。

とはいえ、問題のコンテキストを提供していないため、これを実行できない理由がある可能性があります..

[編集]明確化した後、問題はわかりましたが、これは問題ではないと思います.. [foo, bar, bla] を使用すると、['content 1', 'content 2', 'etc']. 実際の変数名はまったく無関係です (というか、そうあるべきです)。変数の名前が重要な場合、それがまさにハッシュが存在する理由です。

問題は [foo, bar] などを繰り返し処理することではなく、SOAP サーバーがデータを返す方法、および/またはそれを使用しようとする方法に関する根本的な問題です。

解決策は、SOAPサーバーがハッシュを返すようにするか、常に3つの要素があることがわかっているので、次のようなことをしないことです..

{"foo" => foo, "goo" => goo, "bar"=>bar}.each do |param_name, param|
      if param.class != Array
        puts "#{param_name} wasn't an Array. It was a/an #{param.class}"
        puts "Error: #{param_name} wasn't an Array"
      end
end
于 2008-09-12T12:53:08.900 に答える
5

OK、インスタンスメソッドでも機能します。特定の要件(コメントに入れたもの)に基づいて、これを行うことができます:

local_variables.each do |var|
  puts var if (eval(var).class != Fixnum)
end

Fixnum特定の型チェックに置き換えるだけです。

于 2008-09-12T12:35:59.003 に答える
2

joshmsmooreに基づいて構築すると、このようなものでおそらくそれが可能になります。

# Returns the first instance variable whose value == x
# Returns nil if no name maps to the given value
def instance_variable_name_for(x)
  self.instance_variables.find do |var|
    x == self.instance_variable_get(var)
  end
end
于 2008-09-12T11:35:16.403 に答える
2

ありますがKernel::local_variables、これがメソッドのローカル変数で機能するかどうかはわかりません。また、達成したいことを実行できるように操作できるかどうかもわかりません。

于 2008-09-12T11:53:16.330 に答える
2

ローカル変数名を取得する方法がわかりません。ただし、instance_variablesメソッドを使用できます。これは、オブジェクト内のすべてのインスタンス変数名の配列を返します。

簡単な呼び出し:

object.instance_variables

また

self.instance_variables

すべてのインスタンス変数名の配列を取得します。

于 2008-09-12T08:17:38.330 に答える
1

Foo は、データへのポインターを保持する場所にすぎません。データは、それが何を指しているのかを知りません。Smalltalk システムでは、VM にオブジェクトへのすべてのポインターを要求できますが、それは foo 自体ではなく、foo 変数を含むオブジェクトのみを取得します。Ruby で vaiable を参照する実際の方法はありません。ある回答で述べたように、データがどこから来たのかなどを参照するタグをデータに配置することはできますが、一般的に、それはほとんどの問題に対する良いアプローチではありません。最初にハッシュを使用して値を受け取るか、ハッシュを使用してループに渡すことができるため、DBR の回答のように、検証目的で引数名を知ることができます。

于 2008-09-15T20:17:49.867 に答える
1

できません。最初からやり直して、ソリューションを再設計する必要があります。

于 2008-09-12T15:17:52.970 に答える
1

あなたの質問に対する本当の答えに最も近いのは、Enumerable メソッド each_with_index を each の代わりに使用することです。

my_array = [foo, baz, bar]
my_array.each_with_index do |item, index|
  if item.class != Array
    puts "#{my_array[index]} wasn't an Array. It was a/an #{item.class}"
  end
end

each/each_with_index に渡していたブロックから return ステートメントを削除しました。これは何もしない/意味がないためです。each と each_with_index はどちらも、操作対象の配列を返します。

ブロック内のスコープについても、ここで注目すべきことがあります。ブロック外で変数を定義した場合、ブロック内で使用できるようになります。つまり、ブロック内で直接 foo、bar、および baz を参照できます。逆は真ではありません。ブロック内で初めて作成した変数は、ブロック外では使用できません。

最後に、複数行のブロックには do/end 構文が好まれますが、これは単純にスタイルの問題ですが、最近のヴィンテージの ruby​​ コードでは普遍的です。

于 2008-09-15T23:22:59.750 に答える