2014-02-17 7 views
2

Я очень смущен о каком-то тернарном выражении в рубине.akward trernary оценка в ruby ​​

У меня есть это выражение:

puts respond_to? "greeting".to_sym ? "hello" : "bye" 

конечно, что это не то, что я делаю в моем приложении, как раз для вас, чтобы увидеть.

вещь в том, что приведенное выше выражение возвращает

false 

, когда оно должно быть возвращение hello если метод существует и bye, если это не так ли?

если я изменить выражение

puts respond_to?("greeting".to_sym) ? "hello" : "bye" 

возвращает правильную вещь, либо «привет», если она существует, и «до свидания» в противном случае.

Почему это происходит? Есть что-то о тройном выражении в рубине, которого я не знаю?

Просто, чтобы вы знаете правильный код в моем приложении является:

respond_to?(path.to_sym) ? self.send(path) : "#" 

Который возвращает правильный путь для БД хранятся меню заголовка и, если он не существует, то он будет просто положить «# «чтобы избежать ошибок.

ответ

3

Если вы не имеете скобки для respond_to, оценка происходит как этого

"greeting".to_sym ? "hello" : "bye" #results in "hello" 

puts respond_to? "hello" #results in false 

тройного выражение будет получить оценку первой без скобок для respond_to

2

я побежал ruby --dump parsetree на вашем примере (всегда хороший способ увидеть, что на самом деле происходит). В версии без круглой скобки аргумента тернар оценивается и respond_to? проверяет на "hello" или «bye». Во втором случае код делает то, что вы намереваетесь.

без скобок:

# @ NODE_SCOPE (line: 1) 
# +- nd_tbl: (empty) 
# +- nd_args: 
# | (null node) 
# +- nd_body: 
#  @ NODE_FCALL (line: 1) 
#  +- nd_mid: :puts 
#  +- nd_args: 
#   @ NODE_ARRAY (line: 1) 
#   +- nd_alen: 1 
#   +- nd_head: 
#   | @ NODE_FCALL (line: 1) 
#   | +- nd_mid: :respond_to? 
#   | +- nd_args: 
#   |  @ NODE_ARRAY (line: 1) 
#   |  +- nd_alen: 1 
#   |  +- nd_head: 
#   |  | @ NODE_IF (line: 1) 
#   |  | +- nd_cond: 
#   |  | | @ NODE_CALL (line: 1) 
#   |  | | +- nd_mid: :to_sym 
#   |  | | +- nd_recv: 
#   |  | | | @ NODE_STR (line: 1) 
#   |  | | | +- nd_lit: "greeting" 
#   |  | | +- nd_args: 
#   |  | |  (null node) 
#   |  | +- nd_body: 
#   |  | | @ NODE_STR (line: 1) 
#   |  | | +- nd_lit: "hello" 
#   |  | +- nd_else: 
#   |  |  @ NODE_STR (line: 1) 
#   |  |  +- nd_lit: "bye" 
#   |  +- nd_next: 
#   |   (null node) 
#   +- nd_next: 
#    (null node) 

С:

# @ NODE_SCOPE (line: 1) 
# +- nd_tbl: (empty) 
# +- nd_args: 
# | (null node) 
# +- nd_body: 
#  @ NODE_FCALL (line: 1) 
#  +- nd_mid: :puts 
#  +- nd_args: 
#   @ NODE_ARRAY (line: 1) 
#   +- nd_alen: 1 
#   +- nd_head: 
#   | @ NODE_IF (line: 1) 
#   | +- nd_cond: 
#   | | @ NODE_FCALL (line: 1) 
#   | | +- nd_mid: :respond_to? 
#   | | +- nd_args: 
#   | |  @ NODE_ARRAY (line: 1) 
#   | |  +- nd_alen: 1 
#   | |  +- nd_head: 
#   | |  | @ NODE_CALL (line: 1) 
#   | |  | +- nd_mid: :to_sym 
#   | |  | +- nd_recv: 
#   | |  | | @ NODE_STR (line: 1) 
#   | |  | | +- nd_lit: "greeting" 
#   | |  | +- nd_args: 
#   | |  |  (null node) 
#   | |  +- nd_next: 
#   | |   (null node) 
#   | +- nd_body: 
#   | | @ NODE_STR (line: 1) 
#   | | +- nd_lit: "hello" 
#   | +- nd_else: 
#   |  @ NODE_STR (line: 1) 
#   |  +- nd_lit: "bye" 
#   +- nd_next: 
#    (null node) 
5

Без скобок, кажется, что ваш код интерпретируется следующим образом:

puts respond_to?("greeting".to_sym ? "hello" : "bye") 

Материал в скобках затем оценивая «привет», и self, по-видимому, не отвечает на это, поэтому respond_to?false.

Вот почему всегда полезно использовать круглые скобки, когда есть какие-либо сомнения относительно порядка операций вашего кода; это делает ваш код более читаемым и устраняет ошибки, такие как этот.

Смежные вопросы