Questions tagged «side-effect»


9
退货被认为有害吗?没有它,代码可以起作用吗?
好的,标题有点clickbaity,但是我已经很认真地告诉别人,请不要踢一会儿。我喜欢它如何鼓励以真正的面向对象的方式将方法用作消息。但是,这个棘手的问题一直困扰着我。 我开始怀疑编写良好的代码是否可以同时遵循OO原则和功能原则。我正在设法调和这些想法,而我所坚持的最大症结是return。 纯函数具有两种性质: 使用相同的输入重复调用它总是得到相同的结果。这意味着它是不可变的。其状态仅设置一次。 它不会产生副作用。调用它引起的唯一变化就是产生结果。 那么,如果您发誓要使用return它来传达结果,那么如何才能完全发挥功能呢? 该出来,不问用什么有些人会考虑副作用思想工作。当我处理一个对象时,我不会询问它的内部状态。我告诉它我需要做的事情,它使用其内部状态来弄清楚该如何处理我已经告诉它要做的事情。一旦我告诉了我,我就不会问它做了什么。我只是希望它对它被告知要做的事情有所作为。 我认为“告诉,不要问”不仅仅是封装的另一个名称。当我使用时,return我不知道叫我什么。我不能说这是协议,我必须强迫它处理我的协议。在许多情况下,这表示为内部状态。即使暴露的不是确切的状态,通常也只是对状态和输入args进行一些计算。拥有一个响应界面,可以将结果整理成比内部状态或计算更有意义的结果。那就是信息传递。请参阅此示例。 回想过去,当磁盘驱动器中实际上装有磁盘,而拇指驱动器是您在汽车上做的,而车轮太冷而无法用手指触摸时,我就被教给了令人讨厌的人们如何考虑没有参数的功能。void swap(int *first, int *second)似乎很方便,但是我们鼓励我们编写返回结果的函数。因此,我坚信信念,并开始遵循。 但是现在我看到人们在构建体系结构,在该体系结构中,对象可以通过其构造方式控制结果的发送位置。这是一个示例实现。再次注入输出端口对象似乎有点像out参数的想法。但这就是告诉对象不要告诉其他对象他们所做的事情的方式。 当我第一次了解副作用时,我将其视为输出参数。有人告诉我们不要以令人惊讶的方式进行某些工作,也就是说,不遵守return result公约,以使人们感到惊讶。现在可以肯定,我知道有很多并行异步线程问题会带来副作用,但是返回实际上只是一个约定,您可以将结果压入堆栈,以便以后调用时可以将其弹出。真的就是这些。 我真正想问的是: 是return避免所有这些副作用的苦难并获得没有锁等的线程安全性的唯一方法。还是我可以跟着说,不要以纯粹的功能性方式提出要求?

7
您怎么称呼一个函数,其中相同的输入将始终返回相同的输出,但也会产生副作用?
假设我们有一个正常的纯函数,例如 function add(a, b) { return a + b } 然后我们对其进行更改,使其具有副作用 function add(a, b) { writeToDatabase(Math.random()) return a + b; } 据我所知,它并不是纯函数,因为我经常听到人们称纯函数为“无副作用的函数”。但是,就其对于相同输入将返回相同输出的事实而言,它的行为确实类似于纯函数。 这种函数类型是否有其他名称,是未命名的,还是实际上是纯函数,而我对纯函数的定义有误?

5
功能语言中的异步编程
我主要是C / C ++程序员,这意味着我的大部分经验都涉及过程和面向对象的范例。但是,正如许多C ++程序员所知道的那样,多年来,C ++的重点已转移到具有功能的风格,最终在C ++ 0x中增加了lambda和闭包。 无论如何,尽管我在使用C ++ 进行功能样式编码方面有丰富的经验,但是我对诸如Lisp,Haskell等实际功能语言的经验却很少。 我最近开始研究这些语言,因为纯功能语言中的“无副作用”的想法一直吸引着我,特别是在将其应用于并发和分布式计算方面。 但是,出于C ++的背景,我对于这种“无副作用”的哲学与异步编程的工作方式感到困惑。异步编程是指可以分发用户提供的事件处理程序以处理异步发生的事件(程序流之外)的任何框架/ API /编码样式。这包括异步库,例如Boost.ASIO,甚至只是普通的C语言。信号处理程序或Java GUI事件处理程序。 所有这些共同点是,异步编程的性质似乎需要创建副作用(状态),以使程序的主要流程意识到已调用了异步事件处理程序。通常,在Boost.ASIO之类的框架中,事件处理程序会更改对象的状态,从而使事件的影响传播到事件处理程序功能的生存期之外。真的,事件处理程序还能做什么?它不能“返回”值到调用点,因为没有调用点。事件处理程序不是程序主流程的一部分,因此它对实际程序有任何影响的唯一方法是更改​​某些状态(或更改longjmp为另一个执行点)。 因此,似乎异步编程是关于异步产生副作用的。这似乎与函数式编程的目标完全矛盾。这两种范例在功能语言中如何进行协调(实际上)?

