首页 理论教育 函数式编程入门:Elixir中的非纯函数

函数式编程入门:Elixir中的非纯函数

时间:2023-11-20 理论教育 版权反馈
【摘要】:现在再次调用IO.gets/1,还是使用参数"What's the meaning of life?再看另一个例子:函数total是一个有趣的例子。tax处在函数作用域之外;因此可以说total是不纯的。但是,由于不变性,重新绑定tax变量不会影响total函数。total函数的tax值是不变的,所以每次调用total时,传递相同的参数都会得到一致的值。考虑下面的函数:total函数返回了一致的结果,但它使用IO模块打印消息,这是副作用。最好让total函数只负责计算,将IO.puts/1放到total之外。

函数式编程入门:Elixir中的非纯函数

传入的参数固定时,非纯函数可能返回不一致的结果,并且可能产生超出函数作用域的影响。这就是它无法预测的原因。在IEx中尝试以下函数:

输入42,按Enter,结果为"42\n"。现在再次调用IO.gets/1,还是使用参数"What's the meaning of life?\n"。程序会再次询问;输入43,按Enter,结果为"43\n"。我们用相同的参数调用了同一个函数,却产生了不同的值。这就是一个非纯函数。非纯函数会与程序之外的东西交互,例如,读/写文件、访问API、读取数据库、生成随机数、请求用户输入等。IO.gets/1请求用户输入,而我们无法预测用户的输入内容。每次调用IO.gets/1都会产生不同的结果。

非纯函数还有另外一种定义:引用了函数参数以外值的函数。一旦函数使用了函数作用域之外的值,它就变成非纯函数了。让我们看一个例子:

函数DateTime.utc_now()是不纯的,每次调用都会返回一个新结果。因为它在内部引用了全局机器时钟状态。如果我们创建依赖DateTime.utc_now/0结果的函数,它们也将变得不纯。再看另一个例子:

函数total是一个有趣的例子。它引用了tax变量,而tax不是局部变量。tax处在函数作用域之外;因此可以说total是不纯的。但是,由于不变性,重新绑定tax变量不会影响total函数。total函数的tax值是不变的,所以每次调用total时,传递相同的参数都会得到一致的值。那么,total函数究竟是纯还是非纯?真矛盾呀!它是纯的,因为它的输出只受输入的影响。(www.xing528.com)

所以,非纯函数的最终定义是:会产生副作用的函数都是不纯的。副作用涉及访问和操作函数作用域之外的值,比如在终端编写消息、更改全局状态、读写数据库、访问API等。考虑下面的函数:

total函数返回了一致的结果,但它使用IO模块打印消息,这是副作用。具有副作用的函数是不纯的。这样写函数是一种不好的做法;另一个使用此函数的开发人员不会期望total在控制台中打印消息。在没有IO设备的情况下,这个简单的函数将导致意外错误。最好让total函数只负责计算,将IO.puts/1放到total之外。下面是一个例子:

我们可以用这种方法把非纯函数与纯函数隔离开。不要认为非纯函数是不好的,纯函数才是好的。非纯函数是所有实用软件都需要的。为了提高软件的可维护性,您应该尽量使用纯函数,同时通过适当的处理隔离不纯的部分。现在你已经知道如何识别非纯函数,是时候讲解隔离策略了。我们将研究如何提高函数的可预测性,隔离意外结果,避免影响整个系统。让我们从条件语句开始。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