如何编写没有Java副作用的程序?

Bas*_*stl 8 java functional-programming scala

作为一名长期的Java程序员,近年来Haskell成瘾者,我现在正在学习Scala.我的问题是:

如何编写没有Java副作用的程序?

即我如何手动完成Scala为我做的事情?

来自Odersky的Scala书经常用OO术语解释功能概念(例如val = final,if = ternary op.).

是否有一个可访问的指南如何编写没有Java的副作用(尽可能少)?我想可以通过普通的旧java和一些规则来获得许多已知的好处(例如,不可修改的集合,最终值,不修改对象/应用程序状态的刚性方法).

Apo*_*isp 12

  1. 使每个方法,字段和类成为abstractfinal.
  2. 创建每个变量和方法参数final.
  3. 如果您使用Array像文件和数据库连接这样的可变结构,或者使用i/o资源,那么永远不要让它们逃避构造它们的范围.


Pet*_*Mmm 7

在没有较少副作用的情况下进行编程的一种方法是仅使用不可变类.您可以将它应用于您自己的类,但是如果不从头开始重写,则无法更改标准Java runntime.

无论如何,使Java副作用免费,没有任何意义,因为它是一种具有OO数据封装的命令式编程语言.换句话说,副作用是语言的一部分,本身并不邪恶.

  • @Bastl:例如它的所有属性都是不可变的...在Java中,如果你的属性是例如本机数组,它就会成为一个问题. (2认同)
  • @Bastl我认为Odersky本人曾说过一个纯粹的功能性程序只会产生热量.I/O本质上不起作用,这就是为什么它与Haskell中的常规代码与monad分开.如果Java对象在实例化后没有可以更改其引用的字段,并且它可以访问的所有对象都是不可变的,那么它是不可变的.一个很好的例子是String.使用集合强制执行的一种好方法是Collections.unmodifiableList()等. (2认同)

mer*_*ict 5

作为一名长期的Java程序员,近年来Haskell成瘾者,我现在正在学习Scala.

恭喜 :)

如何编写没有Java副作用的程序?即我如何手动完成Scala为我做的事情?

好吧,Scala在执行或协助副作用自由风格方面对你(与Haskell相比)并没有那么多.例如,您始终可以在Scala中随意使用选项var,而在Haskell中如果您想要可变,IORef或者STRef您需要使用适当的monad向类型系统指示.

换句话说,虽然你问如何在Java中模仿Scala风格,但要考虑的第一步是如何在Scala中模仿Haskell风格,这当然是Scalaz发挥作用的地方.

所有这一切,我想你已经回答了你自己的问题:

我想可以通过普通的旧java和一些规则来获得许多已知的好处(例如,不可修改的集合,最终值,不修改对象/应用程序状态的刚性方法).

纪律至少是故事的一半.简单地使用final和不可变的集合(àlaGuava)会对您的代码最终看起来产生各种影响.当然,故事的另一半是当你的程序需要副作用(例如I/O)时你会怎么做?在Haskell你会使用IOmonad,在Scala中你可能会选择使用scalaz.effects.IO,但在Java中,说实话,我认为这不是一场值得战斗的战斗.

在我看来,您将在任何Java程序中编写的两个最重要的功能样式代码行如下:

import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
Run Code Online (Sandbox Code Playgroud)

其余的是读者的练习;)