3
查看单子的不同方法
在学习Haskell的过程中,我遇到了很多教程,试图解释什么是monad,以及为什么monad在Haskell中很重要。他们每个人都使用类比,因此更容易理解其含义。归根结底,我对单子是3种不同的看法: 查看1:将Monad作为标签 有时我认为将monad作为特定类型的标签。例如,一个类型的函数: myfunction :: IO Int myfunction是一个函数,无论何时执行它都会产生一个Int值。结果的类型不是Int,而是IO Int。因此,IO是Int值的标签,警告用户知道Int值是执行IO操作的过程的结果。 因此,此Int值已被标记为来自具有IO的过程的值,因此该值为“脏”。您的过程不再是纯粹的。 视图2:莫纳德(Monad)是可能发生令人讨厌的事情的私人空间。 在所有过程都是纯且严格的系统中,有时您需要产生副作用。因此,monad只是一个很小的空间,允许您做讨厌的副作用。在这个空间中,您可以逃脱纯净的世界,走不纯净的事物,进行过程,然后返回有价值的东西。 图3:Monad的范畴论 我不完全理解这种观点。monad只是同一类别或子类别的函子。例如,您具有Int值,并且作为IO Int子类,它们是在IO过程之后生成的Int值。 这些观点正确吗?哪个更准确?

4
IO monad模式处理副作用的好处是否纯粹是学术上的?
对不起,还有另一个FP +副作用问题,但是我找不到一个可以完全回答我的问题。 我对函数式编程的(有限的)理解是,应将状态/副作用最小化并与无状态逻辑分开。 我还收集了Haskell的方法,即IO monad,它通过将有状态的动作包装在一个容器中以供以后执行(被认为超出程序本身的范围)来实现。 我试图理解这种模式,但实际上是确定是否在Python项目中使用它,因此要避免使用Haskell规范。 粗暴的例子来了。 如果我的程序将XML文件转换为JSON文件: def main(): xml_data = read_file('input.xml') # impure json_data = convert(xml_data) # pure write_file('output.json', json_data) # impure IO monad的方法不是有效地做到这一点: steps = list( read_file, convert, write_file, ) 然后通过不实际调用这些步骤来放任自己的责任,而是让口译员这样做? 换一种说法,就像写: def main(): # pure def inner(): # impure xml_data = read_file('input.xml') json_data = convert(xml_data) write_file('output.json', …


2
有状态库顶部的无副作用界面
在约翰·休斯(John Hughes)的采访中,他谈到了Erlang和Haskell,他对在Erlang中使用有状态的库有以下看法: 如果要使用有状态的库,通常会在其之上构建无副作用的接口,以便随后可以在其余代码中安全地使用它。 他是什么意思?我试图考虑一个例子,但是我的想象力和/或知识使我失望。

