2015-06-22 4 views
0

Долгий вопрос, но я думаю, что это странно. Я играл с заявлениями о рубине. Создал небольшую функцию fizzbuzz для практики.Заявление оператора Fizzbuzz

Изначально созданный код, как это

def fizzbuzz(start_num, end_num) 
    fizzbuzz = [] 
    (start_num..end_num).each do |x| 
     if x % 3 == 0 && x % 5 != 0 
      fizzbuzz << "fizz" 
     elsif x % 5 == 0 && x % 3 != 0 
      fizzbuzz << "buzz" 
     elsif (x % 3 == 0 && x % 5 == 0) 
      fizzbuzz << "fizzbuzz" 
     else 
      fizzbuzz << x.to_s 
     end 
    end 
    fizzbuzz 
end 

работ, как и ожидалось. Затем захотелось играть с помощью оператора switch. Так что я пробовал:

def fizzbuzz(start_num, end_num) 
fizzbuzz = [] 
(start_num..end_num).each do |x| 
    case x 
    when x % 3 == 0 
     fizzbuzz << "fizz" 
    when x % 5 == 0 
     fizzbuzz << "buzz" 
    when (x % 3 == 0 && x % 5 == 0) 
     fizzbuzz << "fizzbuzz" 
    else 
     fizzbuzz << x.to_s 
    end 
end 
fizzbuzz 

конец

На этот раз код выводит только число преобразуется в строку. Тогда по ошибке я пытался добавить & & в конце каждого, когда заявление как так

def fizzbuzz(start_num, end_num) 
    fizzbuzz = [] 
    (start_num..end_num).each do |x| 
     case x 
     when x % 3 == 0 && 
      fizzbuzz << "fizz" 
     when x % 5 == 0 && 
      fizzbuzz << "buzz" 
     when (x % 3 == 0 && x % 5 == 0) && 
      fizzbuzz << "fizzbuzz" 
     else 
      fizzbuzz << x.to_s 
     end 
    end 
    fizzbuzz 
end 

Интересно это выводит правильный результат. Это, вероятно, тривиальный ответ, но кто-нибудь знает, почему это так? Мне кажется странным.

+2

Потому что оператор switch выполняет только одну ветвь, и вам нужно, чтобы она ударила несколько. FizzBuzz не является большим вариантом использования для 'case' – Brennan

+0

@Brennan Это не так, но это не проблема. код OP не требует какого-либо провального поведения. Может быть, я не понимаю вашу точку зрения. –

+1

Сначала я неправильно читаю. Это не проблема, и как только исправлено будет работать, но она все еще показывает непонимание того, как эта структура работает.Он не требует * какого-либо пассивного поведения, но он, безусловно, пытается использовать его как таковой. – Brennan

ответ

1

Операторы when делают логические &&.

У этого есть побочный эффект, связанный с конкатенированием вашего выхода, когда условие истинно.

Вопрос: На самом деле спрашивает, на основе вашего комментария, что происходит с операциями when, которые не работают. Проблема в том, что вы написали case x, который оценивает x на месте и сравнивает его с выражениями when.

Вместо этого использовать "голый case", например,

case 
when (x % 3) == 0 
    # etc 

Отметим также, что это может быть обернуты немного плотнее, например,

def fizzbuzz(start_num, end_num) 
    (start_num..end_num).collect do |x| 
    case 
     when (x % 3) == 0 
     "fizz" 
     when (x % 5) == 0 
     "buzz" 
     when (x % 3 == 0 && x % 5 == 0) 
     "fizzbuzz" 
     else 
     x.to_s 
    end 
    end 
end 
1

За последний кусок кода, давайте посмотрим, один when состояние в деталях:

when x % 3 == 0 && 
    fizzbuzz << "fizz" 

Несмотря на indentat иона, это эквивалентно:

when x % 3 == 0 && fizzbuzz << "fizz" 

Помните, что && короткое замыкание. Выражение && возвращает свой первый аргумент, если он является ложным. В противном случае его второй аргумент оценивается и возвращается в качестве результата.

Так что если x % 3 == 0 является ложным, то fizzbuzz << "fizz" не выполняется. Если верно x % 3 == 0, выполняется fizzbuzz << "fizz". Именно то, что ожидается.

+0

Понял, однако часть, которая меня смущает, кажется, не задана в исходном вопросе, почему исходный оператор switch не выполнил 'fizzbuzz <<" fizz ", даже если' when x% 3 == 0' был true ? –

+0

@AlexKonetchy Потому что это не так, как работают операторы Ruby 'case'; поскольку вы написали «случай x», он сравнивает «x» с значением выражения 'when'. –