2

私はRubyが初めてで、プログラミング全般も初めてです。スタンドアロンの Ruby スクリプトに、yaml ファイルからデータを読み取り、そのデータをメソッドの変数に割り当てるコードがあります。これはすべてメソッドで行われます。メソッドの定義の外で、そのメソッドを呼び出して、割り当てられた変数の値を出力します。しかし、あー、メソッドで割り当てられた変数の値が nil です...なぜですか? これは、私が推測するオブジェクト指向プログラミングと関係があります。誰かが詳しく説明できますか?

以下はコードです。前もって感謝します。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

source_connection=nil

def load_configurations
    file_name = nil

    ARGV.each do|a|
      file_name = "#{a}"
    end
    dest_options = YAML.load_file(file_name)
    source_connection = dest_options['dest_name']
end

load_configurations()

puts source_connection

#####  returns nothing. why? #####
4

2 に答える 2

5

Ruby には、ほとんどの言語と同様に (少なくとも私が知っている限りでは、Javascript は例外かもしれません)、可視性スコープと呼ばれる概念があります。

Ruby には 4 つのスコープがあります。

  • グローバル スコープ
  • クラススコープ
  • メソッドのスコープ
  • ブロックスコープ

実際には、ex に対して定義されたローカル変数が意味することです。in method は、呼び出しスタックを明示的に up (メソッド/ブロック呼び出しパラメーターを使用) または down (return を使用) に渡さない限り、このメソッドでのみ表示されます。

あなたの場合、メソッドの外側でsource_connectionnil に割り当てますが、別のスコープで同じ var 名を参照するため、そこでのみ割り当てられます。これを解決する Ruby の方法は、インスタンス変数( @source_connection) を定義するか、この変数をメソッドに明示的に渡してから返すことです。

プロのヒント: Ruby では、デフォルトで最後の評価が返されるため、明示的に記述する必要はありませんreturn source_connection

編集:
クラス インスタンスとインスタンス変数を使用すると、状況がもう少し複雑になるため、これらのトピックを完全にレイアウトする Metaprogramming Ruby の本の方向性を示すだけでよいでしょう。

EDIT2:
私の書き直しの提案(少しスタイルを変更します-メソッド定義の場合、パラメーターがあるかどうかに関係なく、常に括弧を追加することをお勧めします。一方、呼び出しの場合、パラメーターがない場合または単一のパラメーターがある場合は省略できます-ただし、これは依存します個人的な好みで ;) インデントも 2 つのスペースに変更しました。これが最も一般的に使用されていると思います。

#!/usr/bin/env ruby

require 'pg'
require 'yaml'

def load_configurations()
  file_name = nil

  ARGV.each do|a|
    file_name = "#{a}"
  end
  dest_options = YAML.load_file(file_name)
  dest_options['dest_name'] # Ruby will return last evaluation
end

source_connection = load_configurations

puts source_connection # now it will print what you expect
于 2013-07-15T17:32:44.820 に答える
3

変数はメソッドのスコープで作成され、グローバル スコープで定義されている変数には設定されません。詳細については、これを読むとよいかもしれません: http://www.techotopia.com/index.php/Ruby_Variable_Scope

これを行うことができるはずです:

def load_configurations
  file_name = nil

  ARGV.each do |a| 
    file_name = "#{a}"
  end

  dest_options = YAML.load_file(file_name)
  dest_options['dest_name']
end

source_connection = load_configurations
puts source_connection
于 2013-07-15T17:31:28.100 に答える