Rubyを初めて使用する場合は、初心者用手袋を着用してください。
次の2つのスニペットに違いはありますか(あいまいまたは実用的)?
my_array = [:uno, :dos, :tres]
my_array.each { |item|
puts item
}
my_array = [:uno, :dos, :tres]
my_array.each do |item|
puts item
end
ブレース構文を使用すると、ブロックを1行に配置できることがわかります
my_array.each { |item| puts item }
しかし、それ以外に、ある構文を他の構文よりも使用する説得力のある理由はありますか?
Ruby cookbook は、ブラケット構文の優先順位がdo..end
よりも高いことを示します
ブラケット構文はdo..end構文よりも優先順位が高いことに注意してください。次の2つのコードスニペットを検討してください。
1.upto 3 do |x|
puts x
end
1.upto 3 { |x| puts x }
# SyntaxError: compile error
2番目の例は、括弧が使用されている場合にのみ機能します。1.upto(3) { |x| puts x }
これは少し古い質問ですが、_{}
_と_do .. end
_についてもう少し説明したいと思います
前に言ったように
ブラケット構文の優先順位はdo..endより高い
しかし、これがどのように違いをもたらすか:
_method1 method2 do
puts "hi"
end
_
この場合、method1は_do..end
_のブロックで呼び出され、method2は引数としてmethod1に渡されます! method1(method2){ puts "hi" }
と同等です
しかし、あなたが言うなら
_method1 method2{
puts "hi"
}
_
method2がブロックで呼び出され、戻り値が引数としてmethod1に渡されます。 method1(method2 do puts "hi" end)
と同等です
_def method1(var)
puts "inside method1"
puts "method1 arg = #{var}"
if block_given?
puts "Block passed to method1"
yield "method1 block is running"
else
puts "No block passed to method1"
end
end
def method2
puts"inside method2"
if block_given?
puts "Block passed to method2"
return yield("method2 block is running")
else
puts "no block passed to method2"
return "method2 returned without block"
end
end
#### test ####
method1 method2 do
|x| puts x
end
method1 method2{
|x| puts x
}
_
####出力####
_#inside method2
#no block passed to method2
#inside method1
#method1 arg = method2 returned without block
#Block passed to method1
#method1 block is running
#inside method2
#Block passed to method2
#method2 block is running
#inside method1
#method1 arg =
#No block passed to method1
_
一般的に、慣例では、メソッド呼び出しや比較などの小さな操作を行うときに{}
を使用するので、これは完全に理にかなっています。
some_collection.each { |element| puts element }
ただし、複数行に渡るわずかに複雑なロジックがある場合は、次のようにdo .. end
を使用します。
1.upto(10) do |x|
add_some_num = x + Rand(10)
puts '*' * add_some_num
end
基本的には、ブロックロジックが複数の行に渡って同じ行に収まらない場合はdo .. end
を使用し、ブロックロジックがシンプルで単純/単一のコード行の場合は{}
。
Rubyのブロックに対してdo end
と{ }
を選択するための2つの一般的なスタイルがあります。
最初の非常に一般的なスタイルは、Ruby on Railsによって普及し、単一行と複数行の単純なルールに基づいています。
{ }
を使用しますdo end
を使用しますこれは、do/endが1ライナーでひどく読み取りますが、複数行ブロックの場合、閉じている}
を独自の行にハングさせたままにすることは、Rubyでend
を使用する他のすべてと矛盾するため、モジュール、クラスおよびメソッド定義(def
など)および制御構造(if
、while
、case
など)
あまり見られない2番目のスタイルは、セマンティック、または「 Weirich Braces 」として知られ、後期の偉大なルビイストJim Weirichによって提案されました。
do end
を使用します{ }
を使用しますこれは、ブロックがその戻り値で評価される場合、チェーン可能である必要があり、{}
ブレースがメソッドチェーンに適していることを意味します。 。
一方、ブロックがその副作用について評価される場合、戻り値は重要ではなく、ブロックは「実行中」です「何か、それで連鎖する意味がありません。
構文のこの区別は、ブロックの評価に関する視覚的な意味と、戻り値を考慮する必要があるかどうかを伝えます。
たとえば、ここではブロックの戻り値がすべてのアイテムに適用されます。
items.map { |i| i.upcase }
ただし、ここではブロックの戻り値を使用していません。手続き的に動作しており、doing副作用があります:
items.each do |item|
puts item
end
セマンティックスタイルのもう1つの利点は、ブロックに行が追加されたからといって、中かっこを実行/終了する必要がないことです。
観察として、偶然にもfunctionalブロックは1ライナーであり、proceduralブロック(例:config)は複数行です。したがって、Weirichスタイルに従うと、Railsスタイルとほぼ同じになります。
私は長年Weirichスタイルを使用していましたが、これから常にブレースを使用に移動しました。ブロックスタイルの情報を使用したことを覚えていないので、定義がちょっとあいまいです。例えば:
date = Timecop.freeze(1.year.ago) { format_date(Time.now) }
customer = Timecop.freeze(1.year.ago) { create(:customer) }
これらは性的または機能的ですか?
そして、私の意見では行数の問題は役に立たない。行が1行以上あるかどうか、そして行を追加または削除しただけでスタイルを変更する必要があるのはなぜですか?