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