• ベストアンサー

後処理を保証するブロック付きメソッドの例について。

後処理を保証するブロック付きメソッドの例について。 後処理を保証するブロック付きメソッドの例として、以下のプログラムがありました。 def omit_brock1 if defined? yield puts "brock exist" else 以下略 2行目のyieldについて質問です。 yieldってはじめからRubyにあったはずです。これをdefined?してもかならずtrueが返るのではないでしょうか?とするとif文使うのも無駄だと思うのですが、どうなんでしょう? よろしくお願いします。

  • ghfjri
  • お礼率92% (372/403)
  • Ruby
  • 回答数2
  • ありがとう数6

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

  • ベストアンサー
  • siffon9
  • ベストアンサー率64% (136/211)
回答No.1

def omit_block1 if defined? yield puts "brock exist" else puts "brock not exist" end end omit_block1{puts "foo"} #=> brock exist omit_block1 #=> brock not exist ブロックなしでメソッドを呼ぶとif文の判定はfalseになりますね。 メソッドの定義の中にyieldが在った場合には、一時的にブロックへ制御が渡されます。ですからブロック付で呼ばれる場合とそうでない場合があるメソッドの場合、ブロックの有無を判定して処理を分けなければなりません。 > yieldってはじめからRubyにあったはずです。 このif文の意味は、yieldという語句がRubyに存在するかをみているのではなくて、yieldが制御を渡すブロックの有無を判断しています。 ちなみにyieldのあるメソッドをブロックなしで呼ぶとエラーになりました。 def omit_block1 yield end omit_block1 test.rb:4:in `omit_block1': no block given (yield) (LocalJumpError) from test.rb:7:in `<main>'

ghfjri
質問者

お礼

回答いつもありがとうございます。 なるほど。メソッドの有無ではなくてブロックの有無をdefined?で聞いていたんですね。よくわかりました。

その他の回答 (1)

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

リファレンスのdefined?の部分に以下の記述があります。 >特別な用法として以下があります。 > >defined? yield >yield の呼び出しが可能なら真(文字列 "yield")を返します。 block_given? と同様にメソッドがブロック付きで呼ばれたかを判断する方法になります。 普通は、 def omit_brock1 if block_given? puts "block exist" else puts "block not exist" end end と、block_given? を使うと思います。これはtrue/falseを返します。

ghfjri
質問者

お礼

回答ありがとうございます。 わかりやすい説明ありがとうございます。 普通はblock_given?を使うんですね。 勉強になりました。

関連する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
  • ブロックつきメソッドやyield文の用途について

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

    • ベストアンサー
    • Ruby
  • Ruby 文法 ブロックの中で メソッドを呼ぶ

    class Hoge def val 'aaa' end def piyo yield end end h=Hoge.new h.piyo do p h.val #<ーここの話 end 上の様に書く時、ブロックの中で、そのクラスのメソッドを呼ぶ時、上の例だと h.val と書いてますが、これself.valなどと書きたいのですがERRになってしまいます。 h.と書くのがとても嫌なのですが、なにか良い書き方あるのでしょうか?

    • ベストアンサー
    • Ruby
  • 【ruby】二つのブロック付きメソッドをif文で使い分けたい

    二つのブロック付きメソッドhogeとpiyoがあるとします。 ブロックの中に記述するプログラムは同じだが、hogeを使うか、piyoを使うかは条件により制御したいです。 このような場合、どのように書いたら簡素になるでしょうか? sw=true if sw then  hoge() do |x|   puts x  done else  piyo() do |x|   puts x  done end 上記例では冗長の思うのですが、ご指導のほど宜しくお願いいたします。

    • ベストアンサー
    • 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】無名関数?でブロック付きメソッドって作れませんか?

    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
  • 【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 sortメソッド

    RubyのEnemuratableモジュール内で定義されているメソッドのひとつsort メソッドの使い方が良くわかりません。 ブロックや<=>演算子を用いて何か分かりやすい例はありますでしょうか?

  • ブロック1 Ruby認定試験対策問題

    Ruby認定試験対策問題をやっていたら分からないところがあったので、 教えてください。 2.9-1.ブロック ■問題 testメソッドに渡されたブロックのselfは次のうちどれか? class Foo def test (1..3).each{|i| yield(i)} end end foo = Foo.new foo.test{|i| i } ■回答 トップレベル ■解説 ブロックはメソッドの呼出し先のselfを継承します ■疑問 ・testメソッドに渡されたブロックとは、(1..3)のことを指すのでしょうか。 ・メソッドの呼出し先とは、foo.test{|i| i }のことを意味しているのでしょうか。 ・呼出し先のselfとは、fooかFooのことでしょうか? ・「selfはメソッド内で実行されるとそのメソッドを実行しているオブジェクトを参照することが出来ます」 と別のサイトに記載されていたのですが、「トップレベルのselfとはObjectクラスのメソッドを実行している」、という意味になるのでしょうか。 それがこの問題のどこに関連しているのでしょうか。

    • ベストアンサー
    • Ruby
  • メソッドのモンキーパッチ

    # Ruby 2.1 環境です。 # 変更できないモジュール Mylib があります。 module Mylib def self.mymethod(n) puts "hello!" * n end def mymethod(*args) Mylib.mymethod(*args) end end # Mylib は次のように使っています。 # # 1. クラスメソッドとして呼び出し # # Mylib.mymethod 3 # => "hello!hello!hello!" # # 2. Mix-in してからメソッド名だけの呼び出し # # include Mylib # mymethod 1 # => "hello!" # これはちゃんと期待通りの挙動です。 # ---- # 元の Mylib に変更を加えずに、mymethod と同名で # mymethod の事前処理・# 事後処理を使う側で定義したいです。 # # 次のコードを書いてみました。 # モジュールを再オープンします。 module Mylib def self.mymethod_new(n) # 事前・事後処理を行うメソッドの実装です。 puts "mymethod_new" Mylib.mymethod_old(n.is_a?(Fixnum) ? n : 1) end def mymethod_new(*args) # alias_method でシンボル参照させるための定義です。 Mylib.mymethod_new(*args) end # エイリアスを設定 alias_method :mymethod_old, :mymethod alias_method :mymethod, :mymethod_new end # テスト実行します。 Mylib.mymethod("asdf") # => "mymethod_new" は印字されず、次の例外が出ます。 # no implicit conversion of String into Integer (TypeError) # mymethod_new を通っていないようです。 # どのように記述すれば良いでしょうか?

    • ベストアンサー
    • Ruby