this post was submitted on 21 Mar 2024
294 points (94.8% liked)

Programmer Humor

19821 readers
903 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 2 years ago
MODERATORS
 
you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 42 points 9 months ago (6 children)

Const everything by default

If you need to mutate it, you don't, you need to refactor.

[–] [email protected] 45 points 9 months ago (2 children)

Dogmatic statements like this lead to bad, messy code. I'm a firm believer that you should use whatever style fits the problem most.

Although I agree most code would be better if people followed this dogma, sometimes mutability is just more clean/idiomatic/efficient/...

[–] [email protected] 1 points 9 months ago

I agree somewhat, but I'd also say any codebase needs some level of "dogmatic" standard (ideally enforced via tooling). Otherwise you still end up with bad, messy code (I'd even say messier, as you don't even get consistency)

[–] [email protected] -3 points 9 months ago

Define your terms before relying on platitudes. Mutability isn't cleaner if we want composition, particularly in the face of concurrency. Being idiomatic isn't good or bad, but patterned; not all patterns are universally desirable. The only one which stands up to scrutiny is efficiency, which leads to the cult of performance-at-all-costs if one is not thoughtful.

[–] [email protected] 13 points 9 months ago (1 children)

I'd agree with the first half, but not the second. Sometimes mutability allows for more concise code, although in most cases it's better to not mutate at all

[–] [email protected] 4 points 9 months ago

I feel like I should maybe have put a "probably" in there

After all "there's no silver bullet", but in anything but a few edge cases, the rule applies, IMO

[–] [email protected] 8 points 9 months ago (1 children)

Sorry, I want to make an app that works, not a perfect art piece.

[–] [email protected] 4 points 9 months ago (1 children)

The app working isn't good enough, it needs to be maintainable. From a professional perspective, unmaintainable code is useless code.

Code that mutates everywhere is generally harder to reason about and therefore harder to maintain, so just don't do it (unless there's literally no other practical way, but genuinely these are very rare cases)

[–] [email protected] 1 points 9 months ago (1 children)

I personally disagree, forcing yourself to use non mutable variables only leads to longer and more convoluted code.

[–] [email protected] 2 points 9 months ago

Fair play, I guess we're probably just gonna disagree.

In my experience I'd say mutable code (larger than anything other than toy examples) always results in more time spent fixing bugs down the line, predominantly because it's objectively harder for humans to reason about multiple one to many relationships rather than multiple one to one relationships. I'd say because you need to think about all possible states of the set of mutable variables in your code in order to completely understand it (and I don't just mean understanding the intended purpose of the code, I mean understanding everything that code is capable of doing), that usually results in a more convoluted implementation than the pretty linear way you typically read functional code.

Longer code is practically always better if it's easier to understand than the shorter alternative. Software engineers aren't employed to play code golf, they're employed to write maintainable software. Though I'll say ultra high performance applications might be the exception here—but 99% of engineers aren't doing anything like that.

I'm always happy to be convinced otherwise, but I've never seen a convincing argument

[–] [email protected] 4 points 9 months ago (1 children)

Scala user unite! There are dozens of us, dozens!

[–] [email protected] 5 points 9 months ago (2 children)

Scala? Can we reimplement it in Rust?

[–] [email protected] 4 points 9 months ago

sure, just make sure to add "blazingly fast" in the description and append "-rs" to the name

[–] [email protected] 2 points 9 months ago (1 children)

But does it do everything in anonymous functions and lambdas?

[–] [email protected] 2 points 9 months ago
[–] [email protected] 3 points 9 months ago* (last edited 9 months ago) (1 children)

That is a... strange take.

Random example, imagine a variable that holds the time of the last time the user moved the mouse. Or in a game holding the current selected target of the player. Or the players gold amount. Or its level. Or health. Or current position.

[–] [email protected] 1 points 9 months ago (1 children)

In all those cases, the answer is to swap in a new variable and throw the old one away.

[–] [email protected] 1 points 9 months ago (1 children)

Legit question because i think I'm misunderstanding. But if its a const, how are you able to swap or replace it?

[–] [email protected] 5 points 9 months ago (2 children)

It's only a const within a function. You can pass the value to another function and changing it as it's passed. For example:

const int foo = 1
other_func( foo + 1)

In functional programming, you tend to keep track of state on the stack like this.

[–] [email protected] 1 points 9 months ago

Aaah okay i get it now :) that makes a lot more sense.

[–] [email protected] 1 points 9 months ago (1 children)

What is the advantage of this VS just overwriting the var?

[–] [email protected] 7 points 9 months ago (1 children)

Keeping state managed. The data for the function will be very predictable. This is especially important when it comes to multithreading. You can't have a race condition where two things update the same data when they never update it that way at all.

[–] [email protected] 1 points 9 months ago (1 children)

Hm I'm having trouble visualizing this do you know a quick little example to illustrate this?

[–] [email protected] 1 points 9 months ago (1 children)

Rather than me coming up with an elaborate and contrived example, I suggest giving a language like Elixir a try. It tends to force you into thinking in terms of immutability. Bit of a learning curve if you're not used to it, but it just takes practice.

[–] [email protected] 1 points 9 months ago (1 children)

Ok how about this then, I frequently do something like this:

let className = 'btn'
  if (displayType) {
    className += ` ${displayType}`
  }
  if (size) {
    className += ` ${size}`
  }
  if (bordered) {
    className += ' border'
  }
  if (classNameProp) {
    className += ` ${classNameProp}`
  }

How would this be made better with a functional approach? And would be more legible, better in anyway?

[–] [email protected] 1 points 9 months ago* (last edited 9 months ago) (1 children)

I'd say this example doesn't fully show off what immutable data can do--it tends to help as things scale up to much larger code--but here's how I might do it in JS.

function generate_class_name( display_type, size, bordered, class_name_prop ) 
{
  classes = [
      'btn',
      ( display_type ? display_type : [] ),
      ( size ? size : [] ),
      ( bordered ? bordered : [] ),
      ( class_name_prop ? class_name_prop : [] ),
  ];

  return classes.flat().join( " " );
}

console.log( "<"
    + generate_class_name( "mobile", "big", null, null )
    + ">" );
console.log( "<"
    + generate_class_name( "desktop", "small", "solid", "my-class" ) 
    + ">" );
console.log( "<"
    + generate_class_name( null, "medium", null, null ) 
    + ">" );

Results:

<btn mobile big>
<btn desktop small solid my-class>
<btn medium>

Notice that JavaScript has a bit of the immutability idea built in here. The Array.flat() returns a new array with flattened elements. That means we can chain the call to Array.join( " " ). The classes array is never modified, and we could keep using it as it was. Unfortunately, JavaScript doesn't always do that; push() and pop() modify the array in place.

This particular example would show off its power a little more if there wasn't that initial btn class always there. Then you would end up with a leading space in your example, but handling it as an array this way avoids the problem.

[–] [email protected] 2 points 9 months ago

Very interesting. Actually the part you mention about there being an initial 'btn' class is a good point. Using arrays and joining would be nice for that. I wish more people would chime in. Because between our two examples, I think mine is more readable. But yours would probably scale better. I also wonder about the performance implications of creating arrays. But that might be negligible.