web-dev-qa-db-ja.com

シンボルから文字列の問題

次のコードは失敗します

world = :world
result = 'hello' + world
puts result #=> can't convert Symbol into String

次のコードは動作します

world = :world
result = "hello #{world}"
puts result #=> hello world

どうして?

Ruby 1.8.7を使用

37
Nick Vanderbilt

文字列補間は、暗黙のto_s呼び出しです。だから、このようなもの:

result = "hello #{expr}"

これとほぼ同等です:

result = "hello " + expr.to_s

Karim79が言ったように、シンボルは文字列ではありませんが、シンボルにはto_sメソッドがあるため、補間が機能します。左側の文字列と右側の記号を理解する+の実装がないため、+を連結に使用しようとしてもうまくいきません。

52
mu is too short

worldが数値の場合、同じ動作が発生します。

"hello" + 1 # Doesn't work in Ruby
"hello #{1}" # Works in Ruby

文字列を何かに追加したい場合は、to_strその上:

irb(main):001:0> o = Object.new
=> #<Object:0x134bae0>
irb(main):002:0> "hello" + o
TypeError: can't convert Object into String
        from (irb):2:in `+'
        from (irb):2
        from C:/Ruby19/bin/irb:12:in `<main>'
irb(main):003:0> def o.to_str() "object" end
=> nil
irb(main):004:0> "hello" + o
=> "helloobject"

to_sは「私を文字列に変えることができる」という意味で、to_strは「すべての意図と目的のために、私は文字列です」という意味です。

5
Andrew Grimm

シンボルはnot文字列であるため、明示的な変換なしでは連結できません。これを試して:

result = 'hello ' + world.to_s
puts result
2
karim79

サイドノートとして、あなたはいつでも自分でメソッドを定義できます:)

Ruby-1.9.2-p0 > class Symbol
Ruby-1.9.2-p0 ?>  def +(arg)
Ruby-1.9.2-p0 ?>    [to_s, arg].join(" ")
Ruby-1.9.2-p0 ?>    end
Ruby-1.9.2-p0 ?>  end
 => nil 
Ruby-1.9.2-p0 > :hello + "world"
 => "hello world" 
1
Jed Schneider