【问题标题】:Assigned Anonymous Functions vs Named Function Declarations分配的匿名函数与命名函数声明
【发布时间】:2014-09-30 06:04:54
【问题描述】:

在开发函数式编程语言时,是否可以使指定的匿名函数表达式等同于命名函数声明/定义?

以这种伪语言为例:

add = \ x y -> x + y -- assigned anonymous function expression
add x y = x + y -- named function declaration

我知道在非函数式语言中,两者的属性有些不同,但我想问为什么它们不能相同?是编译器的问题吗?

例如,是否有语言可以在递归方面使上述 2 等价?所以我可以使用他们的名字和他们分配的标签进行递归?

factorial = \ n -> if n = 0 then 1 else n * factorial (n-1)
factorial n = if n = 0 then 1 else n * factorial (n-1)

另见:http://www.haskell.org/haskellwiki/Declaration_vs._expression_style

【问题讨论】:

  • 在哪些“非功能性”语言中是不同的,以及如何?您不能在哪种语言中使用factorial 定义中的任何一个?
  • JavaScript、PHP、Python、Ruby、Haskell...当然它们有语法上的差异,例如functiondef.. 等。
  • @CMCDragonkai:在 JavaScript、Python、Haskell 中,两者没有什么不同。在 Ruby 中,def 定义了方法,因此实际上没有定义“命名函数”的语法。
  • @newacct 你叫什么函数声明?我没有说“命名函数”,我澄清说是指“命名函数声明”。此外,定义方法在某种程度上等同于具有命名空间的函数声明,以及对命名空间的封闭式引用。
  • @CMCDragonkai:你说“例如在这种伪语言中:我知道在非函数式语言中,这两者有一些不同的属性”但对于你提到的几乎所有语言来说都是错误的。跨度>

标签: function functional-programming lambda lambda-calculus


【解决方案1】:

在开发函数式编程语言时,是否可以使指定的匿名函数表达式等同于命名函数声明/定义?

是的,假设您的语言支持命名 lambda 函数或用于在 lambda 函数内递归的构造。

我知道在非函数式语言中,两者的属性有些不同,但我想问为什么它们不能相同?是编译器的问题吗?

这取决于您所说的语言。

例如,是否有语言可以在递归方面使上述 2 等价?所以我可以使用他们的名字和他们分配的标签进行递归?

匿名函数和命名函数在递归方面是有区别的。许多函数式语言通过特殊构造解决了这个问题,允许您在自己的范围内命名匿名函数,以便它们能够调用自己。

例如,在 Clojure 中,您可以像以下表达式一样命名 lambda 函数:

(fn power [n e]
   (if (zero? e)
     1
     (* n (power n (dec e)))))

或在 JavaScript 中:

function power(n, e) {
  if (e === 0) {
    return 1;
  } else {
    return n * power(n, e - 1);
  }
}

这里,符号power 绑定在power 函数的环境中,而不是外部。这与在当前环境中定义函数不同 - 从而使符号 power 对其他人可见:

(defn power [n e]
   (if (zero? e)
     1
     (* n (power n (dec e)))))

或在 JavaScript 中:

var power = function (n, e) ...

但它们在数学上都是等价的函数。

【讨论】:

  • 我不确定我是否理解。但是在您回答的开头,您说它们可以等效。但是在底部你发现了一个警告,即命名函数声明可以很容易地递归,但分配的匿名函数不能不使用固定组合器。这是否意味着命名函数声明不仅仅是分配匿名函数的语法糖,而是实际上做了一些额外的事情(允许简单的递归)?
  • 您能否详细说明一下这个特殊结构?
  • @CMCDragonkai 我会在我的回答中详细说明。
  • 因此它们可以等效:如果语言支持 named 分配的匿名函数。但是,那为什么一种语言不能假设分配的匿名函数也是具有相同分配的 named 呢?
  • @CMCDragonkai 我建议您在弄清楚函数的语义、底层实现和类似的东西时专注于一种特定的语言。没有所有函数式语言都遵循的通用规则集。而js函数本身就是一整章。
【解决方案2】:

我对您的问题投了反对票,因为它包含非通用(私人?)术语和经过深思熟虑的想法,好像每个人都会像您一样思考。

例如:

是否有语言可以使上述 2 等价于 递归条款?所以我可以递归使用他们的名字和他们的 指定标签?

既然在某些语言中完全有可能它们已经(语义上但不是句法上)等价的,为什么还要“让它们等价”呢?所以更好的问题是:它们在哪些语言中是等价的?它们在其他语言中没有的地方有什么区别?

接下来,什么是“指定标签”?我猜这是你的私人术语,你知道它是如何工作的,并且你认为我们都分享这些想法。

让我告诉你,例如,在 Haskell 中,我们不“分配标签”。我们宁愿将名称绑定到值。我们以一种参照透明的方式来做到这一点。这基本上意味着:无论您写的是名称还是它所绑定的表达式。

【讨论】:

  • 感谢您教我正确的术语。
猜你喜欢
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 2011-12-29
  • 2010-09-14
相关资源
最近更新 更多