5
如何创建可扩展且无副作用的集成测试?
在当前的项目中,我很难找到一个好的解决方案来创建没有副作用的可扩展集成测试。关于副作用自由属性的一些澄清:它主要是关于数据库的;测试完成后,数据库中不应有任何更改(应保留状态)。也许可伸缩性和状态保存并没有融合在一起,但是我真的想推动一个更好的解决方案。 这是一个典型的集成测试(这些测试涉及数据库层): public class OrderTests { List<Order> ordersToDelete = new ArrayList<Order>(); public testOrderCreation() { Order order = new Order(); assertTrue(order.save()); orderToDelete.add(order); } public testOrderComparison() { Order order = new Order(); Order order2 = new Order(); assertFalse(order.isEqual(order2); orderToDelete.add(order); orderToDelete.add(order2); } // More tests public teardown() { for(Order order : ordersToDelete) order.delete(); …


3
破坏参考透明度的副作用
Scala中的函数式编程说明了副作用对破坏引用透明性的影响: 副作用,这意味着违反了参照透明性。 我已经阅读了SICP的一部分,其中讨论了使用“替代模型”评估程序。 当我大致了解具有引用透明性(RT)的替换模型时,可以将函数分解为最简单的部分。如果表达式是RT,则可以分解表达式并始终获得相同的结果。 但是,正如以上引用所述,使用副作用可能/将破坏替代模型。 例: val x = foo(50) + bar(10) 如果foo和bar 没有副作用,则执行任一函数将始终将相同结果返回x。但是,如果它们确实有副作用,它们将更改一个变量,该变量会破坏/投入替代模型。 我对这个解释感到满意,但是我并没有完全理解它。 请纠正我,并填写有关破坏RT的副作用的所有漏洞,并讨论对替代模型的影响。

4
有条件的副作用有没有可能?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 我正在参加中间数据结构课程,作为进入美国每个人都听说过的大学的CS MS程序的先决条件。在课堂上写的一行代码引起了我的注意: if (a > 33 | b++ < 54) {...} 这不会在我的工作场所通过代码审查。如果您在面试中编写了这样的代码,这将是对您的重大打击。(除了附带条件的条件外,它还很聪明,但以清晰度为代价。) 实际上,我从未见过有副作用的条件,而且Googling也不会出现太多问题。下课后还有另一个学生问这个问题,所以我不是唯一认为这很奇怪的人。但是这位教授非常坚决地认为这是可以接受的代码,并且他会在工作中编写类似的代码。(他的FT工作是在您都听说过的一家公司担任首席SWE。) 我无法想象这样的代码行是可以接受的,更不用说是令人满意的了。我错了吗?这个可以吗?那么更一般的情况呢:有副作用的条件治疗呢?那些还好吗?

2
单元测试副作用繁重的代码
我开始写C ++代码来运行机器人,如果可以的话,我不知道如何合并单元测试。我提供了一个库,该库允许为机器人创建“命令”,这些命令会自动调度和执行。创建这些命令的机制是继承一个命令基类它们提供,并执行虚拟void Initialize(),void Execute()和void End()方法。这些功能纯粹是出于其副作用而运行,这些副作用会对机器人产生影响(运行电动机,伸出活塞等)。因此,除了模拟整个库之外,我几乎看不到任何将单元测试附加到代码的地方,这样我就可以检查机器人的虚拟前后状态。有没有一种方法可以对此进行单元测试,而不会造成太大的负担? 编辑 我想我可能对库的功能产生了误导。该库提供了机器人以及命令/调度系统的大部分接口,因此它不像模拟命令基类那么简单,我必须模拟整个硬件接口。不幸的是,我没有时间这样做。

2
当我们将计算与副作用分开时,我们将“询问世界”的代码放在哪里?
根据命令查询分离原则,以及使用Clojure演示的“ 数据中的思考”和“ DDD”,应将副作用(修改世界)与计算和决策分开,以便更容易理解和测试这两个部分。 这就留下了一个悬而未决的问题:我们应该把“问世界”放在边界的哪个位置?一方面,从外部系统(例如数据库,扩展服务的API等)请求数据不是参照透明的,因此不应与纯计算和决策代码放在一起。另一方面,将它们从计算部分中分离出来并作为参数传递是有问题的,甚至是不可能的,因为因为我们可能事先不知道可能需要请求哪些数据。

2
函数式编程语言是否会带来副作用?
根据Wikipedia 所说,声明性的函数式编程语言禁止副作用。通常,声明式编程会尝试最小化或消除副作用。 同样,根据维基百科,副作用与状态变化有关。因此,从某种意义上说,函数式编程语言实际上消除了副作用,因为它们不保存任何状态。 但是,此外,副作用还有另一个定义。副作用 除了返回值之外,还可以与其调用函数或外界进行交互。例如,特定函数可能会修改全局变量或静态变量,修改其参数之一,引发异常,将数据写入显示或文件,读取数据或调用其他副作用函数。 从这种意义上说,函数式编程语言实际上会带来副作用,因为有无数的函数实例影响它们的外部世界,调用其他函数,引发异常,写入文件等。 那么,最后,函数式编程语言是否允许副作用? 或者,我不明白什么是“副作用”,因此命令式语言允许它们,而声明式语言则不允许。根据以上内容以及所得到的内容,没有一种语言能够消除副作用,因此我可能遗漏了一些有关副作用的信息,或者Wikipedia定义的定义不正确。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.