【问题标题】:Is Erlang "single assignment" different from Haskell "immutable values"?Erlang“单一赋值”与Haskell“不可变值”不同吗?
【发布时间】:2012-03-17 19:36:13
【问题描述】:

在“Programming Erlang”一书中,据说该语言使用“单一赋值”变量。在其他关于函数式编程语言的文章中,我总是读到“不可变值”。

“单一赋值”一词与“不可变值”有什么不同吗?

【问题讨论】:

  • 好的,我了解技术上的“单一赋值”与“不可变值”不同。 IE。在 Java 中,我们可以有指向可变对象的最终变量和指向不可变对象的非最终(可重新分配)变量。但是......在我看来,能够同时使用这两者似乎是一种危险的组合。这基本上就是为什么我要问是否有重点关注 Erlang 中的单一赋值而不是不变性。据我所知,Erlang 数据结构是不可变的,绑定的“变量”总是只指向一个。这就像 Haskell,不是吗?

标签: haskell functional-programming erlang


【解决方案1】:

在 erlang 中,变量可以是绑定的,也可以是未绑定的。您只能为未绑定的变量赋值。这就是单一赋值的来源,因为一旦绑定了变量,就不能再给它赋值。因此,在 erlang 中,您不能执行以下操作,即使 01 是不可变值。

X = 1.
X = 2. // This is not a valid operation

术语不可变是相对于变量的值,而不是变量本身。因此,在某些语言中,您可以为同一个变量分配不可变的不同值:

X = immutableValue;
X = anotherImutableValue; // This is a valid operation

编辑:来自维基百科

Immutable Object:

在面向对象和函数式编程中,不可变对象是其状态在创建后无法修改的对象。

Single Assignment:

单次赋值是名称绑定的一个例子,与本文中描述的赋值不同,只能完成一次,通常是在创建变量时; 不允许后续重新分配。 [...] 一旦通过单次赋值创建,命名值就不是变量而是不可变对象。

【讨论】:

  • 如果我没记错的话,Erlang 也使用单个= 进行相等性测试,这也与此有关。在 Haskell 中,单个=用于赋值,而== 用于相等性测试。
  • 在 Erlang 中,= 是一个模式匹配运算符。当变量未绑定时,它的行为类似于赋值。 =:=== 用于相等性测试。
【解决方案2】:

差异与(重新)绑定变量和改变值之间的差异有关。

“单一赋值”是指,你不能重新绑定具有不同值的变量,例如:

1> A = 1.
2> A = 2.
** exception error: no match of right hand side value 2

另一方面,“不可变值”意味着您不能更改 本身(例如,从并行线程中),因此如果要修改列表,则必须制作副本或语义等价的东西,而不是就地更改。

【讨论】:

    【解决方案3】:

    Haskell 程序员报告。是的,“单一赋值”和“不可变值”都是完全相同的东西。 Haskell 更深入地理解了这个概念:一切的值都是在编译时定义的。是的,一切。

    然后您可能会问这是怎么可能的,因为 Haskell 可以清楚地执行 I/O。答案是,当您定义从外部世界提取输入的操作时,您并没有定义值,而只是定义了提取它的操作。您永远不会明确定义绑定的值。在 Haskell 中,当您执行以下操作时:

    echo = forever $ do
        x <- getLine
        putStrLn x
    

    您不是在“定义”x,而只是告诉 getLine 和 putStrLn 如何交互。你真正定义的唯一东西是echo,它只不过是一个等待运行的动作。很明显,echo 的行为是在编译时定义的,而 x 的值不是。

    也许你已经知道了,但我写这篇文章也是为了其他对 Haskell 与 Erlang 有类似疑问的人。

    【讨论】:

    • 这两个概念不是一回事 - 请参阅 sch 的解释。
    【解决方案4】:

    嗯,Haskell 是引用透明的。这意味着“变量”是数学意义上的变量。 “分配给变量”的唯一概念在 Haskell 中没有意义,因为名称和它所代表的值之间没有语义差异。换句话说,等号(=)确实引入了一个等式。

    在这个概念中,每个值自然是不可变的,当您定义x = 3 时,x3 之间没有区别。正如方程式所说,它们是完全相同的。

    【讨论】:

    • 不回答问题。这与单一分配有何关系?
    • 在实践中与 Erlang 的 X = 3 有什么区别?在语句 X 之后总是 3,不是吗?
    【解决方案5】:

    我完全不懂 Erlang,所以我可能无法给出最佳答案。

    在 Haskell 中,您不会将程序编写为要评估的一系列步骤。相反,您定义了一组方程。因此,没有出现“分配”的概念。当我在 Haskell 中编写 x = 1 时,这不是将名称 x 绑定到值 1 的指令,而是声明 x 1。

    在 Erlang 中,除了赋值之外,你可以对未绑定的变量做任何事情吗?即使是一个测试变量是否绑定的构造也会使 Erlang 的单一赋值与 Haskell 的变量概念完全不同。就此而言,如果您甚至可以尝试读取一个未绑定的变量并让它抛出一个您可以捕获的异常,那将使 Erlang 的单一赋值完全不同。

    同样,这是因为 Haskell 根本没有赋值的概念。分配是在某个时间点发生的一个步骤。在赋值之前的世界中,变量具有其旧值或未绑定,而在赋值之后的世界中,变量具有其新值。每个世界都是有效的,在每个世界中执行更多的步骤可能会产生不同的结果。

    在 Haskell 中,当我提到 x 时,x 在范围内并已定义,在这种情况下它有一个值,或者不在范围内,在这种情况下,我什至没有编写 Haskell 程序并且编译器会拒绝它。没有前后之分。

    鉴于谷歌搜索向我表明在 Erlang 中变量可以再次解除绑定,我会说它们是完全不同的概念。

    【讨论】:

    • 谢谢,它让我们了解了两种语言之间可能存在的差异。
    • good news: «当您“解除绑定”该值时,您可以再次重新绑定它。 不用说它只适用于 Erlang shell。»(强调我的)。所以它是shell 操作的一部分,而不是语言本身的一部分。 (我不知道 Erlang,只知道 Haskell 和 Prolog)。
    • 在 Prolog 中,我们实际上有“一个测试变量是否绑定的构造”:如果 A 未绑定,var(A) 成功,否则失败。
    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    相关资源
    最近更新 更多