Ответ 1
Ваша проблема связана с непониманием оператора or
, который является общим для людей, изучающих языки программирования, подобные этому. Да, ваша непосредственная проблема может быть решена путем написания x ~= 0 and x ~= 1
, но я расскажу немного подробнее о том, почему ваше попытка решения не работает.
Когда вы читаете x ~=(0 or 1)
или x ~= 0 or 1
, это естественно, чтобы анализировать это так же, как предложение "x не равно нулю или одному". В обычном понимании этого утверждения "х" является субъектом, "не равно" - это предикатная или глагольная фраза, а "ноль или один" - это объект, набор возможностей, соединенных конъюнкцией. Вы применяете объект с глаголом к каждому элементу в наборе.
Однако Lua не анализирует это на основе правил грамматики английского языка, он анализирует его в бинарных сравнениях двух элементов на основе его порядка операций. Каждый оператор имеет приоритет, который определяет порядок, в котором он будет оцениваться. or
имеет более низкий приоритет, чем ~=
, так же как добавление в математике имеет более низкий приоритет, чем умножение. Все имеет более низкий приоритет, чем круглые скобки.
В результате при оценке x ~=(0 or 1)
интерпретатор сначала вычислит 0 or 1
(из-за круглых скобок), а затем x ~=
результат первого вычисления, а во втором примере он вычислит x ~= 0
, а затем применить результат этого вычисления к or 1
.
логический оператор or
"возвращает свой первый аргумент, если это значение отличается от nil и false, иначе или возвращает его второе аргумент". Оператор реляционный оператор ~=
является обратным оператору равенства ==
; он возвращает true, если его аргументы являются разными типами (x - число, правильно?) и в противном случае обычно сравнивает его аргументы.
Используя эти правила, x ~=(0 or 1)
будет разлагаться на x ~= 0
(после применения оператора or
), и это вернет 'true', если x - это что-то другое, кроме 0, включая 1, что нежелательно. Другая форма x ~= 0 or 1
сначала оценит x ~= 0
(которая может возвращать true или false, в зависимости от значения x). Затем он разложится на один из false or 1
или true or 1
. В первом случае оператор вернет 1
, а во втором случае оператор вернет true
. Поскольку структуры управления в Lua рассматривают только nil
и false
как ложные, а что-то еще, чтобы быть истинными, это всегда будет вводить оператор if
, который не является тем, что вы хотите.
Невозможно использовать бинарные операторы, такие как предоставленные в языках программирования, для сравнения одной переменной со списком значений. Вместо этого вам нужно сравнить переменную с каждым значением по одному. Есть несколько способов сделать это. Самый простой способ - использовать законы Де Моргана, чтобы выразить утверждение "не одно или равно нулю" (которое нельзя оценить с помощью двоичных операторов) как "не одно, а не ноль", которое тривиально записывается двоичными операторами:
if x ~= 1 and x ~= 0 then
print( "X must be equal to 1 or 0" )
return
end
В качестве альтернативы вы можете использовать цикл для проверки этих значений:
local x_is_ok = false
for i = 0,1 do
if x == i then
x_is_ok = true
end
end
if not x_is_ok then
print( "X must be equal to 1 or 0" )
return
end
Наконец, вы можете использовать реляционные операторы для проверки диапазона, а затем проверить, что x является целым числом в диапазоне (вы не хотите 0.5, верно?)
if not (x >= 0 and x <= 1 and math.floor(x) == x) then
print( "X must be equal to 1 or 0" )
return
end
Обратите внимание, что я написал x >= 0 and x <= 1
. Если вы поняли приведенное выше объяснение, вы должны теперь объяснить, почему я не написал 0 <= x <= 1
, и что это ошибочное выражение вернется!