Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Functional programming 如何重构两个类似的函数以减少Elixir中的代码重复?_Functional Programming_Elixir_Refactoring_Higher Order Functions_Extraction - Fatal编程技术网

Functional programming 如何重构两个类似的函数以减少Elixir中的代码重复?

Functional programming 如何重构两个类似的函数以减少Elixir中的代码重复?,functional-programming,elixir,refactoring,higher-order-functions,extraction,Functional Programming,Elixir,Refactoring,Higher Order Functions,Extraction,我有以下两项职能: defp select_previous_scheduled_price(scheduled_prices, date) do if length(scheduled_prices) > 1 do before_prices = Enum.filter(scheduled_prices, &starts_before(&1, date)) if !Enum.empty?(before_prices) do

我有以下两项职能:

  defp select_previous_scheduled_price(scheduled_prices, date) do
    if length(scheduled_prices) > 1 do
      before_prices = Enum.filter(scheduled_prices, &starts_before(&1, date))

      if !Enum.empty?(before_prices) do
        hd(before_prices)
      else
        nil
      end
    else
      nil
    end
  end

  defp select_next_scheduled_price(scheduled_prices, date) do
    if length(scheduled_prices) >= 1 do
      after_prices = Enum.filter(scheduled_prices, &starts_after(&1, date))

      if !Enum.empty?(after_prices) do
        hd(after_prices)
      else
        nil
      end
    else
      nil
    end
  end
有两个区别: 1.第二行上的运算符(即,
vs
=
);和 2.为在第三行3上进行过滤而调用的函数(即,
&start\u在/2之前
&start\u在/2之后

由于差异是运算符,而不是函数和必须应用局部值和参数化值的函数,因此我不完全清楚是否或如何考虑这一点

换句话说,我想让解决方案像这样(只实际起作用,而不是这样):

有没有办法让这一切顺利进行

谢谢

而不是将首先消除嵌套
if
的必要性。然后,我将代码拆分为更小的函数,以澄清其意图

defp if_价格(:之前,价格,日期),
do:{length(prices)>1,并在(&1,date)}
如果价格(:之后,价格,日期),
do:{length(prices)>=1,并在(&1,date)}
defp选择上一个计划价格(计划价格、日期),
do:选择计划价格(:之前,计划价格,日期)
defp选择下一个计划价格(计划价格、日期),
do:选择计划价格(:之后,计划价格,日期)
defp选择计划价格(方向、价格、日期)do
如果价格(方向、价格、日期)符合要求
{false,{}->nil
{{{有趣}->
价格
|>枚举过滤器(乐趣)
|>表1.first()
结束
结束

这是一个与您尝试的版本非常相似的版本。它可以编译(但我没有用真实数据运行它)

显著变化:

  • 要传递二进制运算符,可以使用
    &
    /2
    =
    变为
    &>=/2
  • 要调用这些函数,需要使用
  • 我已经使
    if
    逻辑更加惯用

  • 不要像
    =
    那样传递运算符,而是传递一个函数,该函数将执行您要使用它们进行的测试。@GavinBrelstaff,谢谢。。。这将解决问题中较简单的那一半,albiet仍然没有我希望的那么简洁。如果你想传递一个不等式宏,你应该传递一个原子并将其用作
    apply(内核),:这看起来像我要找的。我会试试,谢谢!:-)
    
      defp select_previous_scheduled_price(scheduled_prices, date) do
        select_scheduled_price(scheduled_prices, date, >, &starts_before/2)
      end
    
      defp select_next_scheduled_price(scheduled_prices, date) do
        select_scheduled_price(scheduled_prices, date, >=, &starts_after/2)
      end
    
      defp select_scheduled_price(scheduled_prices, date, meets_length_criteria, filter_criteria) do
        if meets_length_criteria(scheduled_prices, 1) do
          qualified_prices = Enum.filter(scheduled_prices, &filter_criteria(&1, date))
    
          if !Enum.empty?(qualified_prices) do
            hd(qualified_prices)
          else
            nil
          end
        else
          nil
        end
      end
    
    defp select_previous_scheduled_price(scheduled_prices, date) do
      select_scheduled_price(scheduled_prices, date, &>/2, &starts_before/2)
    end
    
    defp select_next_scheduled_price(scheduled_prices, date) do
      select_scheduled_price(scheduled_prices, date, &>=/2, &starts_after/2)
    end
    
    defp select_scheduled_price(scheduled_prices, date, meets_length_criteria, filter_criteria) do
      if meets_length_criteria.(scheduled_prices, 1) do
        scheduled_prices
        |> Enum.filter(&filter_criteria.(&1, date))
        |> List.first()
      else
        nil
      end
    end