2015-08-20 2 views
0

Я ожидаю, что этот код для выполнения блока кода и привести к выходу "x" и "y", или просто бросить синтаксическую ошибку:Странный результат в Руби «конец, если»

if true 
    puts "x" 
end if 
puts "y" 

Однако интерпретатор игнорирования блок if true и выполняет только puts "y". Если я вместо этого ввести следующий код:

if true 
    puts "x" 
end if 

интерпретатор завершает работу с ошибкой синтаксиса конца-входа. Есть ли причина, по которой первый фрагмент является допустимым кодом, но каким-то образом неправильным? Мне кажется, что в парсере есть некоторая ошибка.

Я подтвердил это в Ruby 2.1.2, а также Ruby 2.1.5.

+0

Ваш код эквивалентен 'if puts" y "; если правда; ставит «х»; конец; end'. 'puts" y "' возвращает 'nil', поэтому' if true; ставит «х»; end' не выполняется. –

+0

Aaaa, я понимаю. Он выполняется как однострочный. (если true, помещает «x»; конец), если puts «y» Немного сложно. Не ожидал, что он это прочитает. –

+0

Попробуйте использовать анализатор [Ruby parseer] (https://github.com/seattlerb/ruby_parser) и посмотрите, может ли он объяснить, как интерпретируется ваш код. –

ответ

6

Есть две вещи, которые играют вместе здесь:

  1. Значение возвращение puts является nil
  2. Рубин обычно достаточно умен, чтобы прочитать следующую строку, если текущая команда еще не закончилась.

Это означает, что:

if true 
    puts "x" 
end if 
puts "y" 

является тем же, чем:

if true 
    puts "x" 
end if (puts "y") 

Рубин оценивает puts "y" всухую:

if true 
    puts "x" 
end if nil 

Что приводит Руби не оценить if true блок , потому что if nil действует как if false.


Или другими словами: Ваш пример такой же, как:

if puts("y") # evaluates to nil (aka is falsey) 
    if true 
    puts "x" 
    end 
end 
+0

Но не должен ли конец заканчивать первое утверждение if? Это как-то выполнено как «и» утверждение? –

+0

'end' завершает первый оператор' if'. Но 'if' в той же строке, что и' end', работает как обычный [modifing 'if'] (https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier) как вы могли видеть (что-то вроде этого однострочного: 'do_foo, если bar?'). – spickermann

0

Ваш код неверен. Правильный код:

if true 
    puts "x" 
end 
puts "y" 

Ваш код говорит Руби выполнить if true ... end block если таковые puts "y" возвращает истинный. puts возвращает nil, что соответствует ошибке в проверке состояния, что приводит к тому, что блок вообще не выполняется.

+2

В этом синтаксисе нет ничего неправильного. Это широко используемый синтаксис. –

+0

Ты прав. Я имел в виду неправильное с точки зрения того, что пытался сделать айзер. – tekina

+0

Вы правы. Я забыл себя и подумал, что пишу скрипт VB;) –

2

Я думаю, что вы имеете в виду, чтобы написать это

if true 
    puts "x" 
end 
puts "y" 

Это будет производить вывод, который вы ожидаете.

+0

Почему вы думаете, что это задумал OP? –

+0

Потому что он говорит, что он ожидал, что исходный код будет выводить x и y. –

+0

Возможно, он ожидал, что, поскольку он думал, что «ставит» y «возвращает истинное значение. Оба объяснения правдоподобны. –

0

Ваш код эффективно говорит только для выполнения блока if true, только если puts "y" возвращает true. К сожалению, puts возвращает ноль. Чтобы завершить заявление if в Ruby, вам просто нужно использовать end. В отличие от Shell Scripting или Visual Basic, для разных блоков нет конкретных конечных операторов.

Изменить

if true 
    puts "x" 
end if 
puts "y" 

в

if true 
    puts "x" 
end 
puts "y" 

И вы будете золотой.

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