为什么Erlang if语句只支持其保护中的特定函数?

为什么Erlang if语句只支持其保护中的特定函数?,erlang,Erlang,为什么Erlangif语句只支持其保护中的特定函数 i、 e- 在这种情况下,我们得到一个“非法守卫”错误 使用函数返回值作为条件的最佳实践是什么?检查此问题: 简言之: 在保护序列中只允许有限数量的函数,where不是其中之一 改用案例。检查此问题: 简言之: 在保护序列中只允许有限数量的函数,where不是其中之一 改为使用case。来自其他编程语言,Erlang的if似乎有着奇怪的限制性,事实上,使用得不多,大多数人选择使用case。两者之间的区别在于,case可以测试任何表达式,if只能

为什么Erlang
if
语句只支持其保护中的特定函数

i、 e-

在这种情况下,我们得到一个“非法守卫”错误

使用函数返回值作为条件的最佳实践是什么?

检查此问题:

简言之:

在保护序列中只允许有限数量的函数,where不是其中之一

改用
案例

检查此问题:

简言之:

在保护序列中只允许有限数量的函数,where不是其中之一


改为使用
case

来自其他编程语言,Erlang的
if
似乎有着奇怪的限制性,事实上,使用得不多,大多数人选择使用
case
。两者之间的区别在于,
case
可以测试任何表达式,
if
只能使用valid

如上链接所述,保护表达式仅限于保证无副作用的已知函数。原因有很多,其中大部分归结为代码的可预测性和可检查性。例如,由于匹配是自上而下进行的,所以将执行不匹配的保护表达式,直到找到一个匹配的表达式。如果这些表达式有副作用,那么在调试过程中很容易导致不可预测和混乱的结果。虽然您仍然可以使用
case
表达式来实现这一点,但是如果您看到
if
,您可以知道测试中没有引入任何副作用,而无需进行检查

最后,但重要的是,警卫必须终止。如果他们不这样做,函数调用的缩减可能会永远持续下去,而由于调度器是基于缩减的,这将是非常糟糕的,当事情变得糟糕时,几乎没有什么可以继续

作为一个反例,正是由于这个原因,您可以在Go中饿死调度程序。因为Go的调度器(和所有微进程调度器一样)是协作多任务的,所以它必须等待goroutine产生,然后才能调度另一个goroutine。与Erlang非常相似,它等待函数完成当前正在做的事情,然后才能继续。区别在于Erlang没有类似的循环。要完成循环,需要递归,这需要函数调用/缩减,并允许调度器进行干预。在Go中,您有C风格的循环,它不需要在其主体中调用函数,因此类似于{i=i+1}的代码将使调度程序无法运行。并不是说这样的循环体中没有函数调用是非常常见的,但是这个问题确实存在


相反,在Erlang中,如果不明确地开始这样做,就很难做到这一点。但是,如果guards包含的代码没有终止,那么它就变得微不足道了。

来自其他编程语言,Erlang的
if
似乎有着奇怪的限制性,事实上,它的使用并不多,大多数人选择使用
case
。两者之间的区别在于,
case
可以测试任何表达式,
if
只能使用valid

如上链接所述,保护表达式仅限于保证无副作用的已知函数。原因有很多,其中大部分归结为代码的可预测性和可检查性。例如,由于匹配是自上而下进行的,所以将执行不匹配的保护表达式,直到找到一个匹配的表达式。如果这些表达式有副作用,那么在调试过程中很容易导致不可预测和混乱的结果。虽然您仍然可以使用
case
表达式来实现这一点,但是如果您看到
if
,您可以知道测试中没有引入任何副作用,而无需进行检查

最后,但重要的是,警卫必须终止。如果他们不这样做,函数调用的缩减可能会永远持续下去,而由于调度器是基于缩减的,这将是非常糟糕的,当事情变得糟糕时,几乎没有什么可以继续

作为一个反例,正是由于这个原因,您可以在Go中饿死调度程序。因为Go的调度器(和所有微进程调度器一样)是协作多任务的,所以它必须等待goroutine产生,然后才能调度另一个goroutine。与Erlang非常相似,它等待函数完成当前正在做的事情,然后才能继续。区别在于Erlang没有类似的循环。要完成循环,需要递归,这需要函数调用/缩减,并允许调度器进行干预。在Go中,您有C风格的循环,它不需要在其主体中调用函数,因此类似于{i=i+1}的代码将使调度程序无法运行。并不是说这样的循环体中没有函数调用是非常常见的,但是这个问题确实存在


相反,在Erlang中,如果不明确地开始这样做,就很难做到这一点。但是,如果警卫包含没有终止的代码,它将变得微不足道。

我总是喜欢
案例
而不是
如果
。我总是喜欢
案例
而不是
如果
“如果你看到一个“如果”,你就可以知道测试中没有引入任何副作用,而无需检查。”--你所说的副作用是什么意思,测试?是指测试/保护条件?意味着由保护子句调用的函数是“纯”的,或者换句话说,它可以通过逻辑替换其计算结果,而不改变程序的运行方式。产生副作用的函数有“!”操作符、写入文件系统等。“如果你看到一个“如果”,你不需要检查就可以知道测试中没有引入副作用。”--你怎么办
ok(A) ->
  if
    whereis(abc)=:=undefined ->
            register(abc,A);
    true -> exit(already_registered)
  end.