• ベストアンサー

Rubyのブロックについて

こんにちは、いつもお世話になってます。 本を読んでいくうちに、メソッドの引数の最後に&をつけたものとyieldを書いたものの違いがほとんどないように思えました。 この違いを考えてみたらyieldは引数が持てることくらいしか思いつかないのですがそう考えていいですか? そもそも基本から両者を間違って理解していたら申し訳ございません。

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4859/10275)
回答No.2

#1の人の補足修正ですが、yieldを使うときに、ブロックがあるか無いかは、 if block_given? __yield(1) end で判断します。 一番大きいのは、&で受け取ると、手続きオブジェクトとしてハンドリングできるので、別のメソッドに渡せることです。 def a(&p) __puts "call a" __b(&p) end def b(&p) __puts "call b" __p.call("call here") end a { |x| puts "proc "+x } 引数ももちろん渡せますので、機能的にはyieldのメリットがないので廃止の案もあったようです(速度面のメリットはあり)。

cevid_cpp
質問者

お礼

なるほど、単純にcallの後に引数を付ければ良かったのですね。 本のほうではyieldの説明のほうが詳しく書いてあったような気がしたんですが。。 廃止案もあったなんてびっくりです。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • lingring
  • ベストアンサー率50% (1/2)
回答No.1

違いは少なくとも3つあるようです。 1. ブロック無しで使われたときに、&をつけた引数にはnilが代入されます。 def hoge &block if block then 'A' else 'B' end end hoge #==> 'B' 一方、yield では、エラーがおきます。 def hoge if yield then 'A' else 'B' end end hoge # ==> LocalJumpError: no block given 2. 実行時速度がyieldを使ったときの方が&を使ったときよりも速いようです。 3. &を使ったときは、callメソッドを呼ばなければいけません。 def hoge &block block.call(1) end hoge {|i|+2} #==> 3 一方、yieldはそのまま使えます。 def hoge yield(1) end hoge {|i|+2} #==> 3 まとめると、ブロックを随意的にしたいときや、ブロック引数をとることをメソッド定義の1行目で明示したいときは&を使い、そうでなく、速さにこだわりたいときはyieldを使うべきのようです。

cevid_cpp
質問者

お礼

