为什么Erlang if语句仅在其防护中支持特定功能? [英] Why does Erlang if statement support only specific functions in its guard?

查看:43
本文介绍了为什么Erlang if语句仅在其防护中支持特定功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么Erlang if 语句仅在其防护中支持特定功能?

Why does the Erlang if statement support only specific functions in its guard?

即-

ok(A) ->
  if
    whereis(abc)=:=undefined ->
            register(abc,A);
    true -> exit(already_registered)
  end.

在这种情况下,我们得到了非法警卫"错误.

In this case we get an "illegal guard" error.

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

What would be the best practice to use function's return values as conditions?

推荐答案

与其他编程语言一样,Erlang的 if 似乎具有限制性,实际上,对于大多数人来说,使用率不是很高选择使用 case .两者之间的区别在于,虽然 case 可以测试任何表达式,但是 if 仅可以使用有效的

Coming from other programming languages, Erlang's if seems strangely restrictive, and in fact, isn't used very much, with most people opting to use case instead. The distinction between the two is that while case can test any expression, if can only use valid Guard Expressions.

如上面链接中所述,保护表达式仅限于保证没有副作用的已知函数.造成这种情况的原因有很多,其中大多数归结为代码的可预测性和可检查性.例如,由于匹配是自上而下进行的,因此将执行不匹配的保护表达式,直到找到一个匹配的保护表达式为止.如果这些表达式有副作用,则在调试过程中很容易导致不可预测的结果.尽管您仍然可以使用 case 表达式来完成此操作,但是如果看到 if ,您可以知道,那么在没有该测试的情况下不会引入任何副作用需要检查.

As explained in the above link, Guard Expressions are limited to known functions that are guaranteed to be free of side-effects. There are a number of reasons for this, most of which boil down to code predictability and inspectability. For instance, since matching is done top-down, guard expressions that don't match will be executed until one is found that does. If those expressions had side-effects, it could easily lead to unpredictable and confusing outcomes during debugging. While you can still accomplish that with case expressions, if you see an if you can know there are no side effects being introduced in the test without needing to check.

最后但重要的一点是,守卫必须终止.如果不这样做,则函数调用的减少可能会永远持续下去,并且由于调度程序是基于减少的,因此这确实非常糟糕,而在情况恶化时几乎不会进行任何操作.

One last, but important thing, is that guards have to terminate. If they did not, the reduction of a function call could go on forever, and as the scheduler is based around reductions, that would be very bad indeed, with little to go on when things went badly.

作为一个反例,正是由于这个原因,您可以使Go中的调度程序饿死.因为Go的调度程序(像所有微处理调度程序一样)是协作式多任务的,所以它必须等待goroutine产生才能调度另一个调度程序.就像在Erlang中一样,它会在函数继续运行之前等待函数完成当前正在执行的操作.不同之处在于,Erlang没有类似循环的方式.要完成循环,您需要进行递归,这需要函数调用/缩减,并允许调度程序进行干预.在Go中,您具有C样式的循环,它们不需要在其体内调用函数,因此类似于{i = i + 1} 的的代码将使调度程序饿死.并不是说这样的循环在它们的主体中没有函数调用是非常普遍的,但是这个问题的确存在.

As a counter-example, you can starve the scheduler in Go for exactly this reason. Because Go's scheduler (like all micro-process schedulers) is co-operatively multitasked, it has to wait for a goroutine to yield before it can schedule another one. Much like in Erlang, it waits for a function to finish what it's currently doing before it can move on. The difference is that Erlang has no loop-alike. To accomplish looping, you recurse, which necessitates a function call/reduction, and allows a point for the scheduler to intervene. In Go, you have C-style loops, which do not require a function call in their body, so code akin to for { i = i+1 } will starve the scheduler. Not that such loops without function calls in their body are super-common, but this issue does exist.

相反,在Erlang中,如果不明确指定这样做的话,很难做到这一点.但是,如果守卫所包含的代码没有终止,它将变得微不足道.

On the contrary, in Erlang it's extremely difficult to do something like this without setting out to do so explicitly. But if guards contained code that didn't terminate, it would become trivial.

这篇关于为什么Erlang if语句仅在其防护中支持特定功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