私が見た例のほとんどは取るに足らないものであり、これが言語に何を追加するのかわかりません。Objective-C でコールバックを処理するためにブロックを使用する理由や、Javascript でタイマーのコールバックとして使用されるクロージャーを使用する理由はわかりますが、Ruby でブロックを使用する目的はわかりません。のような関数の代わりに使用できるものinject
ですか?
2 に答える
Ruby はいたるところでブロックを使用しており、これは言語の最もユビキタスな機能の 1 つです。これは基本的に、値としての関数の最適化されたケースです。JavaScript のような実際の関数オブジェクトは、Ruby ではProc
クラスのインスタンスです。ブロックはオブジェクトではないため、オブジェクトであることによって発生するオーバーヘッドの一部を回避できます。その理由は、ほとんどすべての場合、関数を引数として渡したい場合、渡すのは1つだけであり、その場で定義したいので、最適化して物事を少し構文的に良いですか?
これはブロックです:
[1, 2, 3].each do |i|
puts i
end
これは関数です:
func = Proc.new do |i|
puts i
end
[1, 2, 3].hypothetical_each(func)
Proc
機能値の定義でさえ、(コンストラクターへのパラメーターとして) ブロックを含むことがわかります。
通常inject
、 では関数ではなくブロックを使用します。Ruby のほぼすべてのループ構造で使用します (while
非常にまれにしか使用されません)。
ブロックを使用して、Sinatra のようなドメイン固有の言語を構築することもできます。
get 'index.html' do
"Hello World"
end
または Rspec:
describe "addition" do
it "should add two numbers together" do
(1+2).should equal(3)
end
end
ブロックがなければ Ruby を読み書きすることはできないため、ブロックをよく学びましょう。
ruby のブロックの秘密は、ruby のデザインの性質にあります。
Ruby は、メソッド呼び出しが「メッセージ」としてオブジェクトに送信され、戻り値が応答であるオブジェクト モーダルを使用して設計されています。ruby では (python や他のいくつかの言語とは異なり)、関数とメソッドはそれ自体はオブジェクトではありません。ブロックは、このモーダルで関数のようなメッセージを許可する Ruby の方法であり、Ruby が一般的に反復を処理する方法の鍵となります。
私が間違っている場合は誰かが私を修正してください。しかし、ブロックを作成したり、while ステートメントを使用したりせずに Ruby で反復を実行することは実際には不可能であり、実際、for i in object
表記法はオブジェクトeach
メソッドへのアクセスの単なる構文の省略形です。
すなわち。
for i in 1..5
#do stuff with i
end
以下とまったく同じように実行されます。
1..5.each do |i|
#do stuff with i
end
Range オブジェクト1..5
(ruby standard lib Enumerable モジュールを含む) がその要素を渡されたブロックに譲るruby VM によって
内部では、この操作は次のようになります (これは単純化されたバージョンであり、範囲の ... 排他的および .. 包括的バージョンを考慮していないことに注意してください)
class Range
def init(start, end)
@start = start
@end = end
end
def each
i = @start
while i < @end
yield i
i += 1
end
end
end
したがって、その for ループが呼び出されると、範囲オブジェクトが作成obj = Range.new(1,5)
され、オブジェクトにメッセージが送信さobj.send(:each, &block)
れ、各メソッド内で while ループが使用され、ブロックが生成されます。
TL;DR
Ruby はブロックを内部的に使用します。これは、ブロックが非常に設計にとって重要であるためです。ブロックがないと、言語自体がmessage => object => response
モーダルで機能しません。
したがって、「なぜブロックを使用する必要があるのですか?」と尋ねるべきではありません。それらなしでは Ruby プログラムを書くことはできないからです。
代わりに、「Ruby のブロックは、Objective-C や Javascript のブロックとどう違うのですか?」と尋ねてください。彼らは違うからです。
Objective-C について話すことはできませんが、JavaScript ではブロックはまさにオブジェクトです。これは、他のオブジェクトが必要なことを行うために取得して使用できるコードのコンテナーです。ブロックは、それを使用するオブジェクトに関連付ける必要さえありません。
ruby では、ブロックは、オブジェクトがメールで受け取り、それ自体で使用する一連の指示に似ています (メール担当者が次に来たときに、それをメール担当者に渡します)。