Ruby: почему это WHEN-утверждение не работает с двумя условиями? - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть case в моем коде Ruby, который в основном пытается сопоставить строку несколькими способами и соответственно делать с ней разные вещи, вроде как:

case inst
when Rx_inst1
  (some function)
when Rx_inst2
  (some other function)
end

Это прекрасно работает (я не публикую RegEx, так как он очень, очень длинный и хорошо работает). Однако, когда я попытался реализовать следующую модификацию, чтобы даже когда RegEx соответствовал строке, условие не выполняется, если оно содержит подстроку:

case inst
when Rx_inst1
  (some function)
when Rx_inst2 && !/dom\./
  (some other function)
end

it Rx_inst2 прекратил сопоставление inst, когда оно было равно Nm. Friese = Fryzyjczyk, koń fryzyjski или любой другой тип строки, с которой он соответствовал ранее.

Я получил точно такой же результат с && /dom\./ и && inst.include?('dom.'), которые, согласно другим ответам, являются правильным синтаксисом. Что я делаю не так?

Ответы [ 4 ]

0 голосов
/ 07 ноября 2018

@ Darigazz хорошо объяснил, как работает case и почему ваш код неисправен. Вот несколько способов, которыми вы можете написать свое заявление по делу.

# 1

case inst
when Rx_inst1
  m1  
when Rx_inst2
  m2 if inst.match? /dom\./
end

nil возвращается, если inst.match? /dom\./ #=> false in m2 if inst.match? /dom\./. В зависимости от требований if может быть заменено на unless.

# 2

case inst
when Rx_inst1
  m1  
when /(?=.*dom\.)#{Rx_inst2}/
  m2
end

, где (?=.*dom\.) - это позитивный прогноз . Например,

Rx_inst2 = /Bubba|Trixie/
/(?=.*dom\.)#{Rx_inst2}/
   #=> /(?=.*dom\.)(?-mix:Bubba|Trixie)/

В зависимости от требований (?=.*dom\.) может быть заменено на отрицательный прогноз (?!.*dom\.).

0 голосов
/ 05 ноября 2018

Хорошо, так получилось, что я заставил это работать так:

when (!inst.include?('dom.') and Rx_inst2)

Я до сих пор не понимаю, почему мне пришлось делать все эти три следующие вещи:

  1. изменить порядок операций
  2. заключить в скобки все выражение
  3. вызовите первый явно, а второй неявно
0 голосов
/ 05 ноября 2018
case inst
when Rx_inst1
  (some function)
when Rx_inst2 && !/dom\./
  (some other function)
end

case преобразуется в набор операторов if / elsif / else с оператором. === поэтому ваш код эквивалентен

if Rx_inst1 === inst
  (some function)
elsif (Rx_inst2 && !/dom\./) === inst
  (some other function)
end

и (Rx_inst2 && !/dom\./) === inst работает так:

  1. (Rx_inst2 && !/dom\./) часть оценивается как !/dom\./ (Rx_inst2 является RegEx и не ноль или ложь)
  2. !/dom\./ === inst дает вам результат

так when Rx_inst2 && !/dom\./ соответствует всякий раз, когда !/dom\./ === inst соответствует

0 голосов
/ 05 ноября 2018

Совершенно очевидно, Rx_inst2 && !/dom\./ возвращает (из-за оценки короткого замыкания) значение второго операнда, которое равно !/dom\/ (при условии, что Rx_inst2 действительно Regexp и, следовательно, верно). Возможно, вам нужно изменить это регулярное выражение в Rx_inst2, краткого ответа нет.

В качестве альтернативы, вы можете немного изменить все это case выражение, например:

case
when inst =~ Rx_inst1
  # (some function)
when inst =~ Rx_inst2 && !(inst =~ /dom\./)
  # (some other function)
end

но, на мой взгляд, это не очень элегантная форма.

...