2009-06-30 7 views
17

Rubyの新機能ですが、非常に直感的な言語であることがわかりましたが、暗黙の戻り値がどのように動作するかを理解するのが難しいです。Rubyの暗黙の戻り値

私は、Tomcatのログをgrepし、該当するデータからパイプ区切りのCSVファイルを生成するための小さなプログラムを作成しています。ここでは、ログエントリから行を生成するために使用している簡単な例を示します。

class LineMatcher 
    class << self 
    def match(line, regex) 
     output = "" 
     line.scan(regex).each do |matched| 
     output << matched.join("|") << "\n" 
     end 
     return output 
    end   
    end 
end 


puts LineMatcher.match("00:00:13,207 06/18 INFO stateLogger - TerminationRequest[[email protected][accountNumber=0951714636005,srNumber=20]", 
         /^(\d{2}:\d{2}:\d{2},\d{3}).*?(\d{2}\/\d{2}).*?\[accountNumber=(\d*?),srNumber=(\d*?)\]/) 

このコードを実行すると、出力の値を明示的に返すときに期待される以下のコードが返されます。

00:00:13,207|06/18|0951714636005|20 

しかし、私は次のようにLineMatcher変更し、明示的に出力を返さない場合:

class LineMatcher 
     class << self 
     def match(line, regex) 
      output = "" 
      line.scan(regex).each do |matched| 
      output << matched.join("|") << "\n" 
      end 
     end   
     end 
    end 

その後、私は次のような結果を得る:

明らか
00:00:13,207 
06/18 
0951714636005 
20 

を、これではありません希望の結果私は出力変数を取り除くことができるはずですが、戻り値がどこから来ているのかは不明です。また、読みやすさのための他の提案/改善も歓迎します。

+0

修正された書式 – csamuel

答えて

23

はルビー内の任意のステートメントは最後に評価式の値を返します(この場合は)より読みやすく明示的なリターンであなたの方法を見つける...私よりも優れて説明することができます。 プログラムがどのように動作するかを正確に知るために、最もよく使用されているメソッドの実装と動作を知る必要があります。

#eachは、反復したコレクションを返します。つまり、次のコードはline.scan(regexp)の値を返します。

line.scan(regex).each do |matched| 
    output << matched.join("|") << "\n" 
end 

あなたが実行した結果を返したい場合は、eachとして動作しますが、変更のコレクションを返しますmapを、使用することができます。

class LineMatcher 
    class << self 
    def match(line, regex) 
     line.scan(regex).map do |matched| 
     matched.join("|") 
     end.join("\n") # remember the final join 
    end   
    end 
end 

非常に具体的な場合に応じて、いくつかの便利な方法があります。この場合、scanによって返される結果の数が多い場合を除いて、injectを使用することをお勧めします(1つの文字列を処理するよりも効率的に配列を処理します)。

class LineMatcher 
    class << self 
    def match(line, regex) 
     line.scan(regex).inject("") do |output, matched| 
     output << matched.join("|") << "\n" 
     end 
    end   
    end 
end 
+2

フィードバックをいただきありがとうございます...私は実際に何が実際に最後の声明として解釈されるのかを知ることは難しいという事実から私の混乱が生じたと思います。 – csamuel

13

ruby​​では、メソッドの戻り値は最後の文から返された値です。明示的なリターンを持つこともできます。

例では、最初のスニペットが文字列outputを返します。しかし、2番目のスニペットはeachメソッド(これは最後のstmtになります)によって返された値を返します。これは一致の配列になります。

irb(main):014:0> "StackOverflow Meta".scan(/[aeiou]\w/).each do |match| 
irb(main):015:1* s << match 
irb(main):016:1> end 
=> ["ac", "er", "ow", "et"] 

更新:ただし、それでも出力は1行で説明できません。私はそれがフォーマットエラーだと思う、それはどのようには配列を印刷するので、それは異なる行のそれぞれの一致を印刷する必要があります。少しのコードでは、

irb(main):003:0> one_to_three = (1..3).to_a 
=> [1, 2, 3] 
irb(main):004:0> puts one_to_three 
1 
2 
3 
=> nil 

は個人的に私は

+1

申し訳ありません、はい、書式設定エラーがありました。質問で訂正されました。 – csamuel

関連する問題