与构造函数相反的函数的正确术语是什么-从数据类型中解包值?


13

编辑:我改一下这个问题。显然,我引起了一些混乱,因为我没有意识到在OOP中使用析构函数一词是因为它们完全不同-它是在销毁对象时调用的函数。在函数式编程中,我们(尽量)避免发生可变状态,因此没有这种等效状态。(我在问题中添加了适当的标签。)

相反,我已经看到用于解开值的记录字段(尤其是用于newtypes的单值数据类型)有时称为destructordeconstructor。例如,让我们(在Haskell中):

newtype Wrap = Wrap { unwrap :: Int }

Wrap是构造函数,unwrap是什么?

问题是:

  • 我们如何unwrap在函数式编程中调用?解构器?破坏者?或其他术语?
  • 并澄清一下,这个/其他术语是否适用于其他功能语言,还是仅在Haskell中使用?
  • 或许,在非功能性语言中,对此是否有通用的术语

我看过两个词,例如:

...通常,一个人为这些提供聪明的构造函数和析构函数以简化与它们的合作。...

Haskell Wiki上,或

...这里的一般主题是融合构造函数- 像...这样的解构函数对

Haskell Wikibook上(这里的含义可能更笼统),或者

newtype DList a = DL { unDL :: [a] -> [a] }

该unDL功能是我们的解构,从而消除了DL构造。...

现实世界中的Haskell


3
析构
函数

3
这似乎是Haskell特有的(Haskell中的“析构函数”与C ++中的概念不同。名称相似性具有误导性)。如果要使用“解开值”的一般概念,则可能不应该以Haskell为例。在类似C ++的语言中,这样的“解包器”可能只是吸气剂!
Andres F.

1
我建议您从问题中删除“析构函数”一词,改用“解包器”,并询问是否存在跨语言的此模式的通用名称:)
Andres F.

1
.unapply,或“提取”是Scala一个粗略的模拟,但也许没有名字,因为在大多数情况下,你只是模式匹配
基因牛逼

Answers:


5

这个概念有几个术语。我认为,解构是Haskell圈子中的常见现象,这是真实世界中Haskell所说的。我相信在Lisp圈子中,“解构(或解构绑定)”一词很常见。


1
有趣的是,同一事物如何从一种语言到另一种语言获得不同的术语,例如在C#中地图变为select,haskell具有折叠lisp / java,reduce和ruby已注入,haskell具有绑定scala,具有平面图C#具有selectmany
Jimmy Hoffa

在Haskell圈子中,这确实称为解构。如果听起来很奇怪,请记住Haskell没有对象-只是值;因此,不用说该术语具有不同的含义。最重要的是,“解构”就是它所做的。关于这一点,我个人认为应该将对象解构函数称为对象处理程序。它要准确得多。
2014年

8

析构函数是C ++以及我不知道的其他语言使用的术语。它们用于释放由构造函数创建的资源,因此它们的作用恰恰相反。也许该概念并没有从字面上翻译为Haskell,但该术语似乎在某些地方使用。

编辑:考虑到您对问题的编辑,那么我将其称为“ unwrapper”。我能够回答原始问题,但是现在它已经超出了我的知识范围,因此请不要过于重视此编辑。


1
请注意,C ++ / C#/ Java对“析构函数”的使用与Haskell的不匹配。同一个词,不同的概念。
Andres F.

1
@AndresF。是的,这就是为什么我添加这句话的原因:Maybe in Haskell this does not translate really well but I don't know the language.
marco-fiset 2012年

1
公平地说,我删除了我的反对意见。我认为真正的问题是被误导了,这似乎是在问一件事,但实际上是在问另一件事!:)
Andres F.

@AndresF。是的,这个问题具有误导性。OP要求:What's the proper term for a function inverse to a constructor?。除非对问题进行编辑以使其更特定于某些Haskell概念,否则我将保持原样。
marco-fiset 2012年

