【Ruby】文法的なエラーが発生した理由とは?

このQ&Aのポイント
  • 以下のRubyコードを実行すると、hogeとdefaultStringが出力されます。
  • しかし、コードを変更した際にエラーが発生しました。
  • どのような文法的な違反が原因なのか、教えてください。
回答を見る
  • ベストアンサー

【Ruby】 文法的に何が悪いのかわからない

以下に示す(例1)を実行すると、 hoge defaultString と出力されます。 (例1)------------------------------------------------------ def hoge(str) b=(str||'defaultString') + "\n" STDOUT.write b end hoge("hoge") #hoge hoge(nil) #defaultString ------------------------------------------------------------ 下記に示す例2は、例1の2行目と3行目を1行にまとめたものです。 例1と同じ実行結果を期待しています。 (例2) ---------------------------------------------------- def hoge(str) STDOUT.write (str||'defaultString') + "\n" end hoge("hoge") hoge(nil) ------------------------------------------------------------ しかし、例2を実行すると、以下の様なエラーが出ました。 ------------------------------------------------------------ hogewrite.rb:2:in `+': String can't be coerced into Fixnum (TypeError) from write.rb:2:in `hoge' from write.rb:4 ------------------------------------------------------------ 文法的に、何に違反してるのか、わかりません。 ご指導のほど、宜しくお願いいたします。

  • Ruby
  • 回答数2
  • ありがとう数12

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

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

多くの言語では、メソッド呼び出しや関数呼び出しの時に、メソッド名・関数名の後に引数を囲むカッコが必要です。 例: print(1+2) Rubyでは多くの場合、カッコを省略できます。 例: print 1+2 さて、カッコにはこの他に、演算の順序を変えるためのカッコがあります。例:(1+2)/3 メソッド名の後にカッコがある場合、演算の順序を変えるためのカッコなのか、メソッド引数をくくるカッコなのか??? Rubyは、引数をくくるカッコとみなして解釈しようとします。そうじゃなくて演算の順序を変えるカッコのときは、引数をくくるカッコは省略できません。 例:誤: print(1+2)/3 #=> エラー → こう見なされている: (print(1+2)) / 3 #=> printの返す結果を3で割ろうとして、割れないのでエラー ***1 例:正: print((1+2)/3) >文法的に、何に違反してるのか、わかりません。 文法と言うより実行時のエラーです。writeは出力した文字数を返すので str が "hoge" の場合、STDOUT.write(str||'defaultString') は 4 を返します。次に、4 + "\n" を実行しようとして、「文字列と整数は足せない」というエラーになっている。エラーメッセージの corce というのはここでは「(計算できるように値を)変換する」という意味です。 さて、上の ***1 では、わざとエラーになる例にしましたが、 例:STDOUT.write(1+2)/3 はエラーになりません。どうなるかわかりますか? なお、改行付きで出力したい場合は、puts を使うと便利です。 def hoge(str) puts str||'defaultString' end

kingfruits
質問者

お礼

notnotさん、ご回答ありがとうございます。 とても解りやすい説明でした。 >例:STDOUT.write(1+2)/3 >はエラーになりません。どうなるかわかりますか? ()の中の1+2の演算結果が出力されて、writeの戻り値である『1』が3で割られたって事ですね。 以下を実行して検証しました。 ret=STDOUT.write(1+2)/3.0 #=>3 puts puts ret #=> 0.333333333333333

その他の回答 (1)

  • tommy1977
  • ベストアンサー率43% (178/410)
回答No.1

例2 2行目 STDOUT.write (str||'defaultString') + "\n" の write 先が(str||'defaultString')までで終わっていて、 +がなんだかわかんないよ。と言われているので、 STDOUT.write (str||'defaultString'+ "\n") bに代入したものと直で構文化したものは違うので 注意が必要。

kingfruits
質問者

お礼

tommy1977さん、ご回答ありがとうございました。

関連するQ&A

  • ruby メソッドのリターン

    def hoge(arg) "" arg if arg != "" end p hoge("") 上記実行の結果はnilが出力されました。 def piyo(arg) "" end p piyo("") しかし、上記実行の結果は""が出力されました。 前者は""を返してくれないのが納得できません。 説明して頂けませんか?

  • 【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】特異クラスを使って,File.statをカスタムしたい

    File.statに、nameというメソッドを追加したいです。 st=File.stat('hoge.txt') puts st.name #=> hoge.txt 上記のように使いたいのです。 そこで、以下の様に書いてみました。(行頭のスペースは全角です) class File  class << self   def stat(file)    st=File::Stat.new(file)    class << st     def name      @file     end    end    st   end end end st=File.stat('./hoge.txt') puts st.name #=> nil 上記実行結果はnilが出力され、期待した結果は得られませんでした。 上記の様に書いた理由を以下に記します。 クラスメソッドstatは、file.rbのclass Fileの中に定義されていて、 stat.rbのFile::Stat.new(file)を戻り値としていました。 stat.rbのclass File::Statのinitializeでは、 def initialize(file)  @file = file  (略) end となっていたので、上記の様に書いてみたのですが、何が悪いのでしょうか? ご指導のほど、宜しくお願いいたします。

    • ベストアンサー
    • 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】【文法】スパークラスのスーパークラスのメソッドを呼び出したい

    スパークラスのスーパークラスのメソッドを呼び出したいです。 たとえば、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には無い機能が多く拡張されてると考えてください。 ご指導のほど、宜しくお願いいたします。

  • 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】

    #!/usr/bin/ruby -Ke (略) $hoge = input["hoge"] def aaa() (略) end def bbb() (略) end if input["hoge"] aaa() end bbb() このように関数bbbでhtmlのフォームの値hogeを利用して 関数aaaを実行させるプログラムですが、 関数bbbで使用した変数の値をaaaでも利用したいのですが、 よい方法はあるのでしょうか? グローバル変数を$hoge = input["hoge"]の後で $hoge=[]と定義すると、初期化されてしまい、 関数bbbの中でグローバル変数を定義しても駄目でした。

  • 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】 『クラスの生成に失敗』を表現したい

    『クラスの生成に失敗』を表現したいのです。 newの戻り値にnilやfalseを返せばよいと考え、 以下の様に書いてみました。(行頭は全角スペースです。) class Hoge  def initialize(arg)   return arg  end end h = Hoge.new(false) STDERR.puts 'err' unless(h) errはputsされませんでした。(グーグルで調べるとinitializeのreturnは、返ってこないそうでした。) そこで以下の様に書きました。(行頭は全角スペースです。) class Hoge  attr_reader :stat  def initialize(arg)   @stat = arg  end end h = Hoge.new(false) STDERR.puts 'err' unless(h.stat) なんか、ものすごく我流になってる気がします。。。 アドバイスをお願いいたします。

    • ベストアンサー
    • Ruby
  • Ruby

    #!/usr/local/bin/ruby class Foo def []=(x,y) print "Hello,",x,y,"!\n" end end bar = Foo.new bar["wor"] = "ld" 上記実行結果は Hello world! になるのですが、これが理解できません。 上手く説明してくれませんか?

専門家に質問してみよう