Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 纯函数能否返回符号?_Javascript_Referential Transparency - Fatal编程技术网

Javascript 纯函数能否返回符号?

Javascript 纯函数能否返回符号?,javascript,referential-transparency,Javascript,Referential Transparency,这可能接近于哲学,但我认为这将是一个正确的问题 假设我有一个创建ID列表的函数。这些标识符仅在应用程序内部使用,因此可以在此处使用ES2015Symbol() 我的问题是,从技术上讲,当你要求一个符号时,我会想象JS运行时会创建一个唯一的标识符(随机数?内存地址?不确定),为了防止冲突,需要访问全局状态。我不确定的原因是因为“技术上”这个词。我不确定(从哲学的角度来看)这是否足以打破API所呈现的数学抽象 tl;dr:下面是一个例子-- 这个函数是纯函数吗?不是真的,不是,但它实际上可能并不重要

这可能接近于哲学,但我认为这将是一个正确的问题

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

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

tl;dr:下面是一个例子--


这个函数是纯函数吗?

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

在表面上,
(foo)=>Symbol(foo)
看起来很纯净。虽然运行时可能会执行一些具有副作用的操作,但即使同时使用相同的参数调用
Symbol()
,也永远看不到这些操作。但是,使用相同的参数调用
Symbol
将永远不会返回相同的值,这是主要标准之一(见下文第2条)

发件人:

请注意,符号(“foo”)不会强制字符串“foo”成为符号。它每次都会创建一个新符号:

Symbol("foo") === Symbol("foo"); // false
仅从副作用来看,
(foo)=>Symbol(foo)
是纯的(在运行时之上)

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

纯功能函数(或表达式)没有副作用(内存或I/O)。这意味着纯函数有几个有用的属性,其中许多属性可用于优化代码:

  • 如果未使用纯表达式的结果,则可以在不影响其他表达式的情况下删除该结果
  • 如果使用不会产生副作用的参数调用纯函数,则结果相对于该参数列表是恒定的(有时称为引用透明),即如果使用相同的参数再次调用纯函数,则将返回相同的结果(这可以启用缓存优化,如记忆)
  • 如果两个纯表达式之间没有数据依赖关系,那么它们的顺序可以颠倒,或者可以并行执行,并且它们不能相互干扰(换句话说,任何纯表达式的计算都是线程安全的)
  • 如果整个语言不允许副作用,那么可以使用任何评估策略;这使编译器可以自由地对程序中表达式的计算进行重新排序或组合(例如,使用)
您可能会争辩说,该列表的前言排除了JavaScript中的所有内容,因为任何操作都可能导致内存分配、内部结构更新等。最严格的解释是,JS从来都不是纯粹的。这不是很有趣或有用,所以

此功能符合标准#1。不管结果如何,
(foo)=>Symbol(foo)
(foo)=>()
与任何外部观察者相同

标准2给我们带来了更多麻烦。给定
bar=(foo)=>Symbol(foo)
bar('xyz')!=条形('xyz')
,因此
符号
根本不符合该要求。每次调用
Symbol
时,您都会得到一个唯一的实例

接下来,标准3不会带来任何问题。您可以从不同的线程调用
Symbol
,而不会产生冲突(并行),而且调用顺序也不重要

最后,标准#4更像是一个注释,而不是直接的需求,并且很容易满足(JS运行时会在运行时洗牌)

因此:

  • 严格地说,JS中没有任何东西是纯粹的
  • Symbol()
    
  • 如果您所关心的只是副作用而不是记忆,那么这个示例确实符合这些标准

是的,此函数不纯净:
sentinelToSymbol(-1)!=哨兵符号(-1)
。对于纯函数,我们期望这里的等式

然而,如果我们在具有对象标识的语言中使用引用透明性的概念,我们可能需要稍微放宽定义。如果考虑<代码>函数x(){Real[];},它是纯的吗?显然
x()!==x()
,但无论输入如何,函数始终返回空数组,就像常量函数一样。因此,我们必须在这里定义的是我们语言中的价值平等。<代码>==< /代码>运算符可能不是最适合这里的(只考虑<代码>楠< /代码>)。如果数组包含相同的元素,数组是否彼此相等?可能是的,除非它们在某个地方发生了变异

所以你现在必须为你的符号回答同样的问题。符号是不可变的,这使得这一部分变得容易。现在我们可以通过它们的[ [描述] ]值(或<代码> toScript()/代码>来考虑它们相等,因此<代码> StimeLeToSyMyBOL</代码>将是纯的。
但是大多数语言都有允许破坏引用透明性的函数——例如,请参阅。在JavaScript中,这将在其他相等的对象上使用
=
。它将使用符号作为属性,因为这样可以检查它们的身份。因此,如果您在程序中不使用此类操作(或至少在外部无法观察到的情况下),您可以声称您的函数是纯净的,并使用它来重新了解您的程序。

这太完美了,谢谢!按照同样的思路,任何返回值而不是字符串、数字或布尔值的东西都不能是纯的,对吗?给定
f(x)=>({value:x})
f(5)!=f(5)
@RyanKennedy:是的,但“这不是很有趣或有用,所以…”…我们通常会改变规则。@RyanKennedy,当您在具有重复数据消除功能的VM上时
Symbol("foo") === Symbol("foo"); // false