1
请注意,C#具有终结器,但没有析构器,这是不同的,因为终结器具有不确定的执行。因此,也许编辑您的答案以免在C#中传播析构函数的误称。
Jimmy Hoffa

6

在OOP中,构造函数是创建或初始化新对象(“构造”对象)的函数或语言构造,而析构函数是其对偶,函数或语言构造,其在对象释放后清除(通过释放它的任何资源)。保留)并将其删除。

但是,由于Haskell(与C ++不同)具有垃圾回收并且不支持可变状态或其他副作用(至少不直接支持),因此从绝对意义上说,绝对没有理由使用析构函数。而且,与OOP构造函数不同,Haskell构造函数具有更多的应用程序,而不仅仅是对象创建。它们在模式匹配中也大量使用(请参阅下面的示例)。

在您的代码示例中,“ unwrap”是一个记录字段,根据使用方式的不同,我可能将其称为accessor,甚至可能称为getter(尽管后者也用于镜头环境中,所以它可能实际上有点混乱)。

我自己从未在Haskell上下文中使用过“析构函数”(或“析构函数”)一词。正如Andres F.指出的那样,它有时用于指代取消构造函数引入的包装的函数。据我了解,记录获取器可以充当析构函数,但是常规函数也可以充当析构函数,只要它们可以从更复杂的数据类型中获取值即可。例子包括maybeeither来自前奏。

请注意unwrap,在您的示例中,可能有几件事情:

  • 一个函数(就像其他函数一样):例如,您可以执行map unwrap [ Wrap 23, Wrap 42 ];这种用法大致相当于OOP中的getter方法。
  • 记录构造中的记录字段说明符: let w = Wrap { unwrap = 23 }
  • 记录字段说明在记录更新:let w' = w { unwrap = 23 }; 这类似于OOP中的setter方法(如果您挤压很多)。
  • 模式匹配中的记录字段说明符: f Wrap { unwrap = a } = a

最好将Haskell构造函数与OOP构造函数完全不同。我建议您(重新)读一本有关Haskell编程语言的好书,以更好地理解- “ Real World Haskell”确实很好,并且我听说过有关“ Learn You A Haskell”的好东西。两者都应该对构造函数有很好的解释,尤其是记录语法。


2
在Haskell社区中使用“析构函数”一词的证据:haskell.org/pipermail/beginners/2010-April/003946.htmlmail-archive.com/haskell-cafe@haskell.org/msg26463.html。Haskell术语中的“析构函数”是“解包器”,这是一个与内存管理或对象最终确定完全无关的概念。
Andres F.

3
我的论文导演专门在Haskell编程,也使用“析构函数”一词来表示展开。
Andres F.

好吧,我从来没有碰过这个词。完全正确的是,它在使用时与OOP中的析构函数概念完全无关。
tdammers 2012年

@AndresF .:编辑以纪念您的评论。
tdammers 2012年

@AndresF。这很有趣,因为我也从未听说过它被称为析构函数,尽管除此之外,将其仅称为记录字段也不太准确,而且我认为该技术称为“析构函数”只是一种模式匹配。 ?我知道当您的比赛将清单拉开时,这被称为“解构”,这也许是一个相关术语,但涉及到ADT?毕竟,解构列表只是作用在ADT上,因为列表就是这个。.我从stackoverflow.com/questions/11677806/…
Jimmy Hoffa,2012年

2

我认为析构函数是广义的术语。某些语言(例如Java和VB.NET)具有终结器。 /programming/171952/is-there-a-destructor-for-java


类似C ++语言的析构函数在释放分配的内存之前执行清除操作。Haskell中的析构函数从其“外层”解包一个值(您不使用它来清理任何内容)。它们不是真正相关的概念。
Andres F.

2
我想我没有意识到这是一个Haskel问题。
JeffO 2012年

确实不清楚。现在,这个问题已被重新标记并重新提出:)
Andres F.

2

由于似乎没有任何跨语言约定,所以我通常称它们为提取器,因为这是Scala用于该一般概念的术语,并且因为它不太可能与任何现有用法混淆。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.