Как я могу написать ленивую оценку операторов переключателя? - PullRequest
1 голос
/ 18 ноября 2009

В течение долгого времени я отчаянно пытался заставить это работать, я погуглил, я возился и попросил некоторых местных Rubyists (хотя не pdx.rb, хотя я действительно должен).

Мы пытались сделать что-то подобное на работе:

case user.roles.included? (... magic ...) 
when ['admin', 'editor'] 
  then ...
when ['anonymous'] 
  then ...
end

Таким образом, вы можете видеть, как это выглядит case, но поскольку он не использует ===, как заметил Эль, он не работает. Я знаю, что могу использовать if, но похоже, что нужно использовать case.

Ответы [ 2 ]

3 голосов
/ 18 ноября 2009

when использует оператор === для сравнения значения, заданного для case, с аргументом, заданным для when. Кроме того, then не требуется при появлении в строке, отличной от оператора when. Правильный код для того, что вы пытаетесь сделать:

case x
when 16
  puts 'hi'
when Object
  puts 'obj'
end

Что касается нового дополнения к вопросу:

case user.roles.included? (... magic ...) 
when ['admin', 'editor'] 
  ... 
when ['anonymous'] 
  ... 
end

Это не работает, потому что === массива не сопоставляется с include. Я не уверен, откуда взялся оператор Array === или даже что он делает, но вы можете переопределить его, чтобы обеспечить желаемую функциональность.

Судя по приведенному выше коду, вы хотите, чтобы case срабатывал, если одна из ролей пользователя соответствует массиву. Это переопределит Array#=== для этого:

class Array
  def === other_array
    ! (other_array & self).empty?
  end
end

case user.roles
when ['admin', 'editor'] 
  ... 
when ['anonymous'] 
  ... 
end

Предупреждение: В зависимости от того, где вы переопределите Array#===, это может привести к непредвиденным последствиям, поскольку изменит все массивы в этой области. Учитывая, что === наследуется от Object, где он является псевдонимом для ==, я не ожидаю, что это будет большой проблемой.

Места, где новый === отличается от старого ===:

  • New === вернет true, если один из массивов является подмножеством или переупорядочивает другой.
  • Старый === вернет true, только если два массива идентичны (порядок и содержимое).

Насколько я знаю, case / when - единственный раз, когда === может быть неявно вызван для массива.

3 голосов
/ 18 ноября 2009
case 
  when x == 16
    puts 'hi'
  when x.is_a?(Object)
    puts 'obj'
end

Если я действительно понял вопрос, вам просто нужно удалить переменную x после ключевого слова case.

Лямбда-код не работал, потому что лямбда-код просто возвращает аргумент.

names_l.call(names)
# => {:name => 'Terry'}

Это похоже на запуск следующего кода:

case {:name => 'Terry'}
  when 'Terry'
    puts "Success!"
end

А {:name => 'Terry'} не равно 'Terry'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...