【发布时间】:2020-02-07 12:36:47
【问题描述】:
我是 trying to emulate 一种简单的函数式语言,它使用基于参与者的执行模型,其中出现了建模 if 表达式的问题。
现在的 Actor 系统基本上用于speeding up all kind of stuff,通过避免操作系统锁和停滞的线程或make microservices less painful,但最初它应该是一般的替代计算模型[1][2],当代的上面可能是propagation networks。所以这应该能够涵盖任何编程语言结构,当然还有if,对吧?
虽然我知道这偶尔会遇到麻烦,但我看到 one timid attempt 转向使用 akka actor 表示的递归算法(我对其进行了翻新并添加了 further examples,包括下面给出的那个)。这种尝试在函数调用中停止了,但为什么不更进一步,对操作符和 if 条件进行建模呢?事实上,smalltalk 语言应用了这个模型并产生了 actor 概念的前身,正如在下面接受的答案中所指出的那样。
令人惊讶的递归函数调用并不是什么大问题,但if1 是,因为它具有潜在的状态性质。
鉴于子句C: if a then x else y,问题出在:
我最初的想法是,C 是一个行为者,其行为类似于具有 3 个参数 (a,x,y) 的函数,它返回 x 或 y,具体取决于 a。最大并行 [2] a,x 和 y 将同时评估并作为消息传递给 C。现在,这不是很好,如果C 是递归函数f 的退出条件,则在无限递归中发送f 的一个分支。此外,如果x 或y 有副作用,则不能只评估它们。让我们取这个递归和(这不是通常的阶乘,很愚蠢,可以做成尾递归,但这不是重点)
f(n) = if n <= 0
0
else
n + f(n -1)
请注意,我想创建一个类似于 Scala 的 if 表达式,请参阅 (spec, p. 88) 或 Haskell,就此而言,而不是依赖于的 if 语句副作用。
f(0) 会导致 3 个并发评估
-
n <= 0(好的) -
0(好的) -
n + f(n -1)(糟糕,引入了对 f(n) 的调用实际上会返回(产生 0)但对其分支的评估会无限继续的奇怪行为)
我可以从这里看到这些选项:
-
整个计算变成有状态的,
x的评估 或y仅在计算a之后发生(如果 x 或 y 有副作用,则为强制性)。 -
引入了一些保护机制,不会呈现
x或y适用于调用f时超出一定范围的参数。他们可能会评估一些“不适用”的标记而不是一个值,因为它来自一个不相关的分支,所以无论如何都不会在C中使用。
在这一点上我不确定,如果我没有从根本上错过这个问题,而且还有其他明显的方法,我只是看不到。输入赞赏:)
顺便说一句。请参阅this 以获取不同语言中条件分支的详尽列表,但未给出其语义,以及wiki page on conditionals(带有语义)和this 以讨论手头的问题如何成为一个问题到硬件级别。
1 我知道if 可以被视为模式匹配的一种特殊情况,但问题是,如何使用actors 对匹配表达式的不同情况进行建模。但也许这甚至不是一开始就打算的,匹配只是每个演员都可以做的事情,而无需参考其他专业的“比赛演员”。另一方面,有人说“一切都是演员”,相当混乱[2]。顺便提一句。有没有人清楚地知道[#message whatever] 符号在该论文中的含义是什么? # 令人恼火地未定义。也许 smalltak 给出了提示,那里表示a symbol。
【问题讨论】:
-
您的阶乘实现是有状态的,因为递归调用没有位于尾部(因为一旦
f(n-1)返回,您仍然需要添加一些内容)。我认为这是一个基本问题,在 FP 或命令式实现中也是如此。使累积递归函数 TCO 感知的技术可能会有所帮助。 (将累加器作为额外参数) -
我知道这可以是尾递归的,这与递归或总和无关,它与“if”的实现有关。它甚至不是阶乘,这是一个愚蠢的总和;)
-
你能在这里与 Prolog 的
occurs_check问题做一个平行吗?我认为 if 分支的并行计算是一个问题本身,特别是如果您希望您的if成为递归函数中的保护条件。同时执行两个分支并最终选择结果的目的是通过实际做更多的工作来提前完成。但是递归保护的目的实际上是防止代码搜索不存在的东西。 (你的第二个分支实际上是这样做的) -
Laurent,我知道我不能做并行计算(这是一种选择),它可能没有实用的目标,但问题的一部分是,面对Hewitt ea 对参与者系统的初步提议进一步鼓励了它不过,感谢发生检查提示。而对于守卫方法的投票,是隐含的,还是你没有?
-
老实说,我无法为您提供任何进一步的信息,我只是模糊地了解演员模型 :) 我在以前的 cmets 中想说的关键:有一个命令式
if中的基本问题:它用于两种不同的事情-实际上是分支和保护recusion。但是命令式编程通过在其语义中不执行两个分支而摆脱了它(不匹配分支的副作用不应出现在后状态中)我会投票支持有状态的解决方案f 出现在其中一个分支中,第二个出现在其他情况下。
标签: scala parallel-processing functional-programming akka actor