Rubyのブロックとパラメータ渡しを説明する
I. ブロック宣言
ブロックは、関数呼び出しの後に {.} または do..end で囲んで宣言します。一般に、1行のステートメントには {} が使用され、複数行のステートメントには do..end が使用されます。
(1..4).each{|v| print "#{v} "} #output 1 2 3 4
ブロックは関数の引数とは異なり、引数を取ることができます。引数は || でくくられ、もちろん複数の引数を取ることができます。これらの引数をどのように定義するかは、実際には関数の内部で定義されるのですが、これについては後ほど説明します。
第二に、ブロック内の変数へのアクセス
ブロックの外側にある変数にブロックの内側からアクセスできる、つまりブロックの外側にある変数がブロックの内側で見えるということです、次のように。
sum = 0
(1..5).each do |v|
name = 'smile' #name is an in-block variable and can only be seen inside the block. Assume there are no variables with the same name outside the block.
sum += v #sum is visible inside the block
end
p sum #output 15, sum has changed.
p name #Error! name is not accessible.
ブロックの中の変数がブロックの外に出ることができるだけに、誤って望まない外部変数を変更してしまう可能性があります。幸いRuby 1.9以降では、ブロック引数の末尾に";"を付け、";"の後にブロック変数を指定することで安全に宣言する方法が提供されています。
name = 'outside'
sum = 0
(1..5).each do |v;name| #name after ";", multiple variables can be declared, separated by commas
name = 'inside' #name is an in-block variable and can only be seen inside the block. Assume that there are no variables with the same name outside the block.
sum += v #sum is accessible within the block
end
p sum #output 15, sum has changed.
p name #output outside, no change.
3、yieldステートメント
これを見ると、関数がどのようにブロックを呼び出しているのか、よくわからないかもしれません。では、ブロック呼び出しを紹介しましょう。キーとなるのはyieldステートメントです。関数本体の中でyieldを使うと、関数がその関数のブロックを呼び出すことになる。
def threeTime
yield
yield
yield
end
threeTime{p 'Hello world!}
出力は、3行のHello world! yield call blockであることはもう明らかでしょう。
ブロックの引数はどうなっているのでしょうか?もうお分かりだと思いますが、これはyieldの引数で、通常の関数と同様にyieldは引数を取ることができます。例を見てください。
def takeBlock(p1)
if block_given? # Determine if there is a block, if there is no block declared at yield, there will be an error, so it is better to make the determination here.
yield(p1) # pass p1 to the block argument, both the s in the block declaration below
else
p1
end
endie
takeBlock("no block") # output "no block"
takeBlock("no block") { |s| s.sub(/no /, '') } #output"block"
yieldはブロックにパラメータを渡すことができるので、今度はブロックがyieldに値を渡すことができるのでしょうか?答えはイエスです。ブロックの最後の文の値は自動的にyieldに渡されます。
def nTime
i = yield # The first time it is called, the value of the block is returned
(0..i).each {|v| yield(v)} # Here yield can also be placed in the block
end
nTime do |v|
print "#{v} " if v
9 # The number returned when the yield is called
end
#output 1 2 3 4 5 6 7 8 9
もちろん、上記の例はあくまで例であり、実際にそのように定義している人はいない。より良い定義は次のようになる。
def nTime(n)
(0..n).each {|v| yield(v)}
end
nTime(9) do |v|
print "#{v} "
end
Arrayでのfindの実装を見てみましょう。
class Array
def find
for i in 0... .size
value = self[i]
return value if yield(value)
end
return nil
end
end
[1, 3, 5, 7, 9].find {|v| v > 5 } # Implement find the first number greater than 5, output 7.
ブロックのおかげで、Rubyではfor文が少なく、コードがより人間らしく見え、コードを書くことがもはや退屈な作業ではなく、楽しいものになりました。
四、ブロックを渡すもう一つの方法
def fun #without arguments
yield
end
proc = ->{p 'haha'}
fun &proc
#####
def fun2(x) # with arguments
yield x
end
proc2 = ->(x){p x}
fun2 1,&proc2
V. instance_eval()とinstance_exec()
Rubyでは、Objec#instance_eval(), Objec#instance_exec()メソッドを使ってコードブロックを挿入し、オブジェクトのContext Probleを行って、オブジェクト内のコード断片を掘り下げて操作するという非常に素晴らしい機能が提供されます。この機能を使えば、オブジェクトの動作をテストしたり、オブジェクトの現在の状態を確認したりすることが簡単にできます。
class MyClass
def initialize
@v = 1;
end
end
obj = MyClass.new
obj.instance_eval do
puts self # => #<MyClass:0x007fbb2d0299b0>
puts @v # => 1
end
obj.instance_exec(5) { |x| puts x * @v } # => 5
関連
-
Rubyオブジェクト指向プログラミングにおけるクラスメソッドとクラスエクステンション
-
Windowsでrubyとrailsをインストールする際に発生する問題点まとめ
-
RubyのSimple FactoryパターンとFactory Methodパターンを利用する
-
Rubyのインストールと操作
-
Ruby on Railsのパフォーマンスを最適化するためのいくつかの方法についての考察
-
Ruby on Railsのルーティング設定に関するいくつかのアドバイス
-
Rubyのコードコメントを書く際に気をつけるべき事項
-
Rubyのバージョンを管理するためのrbenvの使い方
-
Rubyの基本構文
-
Rubyのクラスとモジュールの書き方のスタイルガイド
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
基本的なユーザー登録とログイン機能を実装するためのRuby on Railsチュートリアル
-
Ruby on Rails ラックミドルウェア基礎学習チュートリアル
-
Rubyのinstance_evalメソッドとclass_evalとの比較
-
Ruby on RailsでPing ++プラットフォームでの決済を実現
-
Rubyにおける数値型と定数の例
-
Rubyの基本的な環境変数の設定と一般的なインタープリタコマンド
-
Ruby on Railsのメーラーの使い方を説明します。
-
Ruby on Railsのインストールに関する簡潔で迅速なガイド
-
Rubyでの正規表現の使い方基本ガイド
-
Rubyのモジュールに関する基礎知識