2017-01-13 1 views
1

J'ai essayé d'utiliser le raccourci pour obtenir une réponse basée sur l'existence d'une sous-chaîne, au lieu de la réponse de chaîne attendue, il a évalué à "faux". Dans mon deuxième exemple plus simple, la chaîne attendue a été imprimée.Pourquoi l'utilisation de la syntaxe sténographique "si" n'évalue-t-elle pas la recherche d'une sous-chaîne à l'aide de "include?"

#fails

puts "test".include? "s" ? "yep" : "nope" 

#success

puts 1>2 ? "1 is greater than 2" : "1 is not greater than 2" 

Répondre

6

C'est un problème precedence.

Solution

Vous devez:

puts "test".include?("s") ? "yep" : "nope" 
#=> yep 

Pourquoi?

L'appel de méthode sans parenthèse se situe entre defined? et or dans la table de précédence, il est donc inférieur à l'opérateur ternaire. Cela signifie que

puts "test".include? "s" ? "yep" : "nope" 

est analysé comme

puts "test".include?("s" ? "yep" : "nope") 

qui est

puts "test".include?("yep") 

qui est

false 

Avertissement

"s" ? "yep" : "nope" 

affiche un avertissement:

warning: string literal in condition 

parce que l'opérateur ternaire attend un booléen, et une chaîne est toujours truthy.

1> 2

La raison pour laquelle cela fonctionne

puts 1>2 ? "1 is greater than 2" : "1 is not greater than 2" 

est que l'opérateur ternaire a une priorité plus élevée que met:

puts (1>2 ? "1 is greater than 2" : "1 is not greater than 2") 

Il est évalué comme:

puts ("1 is not greater than 2") 

Une dernière astuce

Lorsque vous avez un problème de précédence, l'utilisation de puts sans parenthèse peut aggraver le problème. Vous pouvez déclencher IRB et voir ce que le résultat est directement.

Voici un exemple:

# in a script : 
puts [1,2,3].map do |i| 
    i * 2 
end 
#=> #<Enumerator:0x0000000214d708> 

Avec IRB:

[1,2,3].map do |i| 
    i * 2 
end 
# => [2, 4, 6] 
+2

Cette réponse devient une épopée. Aimer. –

+0

La force de liaison est la clé ici. La préséance est un terme plus général qui signifie la même chose. – tadman

+0

@tadman: intéressant, merci. Je viens de googler "Force de liaison Ruby", et surtout trouvé vos réponses sur SO. Avez-vous une référence? –

2

Il ressemble à Ruby est incapable d'analyser ce que vous attendez sans un peu d'aide. Il pense que vous faites

puts "test".include?("s" ? "yep" : "nope") 

Vous devez soit utiliser les (en option) parens autour de l'argument

puts "test".include?("s") ? "yep" : "nope" 

ou forcer l'expression de test pour être interprété dans son ensemble:

puts ("test".include?"s") ? "yep" : "nope" 
+1

Pourquoi devrais être abaissé? Je ne comprends pas. Downvoters: s'il vous plaît laissez un commentaire. –

+1

Je ne sais pas pourquoi, mais le manque de lettres majuscules pourrait conduire les gens à une rage de vote. – tadman

+0

Sheesh. Ok, édité pour ajouter le capital initial. Soupir. –