javascript - 纯函数可以返回 Symbol 吗?

标签 javascript referential-transparency

这可能有点哲学意义,但我认为这是提问的正确地点。

假设我有一个创建 ID 列表的函数。这些标识符仅在应用程序内部使用,因此可以在此处使用 ES2015 Symbol()

我的问题是,技术上,当你请求一个 Symbol 时,我想 JS 运行时会创建一个唯一标识符(随机数?内存地址?不确定),为了防止冲突,需要访问全局状态。我不确定的原因是因为“技术上”这个词。我不确定(同样,从哲学的 Angular 来看)这是否足以打破 API 呈现的数学抽象。

tl;dr:这是一个例子——

function sentinelToSymbol(x) {
  if (x === -1) return Symbol();
  return x;
}

这个函数是纯函数吗?

最佳答案

不是真的,不是,但实际上可能并不重要。

从表面上看,(foo) => Symbol(foo) 看起来很纯粹。虽然运行时可能执行一些有副作用的操作,但您永远不会看到它们,即使您同时使用相同的参数调用Symbol()。但是,使用相同的参数调用 Symbol 永远不会返回相同的值,这是主要标准之一(下面的#2)。

来自 the MDN page :

Note that Symbol("foo") does not coerce the string "foo" into a symbol. It creates a new symbol each time:

Symbol("foo") === Symbol("foo"); // false

只看副作用,(foo) => Symbol(foo) 是纯的(在运行时之上)。

但是,纯函数必须满足更多条件。 From Wikipedia :

Purely functional functions (or expressions) have no side effects (memory or I/O). This means that pure functions have several useful properties, many of which can be used to optimize the code:

  • If the result of a pure expression is not used, it can be removed without affecting other expressions.
  • If a pure function is called with arguments that cause no side-effects, the result is constant with respect to that argument list (sometimes called referential transparency), i.e. if the pure function is again called with the same arguments, the same result will be returned (this can enable caching optimizations such as memoization).
  • If there is no data dependency between two pure expressions, then their order can be reversed, or they can be performed in parallel and they cannot interfere with one another (in other terms, the evaluation of any pure expression is thread-safe).
  • If the entire language does not allow side-effects, then any evaluation strategy can be used; this gives the compiler freedom to reorder or combine the evaluation of expressions in a program (for example, using deforestation).

您可能会争辩说该列表的前言排除了 JavaScript 中的一切,因为任何操作都可能导致分配内存、更新内部结构等。在最严格的解释中,JS 永远不是纯粹的.这不是很有趣或有用,所以...

此功能符合标准#1。忽略结果,(foo) => Symbol(foo)(foo) => () 与任何外部观察者都是相同的。

标准 #2 给我们带来了更多麻烦。给定 bar = (foo) => Symbol(foo)bar('xyz') !== bar('xyz'),所以 Symbol code> 根本不满足该要求。每次调用 Symbol 时,您都可以保证获得一个唯一的实例。

继续前进,条件 #3 没有问题。您可以从不同的线程调用 Symbol 而不会发生冲突(并行),并且它们的调用顺序无关紧要。

最后,标准 #4 与其说是直接要求,不如说是一个注释,而且很容易满足(JS 运行时会随机播放所有内容)。

因此:

  • 严格来说,JS中没有什么是纯粹的。
  • Symbol() 绝对不是纯粹的,因此示例也不是。
  • 如果您只关心副作用而不是内存,那么该示例确实符合这些标准。

关于javascript - 纯函数可以返回 Symbol 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38705646/

相关文章:

haskell - 如果你编译一个没有输入的程序会发生什么? (Haskell IO 纯度问题(再次))

Haskell - 如何在 IO 函数中使用纯函数?

javascript - HTML5、CSS3 和/或 JS 中旋转 CD 上的音频播放器

javascript - 如何以表单安全地显示用户的服务器端数据?

javascript - 如何使用如图所示的相同表创建 url

javascript - 数据表.row()未定义

javascript - 在 Javascript 中定义一个带有命名空间的类

scala - 猫效应 IO monad 是如何真正起作用的?

data-structures - 是否有双向多映射持久数据结构?

clojure - 我们可以考虑 Clojure 的 STM 'functional' 吗?