简体   繁体   English

这可以被认为是一个纯函数(函数式编程)吗?

[英]Can this be considered a pure function (functional programming)?

I've been reading about functional programming and its concepts. 我一直在阅读函数式编程及其概念。 It's clear to me that when working in big projects you always need to mix (at some adequate level) multiple paradigms such as OO and functional. 我很清楚,在大项目中工作时,你总是需要混合(在某种程度上)多种范例,如OO和功能。 In theory, concepts such as function purity are too strict such as 从理论上讲,功能纯度等概念太严格了

The function always evaluates the same result value given the same argument value(s). 在给定相同参数值的情况下,该函数始终评估相同的结果值。 The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices. 功能结果值不能取决于程序执行过程中或程序的不同执行之间可能发生变化的任何隐藏信息或状态,也不依赖于I / O设备的任何外部输入。 ( https://en.wikipedia.org/wiki/Pure_function ) https://en.wikipedia.org/wiki/Pure_function

That said, is this (or can be considered) code a pure function? 那就是说,这个(或者可以认为)代码是一个纯函数吗?

const externalVar = 10;

function timesTen(value) {
    return externalVar * value;
}

I'm asking this because, in this case, the timesTen function will always return the same value for an input, and anyone can change the value of externalVar as this is a constant. 我问这个是因为,在这种情况下, timesTen函数将始终为输入返回相同的值,任何人都可以更改externalVar的值,因为这是一个常量。 However, this code breaks the rule of accessing external function's scope. 但是,此代码违反了访问外部函数范围的规则。

Yes. 是。 It is guaranteed to be pure. 它保证是纯净的。

The reason is that it only depends on bound and immutable free variables. 原因是它只依赖于绑定和不可变的自由变量。

However, this code breaks the rule of accessing external function's scope. 但是,此代码违反了访问外部函数范围的规则。

There is nothing in your quote that says you cannot access free variables. 您的引言中没有任何内容表明您无法访问自由变量。 It says external input as reading from a file, network, etc not a free variable from a previous scope. 它表示外部输入是从文件,网络等读取而不是来自先前范​​围的自由变量。

Even Haskell use global function names like foldr and it is a free variable in every function it is used and of course the result is pure. 甚至Haskell也使用像foldr这样的全局函数名,它在每个函数中都是一个自由变量,当然结果是纯粹的。

Remember that functions by name is just variables. 请记住,按名称的函数只是变量。 parseInt is a variable that points to a function so it would have been hard to make anything at all if every function you should use in another function be passed as parameter. parseInt是一个指向函数的变量,因此如果您应该在另一个函数中使用的每个函数都作为参数传递,那么根本不需要做任何事情。

If you redefine parseInt to something that is not pure or during the duration of your program so that it works differently then no function calling it would be pure. 如果你将parseInt重新定义为非纯粹的东西或者在程序的持续时间内,以便它以不同的方式工作,那么调用它的函数就不会是纯粹的。

Function composition and partial evaluation work because they supply free variables. 功能组合和部分评估工作因为它们提供自由变量。 Its an essential method of abstraction in functional programming. 它是函数式编程中一种必不可少的抽象方法。 eg. 例如。

function compose(f2, f1) {
  return (...args) => f2(f1(...args));
}

function makeAdder(initialValue) {
  return v => v + initialValue;
}

const add11 = compose(makeAdder(10), makeAdder(1));
add11(5); // ==> 16

This is pure. 这很纯粹。 The closure variable / free variable f1 , f2 , initialValue never changes for the created functions. 闭包变量/自由变量f1f2initialValue永远不会因创建的函数而改变。 add11 is a pure function. add11是一个纯函数。

Now look at compose again. 现在再看看compose It looks pure but it can be tainted. 它看起来很纯净但可能会受到污染。 If not both functions passed to it were pure the result isn't either. 如果不是两个函数都传递给它是纯粹的,结果也不是。

OO can be purely functional too! OO也可以是纯粹的功能!

They can easily be combined by not mutating the objects you create. 通过不改变您创建的对象,可以轻松地组合它们。

class FunctionalNumber {
  constructor(value) {
    this.value = value;
  }
  add(fn) {
    return new FunctionalNumber(this.value + fn.value);
  }
  sub(fn) {
    return new FunctionalNumber(this.value - fn.value);
  }        
}

This class is purely functional. 这个课程纯粹是功能性的。

In fact you can think of a method call like obj.someMethod(arg1, arg2) as a function call with obj as first argument someFunction(obj, arg1, arg2) . 实际上,您可以将obj.someMethod(arg1, arg2)等方法调用视为函数调用,并将obj作为第一个参数someFunction(obj, arg1, arg2) It's only syntactic differences and if someFunction mutated obj you would have said it was not pure. 这只是语法上的差异,如果someFunction突变obj你会说它不纯粹。 This is how it is with someMethod and obj too. 这也是someMethodobj someMethod

You can make classes that work on large data structures that are functional, which means you never have to copy it before changing when doing a backtracking puzzle solver. 您可以创建适用于大型数据结构的类,这意味着您在执行回溯拼图求解器时更改之前无需复制它。 A simple example is the pair in Haskell and Lisp. 一个简单的例子是Haskell和Lisp中的对。 Here is one way to make it in JavaScript: 这是在JavaScript中实现它的一种方法:

class Cons {
  constructor(car, cdr) {
    this.car = car;
    this.cdr = cdr;
  }
}

const lst = new Cons(1, new Cons(2, new Cons(3, null)));
const lst0 = new Cons(0, lst);

lst0 is lst but with a new element in front. lst0lst但前面有一个新元素。 lst0 reuses everything in lst . lst0重用lst所有内容。 Everything from lists to binary trees can be made with this and you can make many sequential data structures with immutable binary trees. 从列表到二叉树的所有内容都可以用这个来创建,你可以用不可变的二叉树创建许多顺序数据结构。 It's been around since the 50s. 它自50年代以来一直存在。

I understand your opinion and totally agree with @Sylwester, but there's a point that is worth mention: with reflection external constant values can be modified and break the pureness of your function. 我理解你的意见并完全同意@Sylwester,但有一点值得一提:反射外部常量值可以修改并破坏你的功能的纯粹性。 We know that everything in IT can be hacked and we should not considere this over the concepts, but in practice we should have this clear in mind, that in this way functional pureness is unsound. 我们知道IT中的所有东西都可以被黑客入侵,我们不应该考虑这些概念,但在实践中我们应该清楚这一点,这样功能纯粹是不合理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM