我试着去检查一个情况下,如果一个列表是空的,而随后recursivly捕捉模式时,它是,这是在二郎山去还是我正走在错误的道路和模式匹配赶上如果最好的办法正道名单已被清空或不?
calculate([Head|Tail], pi, x, y) ->
...calculations of Head being sent to a list...
case Tail == [] of
false ->
calculate(Tail, pi, x, y)
end.
或者应该算我只是模式匹配,如果该列表是空的?
错误代码
一般的做法是使用功能子句与模式匹配。 它的工作原理就像情况下,它被认为是更可读。 同时,修复你在执行有一个错误:
首先所有的代码可能会以这种方式被改写。
calculate([Head|Tail], pi, x, y) ->
%% ... actual calculations ...
calculate( Tail, pi, x, y);
calculate([], pi, x, y) ->
%% you need to return something here, but you don't
正如你所看到的,条款中的一项不返回任何东西,这是不是在二郎山(编译过程中失败)允许的。 你的实现不正是同样的事情。 case
就像在二郎事情必须返回一些值(并且由于它是激射声明在函数这个值将从函数返回)。 此外,由于case
需要返回的东西,它需要匹配它的条款之一。 它大多数情况下,由于Tail == []
会返回false
它不会是一个问题。 但在最后的递归调用,当Tail
是空单, Tail == []
会返回true
和case
将不匹配任何东西。 而在二郎这将导致(投掷,或退出是精确的) case_clause
错误。 所以您的实现总是会失败。
要解决它,你需要确保你总是有东西在匹配你的情况下,这样的
case Tail == [] of
false ->
calculate(Tail, pi, x, y)
true ->
%% return something
end.
或者,它可能这样写
case Tail of
[] ->
%% return something sane
_ ->
calculate(Tail, pi, x, y)
end.
其中_
将匹配任何东西,并且将工作有点像else
一些其他语言。 最后它可能与功能条款被写入,就像我之前表现,但这种理智的返回值。
编辑
返回值
如果你看一下我们的代码莱特我们现在只返回一个值接近; 从去年递归调用的一个(一个我所谓的“理智”)。 如果你想利用帐户下所有的递归调用所有的计算,你需要以某种方式积累他们。 而要做到这一点,我们将使用Acc
变量
calculate([Head|Tail], pi, x, y, Acc) ->
%% ... actual calculations with result assigned to Res variable ...
NewAcc = [Res | Acc]
calculate(Tail, pi, x, y, NewAcc);
calculate([], pi, x, y, Acc) ->
Acc.
在每次递归调用我们增加我们的计算Res
累加器Acc
,并发送该更新的列表,以递归的一个新的水平。 最后,当我们的输入列表是空的(我们处理的所有数据),我们刚刚返回整个蓄电池。 所有我们需要做的,就是确保,当calculate
被称为第一,它被称为空列表作为Acc
。 这可以通过新的(有点老)函数来完成
calculate(List, pi, x, y) ->
calculate(List, pi, x, y, _Acc = []).
现在,我们可以导出calculate/4
和保持calculate/5
私有。
模式匹配。 它的正确的事情。
它也更有效。 它还可以防止你来自发展中国家的只是接受任何类型的变量前面,通过你的函数会中途,发现你已经收到什么习惯甚至不是一个列表(哎呀!)。 模式匹配(使用某些类型的后卫),也是中央对透析方式成功检查分型的 - 这可能是或不是怎么了你的权利,但肯定会一旦你开始对之类的软件有客户合作。
最重要的是,学习采取的模式匹配的优势,教你写的小功能 。 写一个巨大的功能与bajillion参数,可以做一切当然是可能的,而且在许多其他语言中也很常见,但模式匹配将说明你为什么这个只要你开始写你的对手的情况下是一个坏主意。 这将帮助你的方法,我甚至不能开始描述; 它会渗入你如何看待没有你在第一次欣赏它的程序; 这将削减无关的信息嵌套条件(因为他们不存在); 它会教你停止编写的参数错误校验码无处不在 。
添加一个子句空列表,如果没有可能,用一个单一的元素列表:
func([H],P,X,Y) ->
do_something(H,P,X,Y);
func([H|T],P,X,Y) ->
do_something(H,P,X,Y),
func(T,P,X,Y).
请注意,这将失败,一个空的输入列表。
也看看,如果你能使用的功能列表中的一个:地图/ 2或列表:与foldl / 3或列表理解...