Если из конструкции case убрать шаблоны, но оставить охранные выражения, то получится конструкция cond.
Было:
case Expr do
Pattern1 [when GuardSequence1] ->
Body1
...
PatternN [when GuardSequenceN] ->
BodyN
end
Стало:
cond do
GuardSequence1 ->
Body1
...
GuardSequenceN ->
BodyN
end
В принципе, это эквивалент цепочки if...else if
, которая нередко встречается в императивных языках. Python, например:
a = int(input())
if a < -5:
print('Low')
elif -5 <= a <= 5:
print('Mid')
else:
print('High')
Как и в конструкции case, очередность выражений важна. И если ни одно из выражений не вычислилось в true, то возникает исключение.
def my_fun(num) do
cond do
num > 10 -> IO.puts("more than 10")
num > 5 -> IO.puts("more than 5")
end
end
my_fun(20) # => more than 10
my_fun(8) # => more than 5
my_fun(3) # ** (CondClauseError) no cond clause evaluated to a truthy value
В Эликсир есть привычная всем конструкция if:
def gcd(a, b) do
if rem(a, b) == 0 do
b
else
gcd(b, c)
end
end
Только это не настоящая конструкция языка, а макрос. Впрочем, в Эликсир очень многое является макросами. В некоторых случаях это важно знать, в некоторых не важно.
Есть и конструкция unless, тоже макрос:
def gcd(a, b) do
unless rem(a, b) != 0 do
b
else
gcd(b, c)
end
end
Есть важное отличие от императивных языков -- в функциональных языках if всегда возвращает какое-то значение.
a = 5
b = 10
c = if a > b do
a
else
b
end
IO.puts(c)
# => 10
Некоторые функциональные языки требуют, чтобы часть else всегда присутствовала, потому что значение нужно вернуть в любом случае, выполняется условие if или не выполняется. Эликсир этого не требует:
c = if a > b do
a
end
IO.puts(c) # => nil
Реализовать функцию single_win?(a_win, b_win)
, которая принимает 2 булевых параметра: a_win
-- победил ли игрок A, и b_win
-- победил ли игрок B. Функция возвращает true
если победил только один из двоих игроков, иначе возвращает false
.
Реализовать функцию double_win?(a_win, b_win, c_win)
, которая принимает 3 булевых параметра для трех игроков. Если победили игроки A и B, то функция возвращает атом :ab
. Если победили игроки A и C, то функция возвращает атом :ac
, если победили игроки B и C, то функция возвращает атом :bc
. Во всех остальных случаях функция возвращает false
.
Solution.single_win?(true, false)
# => true
Solution.single_win?(false, true)
# => true
Solution.single_win?(true, true)
# => false
Solution.double_win?(true, true, false)
# => :ab
Solution.double_win?(true, false, true)
# => :ac
Solution.double_win?(true, true, true)
# => false
Solution.double_win?(true, false, false)
# => false
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1defmodule Test do
2 use ExUnit.Case
3 import Solution
4
5 test "single_win? test" do
6 assert single_win?(true, false)
7 assert single_win?(false, true)
8 assert not single_win?(true, true)
9 assert not single_win?(false, false)
10 end
11
12 test "double_win? test" do
13 assert :ab == double_win?(true, true, false)
14 assert :bc == double_win?(false, true, true)
15 assert :ac == double_win?(true, false, true)
16 assert not double_win?(true, true, true)
17 assert not double_win?(false, false, false)
18 assert not double_win?(true, false, false)
19 assert not double_win?(false, true, false)
20 assert not double_win?(false, false, true)
21 end
22end
23
Решение учителя откроется через: