Live data from Hacker News

John Carmack on mutable variables

twitter.com

481–490 of 663 posts

Re: John Carmack on mutable variables

#481

I'm curious where this fits in with single assignment semantics: int x = 3; x = 4; // error! int* p = &x; *p = 4; // is that an error?

At least with clang it's a warning:

    f.c:4:8: warning: initializing 'int *' with an expression of type 'const int     *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
    4 |   int* p = &x;
      |        ^   ~~
    1 warning generated.

Re: John Carmack on mutable variables

#483
post #341

Earlier quoted context omitted.

I guess I'm not that good a programmer, because I don't really understand why variables that can't be varied are useful, or why you'd use that. How do you write code that actually works?

If you need new values you just make new things. If you want to do an operation on fooA, you don't mutate fooA. You call fooB = MyFunc(fooA) and use fooB. The nice thing here is you can pass around pointers to fooA and never worry that anything is going to change it underneath you. You don't need to protect private variables because your internal workings cannot be mutated. Other code can copy it but not disrupt it.

> If you need new values you just make new things. > If you want to do an operation on fooA, you don't mutate fooA. You call fooB = MyFunc(fooA) and use fooB.

The beautiful thing about this is you can stop naming things generically, and can start naming them specifically what they are. Comprehension goes through the roof.

Re: John Carmack on mutable variables

#485

Earlier quoted context omitted.

You're using really generic terms which I have to think is mostly because you're talking about it in the abstract. In most scenarios I find there are obvious non-generic names I can use for each step of a calculation.

I mean, I use `result` in a function named `generate` within a class `JSON < Generator`. Stuff like this is pretty common.

> Stuff like this is pretty common.

Common != Good

Re: John Carmack on mutable variables

#486

I try to keep deeper mutation to where it belongs, but I'll admit to shadowing variables pretty often. If I have a `result` and I need to post-process it. I'm generally much happier doing `result = result.process()` rather than having something like `preresult`. Works nicely in cases where you end up moving it into a condition, or commenting it out to test an assumption while developing. If there's an obvious name fo…

> result.process()

What result? What process?

...says every person who has to read your code later.

Re: John Carmack on mutable variables

#487
post #404

Earlier quoted context omitted.

A more common example for me at work is getting a response from url. Then you gotta process it further like response.json() or response.header or response.text etc etc. and then again select the necessary array index or doc value from it. Giving a name like pre_result or result_json etc etc would just become cumbersome.

I would never do `response = response.json()`. I use it when it's effectively the same type, but with further processing which may be optional.

Depends on how clear it is.

I usually write code to help local debug-ability (which seems rare). For example, this allows one to trivially set a conditional breakpoint and look into the full response:

    response = get_response()
    response = response.json()
The fact that the first response is immediately overwritten proves to the reader it's not important/never used, so they can forget about it, where a temp variable would add cognitive load since it might be used later.

and I think is just as clear as this:

    response = get_response().json()

This motivated by years of watching people through code, and me working with deeply non-software engineers, and is always very much appreciated.

Re: John Carmack on mutable variables

#488
post #185

Earlier quoted context omitted.

The way I like to think about is that with immutable data as default and pure functions, you get to treat the pure functions as black boxes. You don't need to know what's going on inside, and the function doesn't need to know what's going on in the outside world. The data shape becomes the contract. As such, localized context, everywhere, is perhaps the best way to explain it from the point of view of a mutable world…

Sure modularity, encapsulation etc are great tools for making components understandable and maintainable. However, don't you still need to understand the entire program as ultimately that's what you are trying to build. And if the state of the entire programme doesn't change - then nothing has happened. ie there still has to be mutable state somewhere - so where is it moved to?

A pretty basic example: I write a lot of data pipelines in Julia. Most of the functions don't mutate their arguments, they receive some data and return some data. There are a handful of exceptions, e.g. the functions that write data to a db or file somewhere, or a few performance-sensitive functions that mutate their inputs to avoid allocations. These functions are clearly marked.

That means that 90% of the time, there's a big class of behavior I just don't need to look for when reading/debugging code. And if it's a bug related to state, I can pretty quickly zoom in on a few possible places where it might have happened.

Re: John Carmack on mutable variables

#489
post #226

Earlier quoted context omitted.

ML superfan here. I don’t mind lisp simplicity either. Erlang is too alien for me, but maybe once I was used to it.

If you start programming in it though, syntax only matters during the first day. Familiarity comes very fast, and if you do five programming exercises, maybe one a day, 'implement a hash map', 'make a small game', etc. you will have no problems whatsoever once the week is done. If you have a course where one day you're supposed to do Haskell and another Erlang, and another LISP, and another Prolog, and there's only o…

Eh, I'd say it depends.

I write way more algol-derived language code than ML, yet piped operations being an option over either constant dot operators where every function returns the answer or itself depending on the context or inside out code is beautiful in a way that I've never felt about my C#/C++/etc code. And even Lisp can do that style with arrow macros that exist in at least CL and Clojure (dunno about Racket/other schemes).

Re: John Carmack on mutable variables

#490
post #272
post #12

How fast this got to the top, you would think John Carmack just invented nuclear fusion.

People worship this guy, but other than being a good C++ graphics programmer, it isn't clear what he's actually done.

Well some people do, I'm sure, but most people just pay ordinary levels of attention to him. And they do that because he's made interesting contributions to multiple products that people like using - which is enough, surely?

(Regarding this specific tweet, this seems to be him visiting his occasional theme of how to write C++ in a way that will help rather than hinder the creation of finishable software products. He's qualified to comment.)

Post reply on HN