`mut` vs. redefinition

You win! The trophy is in the mail.

Is naming stuff like this weird? At my work (not rust) I generally see names like these for variables and methods. They're usually descriptive sentences rather than short names.

I can remember names like GetThingStateExpiryAaccountabilitiesByEmployeeId() being frequently used.

I think it's not answerable in the abstract. It depends whether it's the "same" thing or not, whether it's the same type, etc.

Like I said in the post, when both are possible and roughly the same.

Your function is too big :wink:

1 Like

Probably, but the entire function fits on the screen, which is my size criterion.

The problem is that my eye kept jumping to the function statement. It just never occurred to me to look for a redefinition of the variable. I only found the problem when I clicked on a use of the variable and saw that my IDE didn't highlight the variable in the function statement. Even then my first reaction was that the IDE had a bug. I quickly came to my senses and discovered what I had done.

In that case, I prefer to do:

let a = {
    let mut a = …;
    // mutate a
    a
};

The extra scope makes it easier for me to read.

6 Likes

hm.

let a = GetThingStateExpiryAaccountabilitiesByEmployeeId();

... that's what I say about that.

I have spent enough time loitering in the functional programming camp that mutable variables are almost a code smell to me. I'm not saying that's right - Rust doesn't strike me as a functional programming language - but I do see mutable variables kind of along the same lines as the goto statement, which as we know is considered harmful.

It depends on what you are modeling. Immutable data structures can often be efficient and useful, but they can also be tortured, convoluted ways to do something that simple mutability solves. Use the right tool for the right job.

Mutability worries me much less in Rust than it does in other languages. The reason for this is the single-owner rule that Rust uses, which means that I don't have to worry about things like these:

  • When doing vec![vec![1]; 64], I do not have to worry about whether it's 64 references to the same vector, or 64 distinct vectors.
  • If I pass a value to some other code, I do not have to worry about that other code keeping around a reference to it, expecting it not to change.
  • I don't have to worry about race-conditions either.

In my opinion, the above hazards are why avoiding mutability is so important in other languages, but since they just don't apply to Rust, I don't worry about mutability here.

Rust works because it enables users to write in an imperative programming style, which is the mainstream style of programming that most users are familiar with, while avoiding to an impressive degree the kinds of bugs that imperative programming is notorious for. As I said once, pure functional programming is an ingenious trick to show you can code without mutation, but Rust is an even cleverer trick to show you can just have mutation.

https://boats.gitlab.io/blog/post/notes-on-a-smaller-rust/

3 Likes

Way to go boats.

I nearly spat my coffee out when I heard boats say that in a presentation on YouTube. Surely the FP guys will love that!

Great to hear it's not necessary for me to learn Haskell after all.

1 Like

Then indeed you must learn Haskell. Or OCaml, which has a sort of mutability but only as a very visible special gimmick.

I guess the problems Alice refers to are real, but they seem to me to be in the "then don't do that" category. The problem I had in mind is an intrinsic property of mutation in a block of code, combined with procedural flow control - it makes it harder to reason about the code.

Granted, that's especially true if you find it easy to reason about recursion, which I admit I have not really mastered, but that's a different order of problem.

I suppose strictly speaking that problem resides in the procedural flow, since it's essentially the same problem whether due to mutability or shadowing. In OCaml, let a = 0; doesn't make sense - the assignment has to be followed with the context it applies to: let a = 0 in ... -- OCaml has mutable variables, but isn't procedural in this aspect of the "name space."