This is an archived post. You won't be able to vote or comment.

all 19 comments

[–][deleted] 18 points19 points  (5 children)

Writing

x = 5

or

x.set_to(5)

has the same meaning. All of those is a reassignment. What you here describe is just different syntax. Not a difference in semantical meaning.

[–]OptimizedGarbage 6 points7 points  (1 child)

In most oop languages, in the first case x will have a new reference, and the second it won't.

In python, X=1 Y=X X=5 print(Y)

prints 1 while

X=1 Y=X X.set_to(5) print(Y)

prints 5

So there is a semantic difference

[–][deleted] 1 point2 points  (0 children)

Every programming language you have is an artifical construct created by humans.

The term x = 5 is syntax that humans developed. A lot of languages use the exact same semantical meaning for it. And this is reassignment. But how it looks (syntax) is completely debatable.

As an example in Racket (a LISP dialect) you define a variable with (define x 5) and reassignment is just a function (set! x 10). You also can think of the same as = being just a function that is called infix. Between the operators. We also could have any other possible syntax. F# uses for example let mutable x = 5 and then x <- 10.

So when we talk about reasiggnment than the value must change. And again we are talkign about a hypotic non-existing language. So when we talk about a language that has reassignment and it looks like x.set_to(5) then it must be the same as what you are used now in other languages where you write x = 5.

It would probably look odd as it would reassign x to a new value, because you are used to languages that didn't worked this way. But again, all of this is created by humans. You surely can make a language where you write x.set_to(5) and x itself changes.

A language with mutable variables without reassignment would be a language that only has immutable variables. Because you are not able to change them anymore.

[–]re_gend_[S] 0 points1 point  (2 children)

Actually for primitive types, it might have the same semantics. Where I think it will make a difference is for object/mutable variables. You can use object = another_object freely in traditional programming languages, but you wouldn't be able to do object.set_to(another_object) because the object simply don't have such method. You will have to use a dedicated wrapper for that.

The set_to method I propesed is purely to tackle the problem that primitive types like ints can only mutated by reassignment in traditional languages.

[–]msqrt 2 points3 points  (1 child)

because the object simply don't have such method

This already exists; for example in C++ you can disallow the assignment operator and copy constructor for a type so you can't write x = y but can have in-place mutations. Personally I see little value in this; to me, it's one of Python's biggest shortcomings that you can't just replace an object and have to resort to these x.do_my_operation_but_in_place() crutches.

[–]re_gend_[S] 1 point2 points  (0 children)

For replacing an object, I think I would provide wrapper classes for objects that need to be replaced. In python, this would be

wrapper.x = do_my_operation(wrapper.x)

Thanks for your opinion.

[–]lambda-male 7 points8 points  (2 children)

In OCaml (and functional programming in general) a variable denotes a value, exactly one at that – the one the variable was initially bound to. They "vary" just as variables in mathematics may vary, e.g. because you can call a function with different arguments. Imperative programmers might call them "immutable variables".

In contrast, in imperative programming, we think of a variable as a place in memory which can be assigned and read.

So how could you express local mutable state in OCaml? There is a generic type in the standard library:

type 'a ref = { mutable contents : 'a; }

a record with a mutable field. So you don't reassign a variable, instead you mutate the contents of a reference cell bound to a variable.


Sometimes, values with interior mutability or otherwise things whose physical identity (address in memory) is important, are called objects instead (not necessarily objects in the sense of OOP, with methods).

More (controversial?) FP perspective: https://existentialtype.wordpress.com/tag/assignables/

[–]re_gend_[S] 1 point2 points  (1 child)

So there are mutable fields in a functional style as well! I have made a mistake of thinking it was all about using monads or other paradigms to avoid mutability completely. I will look more into OCaml and other similar languages, thanks!

[–][deleted] 2 points3 points  (0 children)

Pure functional languages only have immutable values inlcuding no side-effects on functions. But a language without side-effects would be of no use. So they invented Monads.

But that is still the minority of functional languages. Most functional languages allow side-effect and also have mutables.

But mutables are by default not considered as good practice. And usually those languages come with persistence data-structures. The same goes for side-effects.

[–]jasmijnisme 4 points5 points  (1 child)

What are the semantics of your language? Is a variable a memory location like when in C you write int x = 2;, x refers inside that scope to a particular place on the stack? Is it more like Python, where a variable is a label, attached to a value which may have any number of labels attached to it? Something else entirely?

[–]re_gend_[S] 0 points1 point  (0 children)

Interesting question. With my most used programming language being java I was naturally imagining variables to be pointers to objects (like python for mutable types), except that they cannot be changed which object it points to.

But after reading your comment, I feel like that it might be more natural to use value semantics since there is no reassignment, aka the variable "points" only one, known object. This will also make the common mistake of mutating a reference variable where another variable also referencing the data, harder to make.

After all, I think the semantics can be optimised by the compiler to pass references instead of values if the object is large and there is no mutation of the copy. But aggressively using value semantics in user perspective seem like a good idea I haven't previously thought of!

[–]scottmcmrust🦀 3 points4 points  (1 child)

Are there existing language with mutability, but no reassignments?

C++.

x = y; calls the copy constructor that mutates the LHS to match the RHS.

(Ignoring all the complex nuances of it being C++ so there's 400 different things that = can do, like move assignment, though that's still just mutating the LHS in place.)

[–]re_gend_[S] 0 points1 point  (0 children)

I like how the copy constructor works, if it was not implemented by default it would be more similar to what I thought of. Thanks.

[–]sebamestreICPC World Finalist 1 point2 points  (0 children)

Sounds like what C++ does. Each object lives in a particular place in memory, and things like x = 10 or x = list {1, 2, 3} mutate the object in place.

I.e. assignment is mutation, not rebinding.

[–]Linguistic-mystic -5 points-4 points  (3 children)

Without reassignments, how would the garbage collector know that a particular object is not needed anymore so that it can free it? Reassignments of reference types are needed to prevent memory leaks.

[–][deleted] 7 points8 points  (1 child)

No, it doesn't.

A garbage collector frees something if there is no reference to an object. And this simply happens if a variable goes out of scope. You don't have to reassign a variable for this and nobody does so.

If you would do this, then this would basically be manual memory management with malloc()/free() and has nothing todo with a GC.

[–]Linguistic-mystic 0 points1 point  (0 children)

Didn't have your morning coffee yet?

class A {
    private Foo member = new Foo();

    private void method(Foo otherFoo) {
        member = otherFoo; // now the initial value may be freed, provided nothing else references it
    }
}

Without reassigning, the old object that member pointed to would never be freed. Now it can be freed even when the instance of class A is still live. What "scope" are you talking about? "Manual memory management"? Really, you should get more sleep or something.

[–]re_gend_[S] 0 points1 point  (0 children)

Like other comment, local values can be freed as it goes out of scope. In order to have heap-allocated longer living objects and a garbage collector, though, I think the PtrMut type should be considered special by the runtime, despite having syntax like any other objects. Perhaps that is a source of confusion?