Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional programming setters

How can I do a setter in functional programming like so? I would like to respect immutability and other functional programming principles.

private int age;

public void setAge(int age){

this.age=age;

}

Is that possible? If not, how can I represent the state (and its changes) of a program in a functional programming language?

like image 602
Rodrigo Cifuentes Gómez Avatar asked Jan 18 '26 14:01

Rodrigo Cifuentes Gómez


2 Answers

In general you should create a new state instead of modifying the old one.

Copy

You could use copy method like this:

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

You could also use 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)

See Learning scalaz/Lens. There are also other implementations of Lens.

shapeless Lens

For instance you could use shapeless Lens that implemented using macros, so you don't have to create lens manually:

import shapeless._

val ageLens = Lens[Person] >> 1

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

See examples on github.

See also

There are a lot of Lens implementations. See Boilerplate-free Functional Lenses for Scala and Macrocosm.

like image 117
senia Avatar answered Jan 20 '26 06:01

senia


While it's practically an oxymoron to talk about an FP mutator, Scala (as a hybrid object-functional language) does have a syntax for creating mutators and mutator-like methods:

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

Naturally, as shown there's no point in this but whatever backs the named accessor and mutator need not be a simple field and the mutator may impose range constraints on the value or do some logging when the value is mutated, so it's a fairly general construct.

Note that you cannot have the mutator alone. It has to have an accessor counterpart.

Addendum

Immutable w/ mutator w/o case class

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
like image 45
Randall Schulz Avatar answered Jan 20 '26 05:01

Randall Schulz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!