• ベストアンサー

【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
  • 回答数1
  • ありがとう数2

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

  • ベストアンサー
  • ryu_chan
  • ベストアンサー率37% (69/186)
回答No.1

以下のように、ブロックを一旦、変数に格納すればすっきりすると思います。 block = proc {|x| puts x } if sw hoge &block else piyo &block end __send__(あるいはsend)を使うと1行で書けます。 __send__( sw ? 'hoge' : 'piyo', &proc {|x| puts x } ) メソッドがたくさんある場合は以下のようにすることもできます。 sw = 2 __send__( %w(hoge fuga piyo foo bar baz)[sw], &proc {|x| puts x } )

kingfruits
質問者

お礼

ryu_chanさん、ご回答有難うございました。 rubyの事だから、きっと良い方法があるのだろうと、うすうす感じてましたが、こんな素晴らしい方法があるんですね!! 勉強になりました。

関連するQ&A

  • 【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 文法 ブロックの中で メソッドを呼ぶ

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

    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 文法 ブロックの中で自クラスの定数を呼ぶ

    以前した質問(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 でメソッドを自作してそのメソッドにブロックを持たせる場合 ブロック内で返り値を返すためにはどうしたらいいのでしょうか? たとえば以下のような自作メソッドがあるとすると 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
  • オープンクラスで再定義時に別で定義されたメソッドの

    オープンクラスで再定義時に別で定義されたメソッドの呼び出しについてです。 ある編集不可能なクラス Hoge の fuga メソッドの戻り値によって、新たなメソッド piyo を定義したいと考え、次のコードを試してみました。 irb(main):001:0> class Hoge irb(main):002:1> def fuga irb(main):003:2> 1 irb(main):004:2> end irb(main):005:1> end => :fuga irb(main):006:0> irb(main):007:0* class Hoge irb(main):008:1> if self.fuga == 1 irb(main):009:2> def piyo irb(main):010:3> puts "foobarbaz" irb(main):011:3> end irb(main):012:2> end irb(main):013:1> end NoMethodError: undefined method `fuga' for Hoge:Class from (irb):8:in `<class:Hoge>' from (irb):7 from /usr/bin/irb:11:in `<main>' この目的の場合、8~12行目はどのような記述をすれば良いのでしょうか。 なお、Hoge のインスタンス作成後に特異メソッドとして piyo を追加のが都合上、難しい状態です。 バージョンは ruby 2.1.5p273 です。 よろしくお願いします。

    • ベストアンサー
    • Ruby
  • ruby undefined method

    class Hoge def body "aaa" end end def up(arg) arg.upcase end res=Hoge.new res.body = up(res.body) puts res.body 上記を実行すると、undefined method `body=' for #<Hoge:0x2b36454> (NoMethodError) になります。 最後の2行を以下のように変えるとうまく動作します。 tmp=res.body tmp = up(tmp) puts tmp この理由が理解できません。 説明して頂けませんか?

  • 【ruby】【文法】スパークラスのスーパークラスのメソッドを呼び出したい

    スパークラスのスーパークラスのメソッドを呼び出したいです。 たとえば、Hoge3のスーパークラスがHoge2で、さらにそのスーパークラス がHogeの時、Hoge3からHogeのメソッドを呼び出したいのです。 もう少し具体的に説明させてもらいます。 class Hoge  def initialize()   @name='hoge'  end end class Hoge2 < Hoge  def initialize()   super   @name='hogehoge'  end end class Hoge3 < Hoge2  def initialize()   super #これではスーパークラスHoge2のメソッドが呼ばれてしまう。   puts @name  end Hoge3.new() 上記実行結果は、hogehogeが出力ですが、 スーパークラスのスーパークラスが設定した@name値、 'hoge'が出力されるようにしたいです。 『Hoge3クラスはHoge2クラスを継承すればよいではないか?』 とも思うでしょうが、Hoge2クラスには、Hogeには無い機能が多く拡張されてると考えてください。 ご指導のほど、宜しくお願いいたします。

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

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

    • ベストアンサー
    • Ruby
  • if文からcase文への置き換え

    ピクチャボックスをクリックしたら、チェック ボックスがチェックされるメソッドを作りたいと 思っています。 Private Sub PictureBox_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click,PictureBox2.Click 'ここから If sender Is PictureBox1 Then If Me.CheckBox1.Checked = False Then Me.CheckBox1.Checked = True Else Me.CheckBox1.Checked = False End If ElseIf sender Is PictureBox2 Then If Me.CheckBox2.Checked = False Then Me.CheckBox2.Checked = True Else Me.CheckBox2.Checked = False End If End If 'ここまで End Sub 上記のif文をCase文に置き換えたくて、 'ここから Select Case sender Case PictureBox1 If Me.CheckBox1.Checked = False Then Me.CheckBox1.Checked = True Else Me.CheckBox1.Checked = False End If Case PictureBox2 If Me.CheckBox2.Checked = False Then Me.CheckBox2.Checked = True Else Me.CheckBox2.Checked = False End If End Select 'ここまで 上記のように書き換えたのですが、エラーが出てしまいます(ビルドは通るのですが)。 Case文の使い方が間違っているんだとは思いますが、どこがどう 間違っているのがよくわかりません。 ご教授いただけないでしょうか?

専門家に質問してみよう