功能编程设置器

时间:2014-01-24 16:21:02

标签: scala functional-programming setter

如何在函数式编程中做一个setter?我想尊重不变性和其他函数式编程原理。

private int age;

public void setAge(int age){

this.age=age;

}

这可能吗?如果没有,我如何用函数式编程语言表示程序的状态(及其变化)?

2 个答案:

答案 0 :(得分:10)

通常,您应该创建一个新状态,而不是修改旧状态。

复制

您可以使用copy这样的方法:

case class Person(name: String, age: Int)

val youngBob = Person("Bob", 15)
val bob = youngBob.copy(age = youngBob.age + 1)
// Person(Bob,16)

scalaz Lens

您也可以使用Lens

import scalaz._, Scalaz._

val ageLens = Lens.lensu[Person, Int]( (p, a) => p.copy(age = a), _.age )

val bob = ageLens.mod(_ + 1, youngBob)
// Person(Bob,16)

Learning scalaz/Lens。还有Lens的其他实现。

无形镜片

例如,您可以使用使用宏实现的shapeless Lens,因此您无需手动创建镜头:

import shapeless._

val ageLens = Lens[Person] >> 1

val bob = ageLens.modify(youngBob)(_ + 1)
// Person(Bob,16)

请参阅examples on github

另见

有很多Lens个实现。请参阅Boilerplate-free Functional Lenses for ScalaMacrocosm

答案 1 :(得分:1)

虽然谈论FP mutator实际上是一种矛盾,但Scala(作为一种混合对象函数式语言)确实有一种创建mutator和类似mutator的方法的语法:

scala> class C1 { def x: Int = xx; def x_=(i: Int): Unit = xx = i; private var xx: Int = 0 }
defined class C1

scala> val c1 = new C1
c1: C1 = C1@1e818d28

scala> c1.x = 23
c1.x: Int = 23

scala> c1.x
res18: Int = 23

自然地,如图所示,没有任何意义,但无论如何,命名的访问器和mutator都不需要是一个简单的字段,并且mutator可能对值施加范围约束或者在值变异时执行一些日志记录,所以它是公平的一般建构。

请注意,您不能单独使用mutator。它必须有一个访问者对应物。

<强>附录

不可变的w / mutator没有案例类

scala> class C2(xInit: Int) { def this = this(0)
                              def x: Int = xx
                              def x_=(i: Int): C2 = new C2(i)
                              private var xx: Int = xInit
                            }

scala> val c2a = new C2()
c2a: C2 = C2@2f85040b

scala> val c2b = c2a.x = 23
c2b: C2 = C2@74f1bfa9

scala> c2a.x
res19: Int = 0

scala> c2b.x
res20: Int = 23