A grasp of immutable datastructures

前端 未结 3 977
执笔经年
执笔经年 2020-12-05 03:28

I am learning scala and as a good student I try to obey all rules I found.

One rule is: IMMUTABILITY!!!

So I have tried to code everything with immutable dat

3条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-05 03:54

    The case for functional programming is one of being concise in your code and bringing in a more mathematical approach. It can reduce the possibility of bugs and make your code smaller and more readable. As for being easier or not, it does require that you think about your problems differently. But once you get use to thinking with functional patterns it's likely that functional will become easier that the more imperative style.

    It is really hard to be perfectly functional and have zero mutable state but very beneficial to have minimal mutable state. The thing to remember is that everything needs to done in balance and not to the extreme. By reducing the amount of mutable state you end up making it harder to write code with unintended consequences. A common pattern is to have a mutable variable whose value is immutable. This way identity ( the named variable ) and value ( an immutable object the variable can be assigned ) are seperate.

    var acc: List[Int] = Nil
    // lots of complex stuff that adds values
    acc ::= 1
    acc ::= 2
    acc ::= 3
    // do loop current list
    acc foreach { i => /* do stuff that mutates acc */ acc ::= i * 10 }
    println( acc ) // List( 1, 2, 3, 10, 20, 30 )
    

    The foreach is looping over the value of acc at the time we started the foreach. Any mutations to acc do not affect the loop. This is much safer than the typical iterators in java where the list can change mid iteration.

    There is also a concurrency concern. Immutable objects are useful because of the JSR-133 memory model specification which asserts that the initialization of an objects final members will occur before any thread can have visibility to those members, period! If they are not final then they are "mutable" and there is no guarantee of proper initialization.

    Actors are the perfect place to put mutable state. Objects that represent data should be immutable. Take the following example.

    object MyActor extends Actor {
      var acc: List[Int] = Nil
      def act() {
        loop {
          react {
            case i: Int => acc ::= i
            case "what is your current value" => reply( acc )
            case _ => // ignore all other messages
          }
        }
      }
    }
    

    In this case we can send the value of acc ( which is a List ) and not worry about synchronization because List is immutable aka all of the members of the List object are final. Also because of the immutability we know that no other actor can change the underlying data structure that was sent and thus no other actor can change the mutable state of this actor.

提交回复
热议问题