我开始学习javascript的函数式编程。这可能是一个愚蠢的问题,但我试图解决以函数式方式编写的非纯函数。
我的问题是,在函数式编程范式中应该使用什么策略来实现这一点。
const crypto = require('crypto');
const encrypt = (data, publicKey) => {
if (publicKey === undefined ) throw 'Missing public key.';
const bufferToEncrypt = Buffer.from(data);
const encrypted = crypto.publicEncrypt({
key: publicKey
}, bufferToEncrypt);
return encrypted;
};
成为纯函数有两个标准。
纯函数准则 1:调用具有相同值的函数必须始终产生相同的返回值
这在执行非对称加密时是不可能的,因为每个操作都会生成一个随机会话密钥。 会话密钥使用公钥加密,然后使用会话密钥加密有效负载。 返回值通常只是两个值的编码版本:(1( 公钥加密的会话密钥和 (2( 会话密钥加密的有效负载。
每次调用函数时,这两个值都会不同,因为会话密钥每次都会不同。
然而,尽管返回值没有相等,但我认为它们在语义上是相等的——也就是说,如果你使用匹配的私钥解密每个值,解密的值将相等。
加密有效地混淆了值是否相等,对于加密来说,这是一件好事。我们不希望在没有解密密钥的情况下比较在不同时间生成的两条加密消息。 这将是一个安全风险。
因此,我认为这个函数在语义上符合这个标准,但如果没有公钥我们就无法分辨。
纯函数准则2:函数没有可观察到的副作用
这一点应该相当明显:写入磁盘是一种副作用,写入全局变量是一种副作用,等等。 我们应该无法区分调用函数之前和之后的状态差异。
从技术上讲,会话密钥的生成需要使用系统的安全随机数生成器。 这将消耗一些熵。 运行函数后,可用的熵将更少,并且可以测量。
但是,我认为可以忽略这种副作用,因为任何需要安全随机数的东西都会有同样的问题,这更多的是安全随机数生成器的实现细节。
这就像声称需要大量 CPU 时间的函数具有副作用,因为运行它会增加进程的 CPU 时间计数器。 是副作用吗? 技术。。。或? 但是没有一个理性的人会认为这是一种副作用。
结论
我将这个函数称为"语义纯"。 如果你问我这是否是一个纯粹的函数,并且只接受一个没有限定的是/否答案,我会告诉你"是"。