为什么erlang中的if语句只支持其中的某些特定功能?
即 -
ok(A) ->
if
whereis(abc)=:=undefined ->
register(abc,A);
true -> exit(already_registered)
end.
在这种情况下,我们得到了#34;非法警卫"错误。
将函数的返回值用作条件的最佳做法是什么。
答案 0 :(得分:2)
请检查此问题:About the usage of "if" in Erlang language
简而言之:
保护序列中只允许有限数量的功能,而whereis不是其中之一
改为使用func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as? UserTableViewCell;
cell?.view(with: users[indexPath.row]);
return cell!;
}
。
答案 1 :(得分:0)
来自其他编程语言,Erlang的if
似乎有着极其严格的限制,事实上,它并没有被广泛使用,大多数人选择使用case
。两者之间的区别在于虽然case
可以测试任何表达式,但if
只能使用有效的Guard Expressions。
正如上面的链接所解释的,Guard表达式仅限于保证没有副作用的已知功能。造成这种情况的原因有很多,其中大部分归结为代码可预测性和可检查性。例如,由于匹配是自上而下完成的,因此将执行不匹配的保护表达式,直到找到一个匹配。如果这些表达具有副作用,则在调试期间很容易导致不可预测和混乱的结果。虽然您仍然可以使用case
表达式完成此操作,但如果您看到if
可以知道,则无需检查即可在测试中引入任何副作用。
最后,但重要的是,警卫必须终止。如果他们没有,那么函数调用的减少可以永远持续下去,并且由于调度程序基于减少,这确实是非常糟糕的,当事情变得糟糕时几乎不会继续。
作为一个反例,您可以将Go中的调度程序饿死,原因正是如此。因为Go的调度程序(与所有微进程调度程序一样)是协同操作的多任务,所以它必须等待goroutine在它可以调度另一个之前产生。就像在Erlang中一样,它等待一个功能来完成它目前正在做的事情,然后才能继续前进。不同之处在于Erlang没有类似循环的东西。要完成循环,需要进行函数调用/缩减,并允许调度程序进行干预。在Go中,你有C风格的循环,它们的体内不需要函数调用,因此类似for { i = i+1 }
的代码会使调度程序饿死。不是没有在他们体内没有函数调用的这种循环是超常见的,但这个问题确实存在。
相反,在Erlang中,如果不明确地这样做,就很难做到这样的事情。但是如果守卫包含的代码没有终止,那么它就会变得微不足道。