web-dev-qa-db-fra.com

Problème de symbole à chaîne

Le code suivant échoue

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

Le code suivant fonctionne

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

Pourquoi?

Utilisation de Ruby 1.8.7

37
Nick Vanderbilt

L'interpolation de chaînes est un appel implicite to_s. Donc, quelque chose comme ça:

result = "hello #{expr}"

est plus ou moins équivalent à ceci:

result = "hello " + expr.to_s

Comme l'a dit karim79, un symbole n'est pas une chaîne mais les symboles ont des méthodes to_s Donc votre interpolation fonctionne; votre tentative d'utilisation de + pour la concaténation ne fonctionne pas car il n'y a pas d'implémentation de + disponible qui comprend une chaîne à gauche et un symbole à droite.

52
mu is too short

Le même comportement se produirait si world était un nombre.

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

Si vous souhaitez ajouter une chaîne à quelque chose, implémentez to_str dessus:

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 signifie "Vous pouvez me transformer en chaîne", tandis que to_str signifie "À toutes fins utiles, je suis une chaîne".

5
Andrew Grimm

Un symbole est pas une chaîne, et en tant que tel, il ne peut pas être concaténé en un sans conversion explicite. Essaye ça:

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

En remarque, vous pouvez toujours définir la méthode vous-même :)

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