Как сопоставить параметр атома с предложением оператора cond - PullRequest
0 голосов
/ 15 марта 2020

Я хочу поместить следующие функции в одну функцию:

def discount(:standard), do: &standard/1
def discount(:bronze), do: &bronze/1
def discount(:silver), do: &silver/1
def discount(:gold), do: &gold/1

Примерно так:

def discount(:rank) do
    cond do
        :standard -> &Shop.standard/1
        :bronze -> &Shop.bronze/1
        :silver -> &Shop.silver/1
        :gold -> &Shop.gold/1
    end
end

Но как мне сопоставить / сравнить параметр функции :rank атомам в моем утверждении cond? Сравнение с == мне тоже не помогает.

Ответы [ 3 ]

3 голосов
/ 15 марта 2020

cond оценивает логические условия. Если вы хотите соответствовать так, используйте case:

def discount(rank) do
  case rank do
    :standard -> &Shop.standard/1
    :bronze -> &Shop.bronze/1
    :silver -> &Shop.silver/1
    :gold -> &Shop.gold/1
  end
end
2 голосов
/ 15 марта 2020

Вам вообще не нужна функция discount/1, если вы используете apply/3:

apply(Shop, rank, [arg])

По моему мнению, если вы выбираете между функцией с несколькими предложениями и одной функция, которая содержит case, версия с несколькими предложениями - лучший код.

Мне также интересно, почему вам нужно возвращать захват функции, а не делать что-то вроде возврата суммы скидки или вычисления дисконтированной стоимости .

1 голос
/ 15 марта 2020

Другой подход - использовать немного метапрограммирования.

defmodule Shop do
  @types ~w|standard bronze silver gold|a

  Enum.each(@types, fn type ->
    def discount(unquote(type)),
      do: &(__MODULE__.unquote type)/1
  end)

  def gold(_), do: 42
  # ...
end

Shop.discount :gold                                 
#⇒ &Shop.gold/1
...