3

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?

4
  • 5
    You would create a new object which is otherwise identical except its age is set to the new age. Commented Jan 24, 2014 at 16:35
  • Please, read that article. Commented Jan 24, 2014 at 18:12
  • 2
    Why the downvotes? "With mutable classes I'm using setters, what should I use with immutable classes?" - I guess it's a good question for a newbie in FP. Commented Jan 24, 2014 at 18:25
  • 1
    @senia: Agreed, and I'm not really sure what the article linked by Artsiom has to do with the question (not that it's bad—it's just not about immutable classes). Commented Jan 24, 2014 at 18:52

2 Answers 2

10

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.