• @[email protected]
    link
    fedilink
    125 days ago

    it’s not radical, it’s just a guarantee that if you hold a reference to an object, it won’t change state under you. It’s a bit like every object has MVCC and copy-on-write semantics built in.

    It’s easy enough to edit the object, producing a new copy, and then explicitly store it back where it goes or send it to whatever consumer needs it.

    • @[email protected]
      link
      fedilink
      125 days ago

      I get the idea, and how you keep it from copying a lot of data unnecessarily. A radical approach would be using immutable types exclusively

      • @[email protected]
        link
        fedilink
        121 days ago

        Oh, regarding copying data - immutable collections are based on https://en.m.wikipedia.org/wiki/Persistent_data_structure - when a change is applied, you get back a reference to a new data structures where as many inner references as possible are shared with the old one. So, all the parts that didn’t change, are not copied.

        For something like a Scala case class (similar to a record), o.copy(membername1 = newvalue) returns a new object, with a new membername1 reference, but all other member references are the same as the copied-from object. So it’s a shallow copy with minimal changes.

        you might see how default immutability as a policy makes this more predictable and able to be reasoned about - any mutable object in an object graph that has a shared reference in a copy may surprise you by suddenly changing state.

        Of course, that’s the situation everywhere, all the time, in default-mutable languages. How many people set a default value of a Python function argument to [] or {} and were baffled when things started breaking because the instance of the default value was mutated?

        • @[email protected]
          link
          fedilink
          121 days ago

          Clever! But I’d worry to run into performance problems when some operations effectively require copying or becoming a sort of linked list.

          Although I suppose you could also be explicit if you do need it to behave in a particular way.

          I like it!

          • @[email protected]
            link
            fedilink
            121 days ago

            There is a bit more overhead when you can’t just overwrite a value in memory. But cpu time and memory space are some of the most cheap and straightforward resources to scale up compared to engineering time to resolve consistency bugs.

            There is also a performance hit associated with mutexes or locking required to ensure mutable structures are updated consistently, and many high-scale systems have moved to append-only logs and copy-on-write semantics - structures that leave already-written data in place - because mutability/locking doesn’t scale.

      • @[email protected]
        link
        fedilink
        125 days ago

        I guess, as a Scala enthusiast, it’s second nature to me - Scala incorporates immutable-by-default into its design so there are accommodations for it (.copy() methods on case classes, well-thought-out operators and methods on collections, “val” bindings, expression-oriented syntax).

        It also lets you have normal OO classes and mutable vars anytime you want them, so you’re not stuck in a corner like you may sometimes be in Haskell if you don’t know the applicable FP pattern.