ありがとうございます。 ブロックは難しくて自分で実装できるようになるまでは時間がかかりそうですが頑張ろうと思います。 ふと疑問なんですがなんで関数名とかよくfooとかhogeを使うんでしょうか? 本見るたびに疑問に思ってました

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • Ruby 自作メソッドのブロック付きメソッドについ

    いつも、ご教授ありがとうございます。 Ruby でメソッドを自作してそのメソッドにブロックを持たせる場合 ブロック内で返り値を返すためにはどうしたらいいのでしょうか? たとえば以下のような自作メソッドがあるとすると def blocktest(str) if (block_given?) yield str else print "メソッドにブロックが与えられていない"; end end begin #自作したメソッドにブロックを与えた場合 res = blocktest("ブロック付きメソッドのテスト") {|value| print value; print "<br/>" print "メソッドに与えられた引数をprintしています" return "ブロックで返り値" } print res; print "<hr />" #ブロックを与えない場合 blocktest("ブロック付きメソッドのテスト"); rescue => ex print ex.message end 上記のようにブロック内で返り値 を指定して変数resのその返り値を返したい場合 どうしたらいいのでしょうか? 一応、ブロック内でreturnで値を与えてはいますが、例外が発生します。 よろしくお願いしまう。

    • ベストアンサー
    • Ruby
  • 【ruby】無名関数?でブロック付きメソッドって作れませんか?

    Proc.new do|arg|  arg.each do |x|   puts x  end end.call([1,2,3,4,5]) 上記のようなものを無名関数と理解しているのですが、 これを下記の様にすると、 Proc.new {|arg|  arg.each do |x|   yield(x)  end }.call([1,2,3,4,5]) do |x|  puts x end no block given とエラーになってしまいます。 無名関数で、ブロック付きメソッドって作れないものでしょうか? ご指導の程、宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • ブロックつきメソッドやyield文の用途について

    こんにちは。 漠然とした質問なのですがご教示ください。 プログラミング初心者で、 現在、「楽しいRuby」と「プログラミング言語Ruby」を読みながら 勉強をしています。 そのなかで「ブロックつきメソッド」や「yield文」の用途についての 疑問が出てきました。 疑問というのは、  「わざわざ、『ブロックを引数として自作メソッドに与える』  ことの利点ってなに?」 ..です。 私としては、  自作メソッドを呼び出した後、その中のyield文で  再度メソッドの外(自作メソッドの呼び出し元)に制御を戻すんだったら、  自作メソッドの中にブロック処理の内容を書いておくか、  または、最初から自作メソッドを呼ばずにブロック処理をするほうが、  処理の流れがわかりやすくてよいのでは??? ..と感じています。 大規模なプログラムを複数の人で作るような場合にはこのようなしくみが あったほうが便利.. ということなんでしょうか? ちなみに私は主に テキストファイルの編集や比較、結合..などの目的で Rubyプログラムを作っていて、規模はせいぜい100~200行くらいです。 他のRubyプログラムとの連携もありません。 「そんな使い方なら、利点はないよ」というご回答でも構いません。 具体例などと併せてご教示ください。 よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • Rubyのイテレータ

    Rubyのイテレータで分からないところがあります。以下のコードです。 if文のところで「yield x」が真なら「return x」を実行すると 推測できるのですが、 その実行結果はこれです。 > irb> a = [1, 2, 3, 4, 5] > => [1, 2, 3, 4, 5] > irb> find(a) {|x| x % 2 == 0} > => 2 > irb> position(a) {|x| x % 2 == 0} > => 1 > irb> count(a) {|x| x % 2 == 0} > => 2 例えば、find関数なら引数は「x」ですが「x % 2 == 0」 と条件式をブロックに書いているのが分かりません。 全体の流れとしてはfind関数なら2で割り切れたのが「2」と「4」で2つあるので 関数の結果は「2」というのは理解できます。 しかし、具体的に「return x」「 if yield x」が何をしているのかが分かりませんでした。 if「もし」yield x「なら」return xを実行する、様なコードなのですが・・・。 またfind(a)なら、引数xが2で割り切れるのなら条件式は「真」なので 真の数字をカウントする、様なコードなのですが・・・。それ以上詳細に教えてくれると助かります。 何方かご存知でしたら教えてください。 > リスト 1 : データの探索 (イテレータ版) > > # ブロックが真となる要素を探す > def find(ary) > for x in ary > return x if yield x > end > false > end > > # ブロックが真となる要素の位置を返す > def position(ary) > for x in 0...ary.size > return x if yield ary[x] > end > false > end > > # ブロックが真となる要素の個数を求める > def count(ary) > c = 0 > for x in ary > c += 1 if yield x > end > c > end なおこのコードが載っているサイトはここです。 http://www.geocities.jp/m_hiroi/light/abcruby08.html

    • ベストアンサー
    • Ruby
  • 【ruby】【文法?】ブロックをbreakした時。。

    質問を見ていただいて有難うございます。 質問を一言で言うと、 「メソッドの中で呼び出し元がbreakを使った事を検知できるか?」 となるのでしょうか。。。以下に詳しく質問を記述いたします。 引数に配列を渡すと、その配列をブロックに一つずつ返してくれる メソッドhoge()があるとします。 以下の様に使います。 ------------------------------------- hoge([0,1,2]) do |x|  puts x end 実行結果 0 1 2 ------------------------------------- このhoge()は、実行中にエラーが発生した場合、トラップして falseを返す事とします。(何事もなければtrueを返します。) このhoge()を以下の様に書きました。 def hoge(arg)  begin   arg.each do |x|    yield x   end  rescue   false  else   true  end end 以下の様に使います。 ------------------------------------- ret=hoge([0,1,2]) do |x|  puts x end puts ret ? 'success' : 'fail' 実行結果 0 1 2 success ------------------------------------- ------------------------------------- ret=hoge(nil) do |x|  puts x end puts ret ? 'success' : 'fail' 実行結果 fail ------------------------------------- ここまでは、よかったのですが、hoge()のブロックの中で、breakを使うと hoge()の戻り値はnilになってしまいます。 ------------------------------------- ret=hoge([0,1,2]) do |x|  break if x==1  puts x end puts ret puts ret ? 'success' : 'fail' 実行結果 0 nil fail ------------------------------------- ここで質問です。 最後の例は、hoge()として異常系ではないので、retにtrueを与えたいのですが、どうしたらよいでしょうか? ご指導のほど、宜しくお願いいたします。

    • ベストアンサー
    • Ruby
  • Ruby 文法 ブロックの中で自クラスの定数を呼ぶ

    以前した質問(http://okwave.jp/qa/q8484921.html)と非常に似てる質問になります。 以前の質問ではブロックの中で、そのクラスのメソッドを呼ぶ時のことでしたが、今回はメソッドではなく、定数にアクセスする時の質問です。 class Hoge VAL=1 def piyo yield end end h=Hoge.new h.piyo do |this| puts Hoge::VAL #<ーココの話 end 上の様に書く時、ブロックの中で、そのクラスの中の定数を参照するとき、上の例だと Hoge::VAL と書いてますが、Hoge::と書くのがとても嫌なので、以下の様に書いてみました。 class Hoge VAL=1 def piyo yield self end def retVal VAL end end h=Hoge.new h.piyo do |this| puts this.retVal #<-Hoge::VALと書かなくてよくなった。 end が、しかし実はVALなどの定数は多数あり、その数の分だけ値を返すメソッドを書くなんて、もっと嫌です。 なんか良い書き方はあるのでしょうか? 以下、蛇足なのですが、そもそもクラスの中でしかアクセスしないマジックナンバー的な定数の定義の仕方が間違っているのでしょうか? moduleに定義して、クラスの中とブロック使うところでincludeするなどの方がスッキリするのかも。。

    • ベストアンサー
    • Ruby
  • Rubyの引数が理解できません。(初心者です)

    プログラミング言語を覚えたいと考え、諸々の事情からRubyを独学したいとおもっております。 先日、「14歳からはじめるRuby…」という本を購入し、早速勉強を始めたのですが、引数でいきなり躓いてしまいました。 以下のような例文がありましたが、原理(理屈?)が理解できません。ご教唆お願いします。 001 def syomei s 002  puts "" 003  puts "============" 004  puts "" + s 005  puts "============" 006 end 007 puts "What's your name?" 008 name = gets.chomp 009 puts "Hello," + name + "!" 010 syomei name なぜ、これでメソッドの中へ変数が引き渡されるのかが理解できません。 「008 name」で初めて出てくるnameと引数"s"が何故イコールになるのでしょうか? 例えば(全くのデタラメですが)、「010 syomei name.s」であったり「010 syomei name = s」などのように定義付けされているのであれば、納得できるのですが…。 初歩中の初歩なのはわかっているのですが、理屈を理解したいと思ってます。よろしくお願いします。

  • 初歩的な質問です・・・

    最近javaの本を買って勉強しているのですが、最初で躓き、理解できないことろがたくさんあります。 ・インスタンスを作る ・コンストラクタを定義する ・メソッド ・引数 ・voidの使い方(public void ,void ~~ そもそもvoid自体の意味が・・・) ・クラスの継承 APIというのを見てもプログラミング初心者の私には説明が難しくて理解できません・・・。 なにかに例えて教えていただければうれしいです(^^) よろしくお願いします!

    • ベストアンサー
    • Java
  • Rubyのシンボルについて教えてください

    Rubyのシンボルについて教えてください Rubyのあるライブラリに付随していたサンプルソースを見ており、シンボルが使われているのですがよく理解できません。以下サンプルソースの一部です。 1 def initialize(parent, display_frame, initial_date, calendar_flags) 2 super( parent, 3 :date => initial_date, 4 :style => calendar_flags | RAISED_BORDER) 5 6 @display = display_frame 7 @date = initial_date 8 @weekday_names = %w|Sun Mon Tue Wed Thu Fri Sat| 8 9 evt_calendar self, :on_calendar 10 evt_calendar_month self, :on_cal_month_change 11 evt_calendar_year self, :on_cal_year_change 12 evt_calendar_sel_changed self, :on_calendar_change 13 evt_calendar_weekday_clicked self, :on_calendar_weekday_click 14 end 3,4行目のsuperメソッドの引数に':date => initial_date'とありますが、これは引数initial_dateを変数dateに代入するという意味でよろしいでしょうか。 その場合、7行目の代入式との違いは何なのでしょうか。 また、9行目から13行目にある':on_cal_year_change'などのシンボルは何を表しているのでしょうか。 基本的な質問で恐縮です。色々なサイトを見てもシンボルについての解説が少なく、よく理解ができませんでした。 ご存知の方がいらっしゃいましたらご回答のほどよろしくお願いいたします。

  • 継承について(長文です)

    いつもお世話になっています。現在、継承についての練習問題を解いているのですがわからないことがあるので質問させていただきます。 問題は、「自己紹介メソッド(抽象メソッド)を持つIntroduceクラスを作成し、そのクラスを継承してFistsNameクラス、FullNameクラス、IncludeAgeクラスを作成しなさい。三つのサブクラスのインスタンスを混合して配列に保持し自己紹介をしなさい」というものです。 それぞれのクラスはコマンドライン引数で名字(引数一つ)だけ、フルネーム(引数二つ)、フルネームと年齢(引数三つ)と3種類の引数を入力することによって適切なメソッドが呼び出されるということです。(わかりにくい文章ですいません。例えばヤマダと入力すればFirstNameクラスの自己紹介メソッドが呼び出されてヤマダと表示させたいのです)引数をサブクラスに渡さないと行けませんが、まずコンストラクタで引数をサブクラスに渡す場合は引数を一つ(もしくは二つ)しか指定しなかったときはフルネームとフルネーム+年齢のクラスでコンパイルエラー(ArrayIndexOutOfBoundsException)が出ます(これは理解することが出来ます)次にメソッドで渡す場合はシグネチャが異なるのでオーバーライドされずこちらもコンパイルエラーとなります。この他に引数をサブクラスに渡す方法はあるのでしょうか? わかりにくい文章になってしまいましたが、要するに三つのサブクラスをインスタンス化しその後、引数の個数により適切なサブクラスのメソッドが呼び出され引数を連結して表示させたいのです。このようなことは実現できないのでしょうか?if節によって引数の個数で場合分けなどをしないといけないのでしょうか?質問文がわかりにくければ補足させていただきます。よろしくお願いします。

    • ベストアンサー
    • Java
このQ&Aのポイント
  • ポンプ上流が低圧となる理由について詳しく教えてください。
  • 流量特性について、市販の調整弁の使用場所や種類によってリニア特性かEQ特性になると解釈しても良いのでしょうか?
  • 質問内容の要点をまとめると、ポンプ上流の低圧の理由と市販の調整弁の使用場所や種類による流量特性について教えてください。
回答を見る