Top
Best
New

Posted by azhenley 3 days ago

John Carmack on mutable variables(twitter.com)
502 points | 602 commentspage 2
bitbasher 2 days ago|
> ... making almost every variable const at initialization is good practice. I wish it was the default, and mutable was a keyword.

Rust mentioned!

willismichael 2 days ago||
Here's a relevant comment on Rust: https://x.com/ID_AA_Carmack/status/1094419108781789184
maleldil 2 days ago||
That was 6 years ago. I'd like to see how that feeling developed.
scuff3d 2 days ago|||
And Zig :)
alternatex 2 days ago||
Plus F# and a whole family of FP languages.
RamtinJ95 2 days ago||
[dead]
y0ned4 2 days ago||
When I started programming in Haskell, where all variables are immutable, I felt like I was in a straitjacket

Then, suddenly, the enlightenment

blub 2 days ago||
How do you know it’s real? When one is in a straitjacket for a long time, the trauma might make the mind disassociate from the body, giving an illusion of freedom.

The brain is essentially dreaming it’s escaped while the body is still programming in Java.

archerx 2 days ago||
That made me laugh, thank you.
kypro 2 days ago|||
I've had this experience with going from PHP and JS to typed languages. Many years ago I was a type sceptic, but after being forced to use them, I now can't stand not having strict typing.

I'm sure others have written about this, but these days I think good code is code which has a very small area of variability. E.g code which returns a value in a single place as a single type, has a very limited number of params (also of single type), and has no mutable variables. If you can break code into chunks of highly predictable logic like this it's so so much easier to reason about your code and prevent bugs.

Whenever I see methods with 5+ params and several return statements I can almost guarantee there will be subtle bugs.

kalaksi 2 days ago|||
I initially started programming with C++, then did a bunch of scripting languages and then Rust and C#. I feel like there are pros and cons to strictness.

I don't like all scripting languages, but Python, for example, has a simple syntax and is easy and fast to learn and write. I think it also has a good standard library. Some things can be simpler because of the missing guardrails. But that's also the weakness and I wouldn't use it for large and complex software. You have to be more mindful to keep a good style because of the freedoms.

C++ and Rust are at the opposite end. Verbose to write and more difficult syntax. More stuff to learn. But in the end, that's the cost for better guarantees on correctness. But again, they don't fit all use cases as well as scripting languages.

I've experienced the good and the bad in both kind of languages. There are tradeoffs (what a surprise) and it's probably also subjective what kind of language one prefers. I think my _current_ favorites are Rust, C# and Python.

maleldil 2 days ago||||
> Whenever I see methods with 5+ params

I don't see why that's a problem. If a function implements an algorithm with several parameters (e.g. a formula with multiple variables), those values have to be passed somehow. Does it make a difference if they're in a configuration object or as distinct parameters?

runevault 2 days ago|||
Personally I'd tweak your last sentence to "return statements in the middle of a function."

Early returns at the very top for things like None if you pass in an Option type don't increase the risk of bugs, but if you have a return nested somewhere in the middle it makes it easier to either write bugs up front or especially have bugs created during a refactor. I certainly have had cases where returns in the middle of a beefy function caused me headaches when trying to add functionality.

criddell 2 days ago|||
How does Haskell deal with things like memory-mapped I/O or signal handlers where the value of a variable can be changed by factors outside of the programmer's control?
how_gauche 2 days ago|||
Side effecting computations that depend on the "real world" go into an IO monad. The game in Haskell is shifting as much of the codebase as possible into pure functions/non-side-effecting code, because it's easier to reason about and prove correct.
chuckadams 2 days ago|||
IORefs usually, which can only be manipulated within the IO monad, so they tend to only get used at the top level and passed down to pure functions as parameters.
chuckadams 2 days ago|||
The lovely thing with Haskell is you have the ST monad that lets you have as many mutable variables as you want, as long as they stay within ST.
or_am_i 2 days ago||
In JetBrains editors it's possible to highlight mutable variables, at least in the languages where the distinction exists. My go to setting in Kotlin is to underscore all `var`'s, for two reasons:

- this makes them really stand out, much easier to track the mutation visually,

- the underscore effect is intrusive just-enough to nudge you to think twice when adding a new `var`.

Nothing like diving into a >3k lines PR peppered with underscores.

omnicognate 2 days ago||
> In C/C++, making almost every variable const at initialization is good practice. I wish it was the default, and mutable was a keyword.

I know it's irrelevant to his point, and it's not true of C, and it doesn't have the meaning he wants, but the pedant in me is screaming and I'm surprised it hasn't been said in the comments:

In C++ mutable is a keyword.

tsimionescu 2 days ago|
It's also really funny, since C++ is like a malicious genie with this. The author wished for mutable to be a keyword, and C++ made the wish come true: it's a keyword that removes some of the guarantees of const!
munchler 3 days ago||
> Making almost every variable const at initialization is good practice. I wish it was the default, and mutable was a keyword.

It's funny how functional programming is slowly becoming the best practice for modern code (pure functions, no side-effects), yet functional programming languages are still considered fringe tech for some reason.

If you want a language where const is the default and mutable is a keyword, try F# for starters. I switched and never looked back.

jandrewrogers 3 days ago||
Pure functional works great until it doesn't. For a lot of systems-y and performance-oriented code you need the escape hatches or you'll be in for a lot of pain and annoyance.

As a practical observation, I think it was easier to close this gap by adding substantial functional capabilities to imperative languages than the other way around. Historically, functional language communities were much more precious about the purity of their functional-ness than imperative languages were about their imperative-ness.

fsloth 2 days ago|||
"Pure functional works great until it doesn't. "

That's why F# is so great.

Functional is default, but mutable is quite easy to do with a few mutable typedefs.

The containers are immutable, but nobody stops you from using the vanilla mutable containers from .net

It's such a beautiful, pragmatic language.

bmitc 2 days ago||||
F# is not a pure functional language. It is a functional-first language that does imperative and OOP better than imperative and OOP languages.

You can program F# just like you would Python, and it will be more readable, concise, performant, and correct.

Fire-Dragon-DoL 3 days ago||||
Unfortunately unless there's an explicit way to state what has side effects like a mut keyword, a lot of fp programming advantages lose value because most devs default to mutable stuff, so the fp benefits don't compound
black_knight 2 days ago||
I think this works quite well with IO in Haskell. Most of my code is pure, but the parts which are really not, say OpenGL code, is all marked as such with IO in their type signatures.

Also, the STM monad is the most carefree way of dealing with concurrency I have found.

christophilus 2 days ago||||
F# isn’t purely functional, though, and strikes a nice balance. I just don’t really like the .NET ecosystem, being 100% Linux these days, as it always seems slightly off to me somehow.
pvdebbe 2 days ago||
Same. I strikes me a great shame that there aren't great F#-like languages that targeted the JVM.
bmitc 2 days ago||
Really? What's wrong with .NET? It's one of the nicest cross-platform platforms out there. What Microsoft has done with it is amazing.
jancsika 3 days ago||||
Hehe, purity is one helluva drug!

For some reason, this makes me think of SVG's foreignObject tag that gives a well-defined way to add elements into an SVG document from an arbitrary XML namespace. Display a customer invoice in there, or maybe a Wayland protocol. The sky's the limit!

On the other hand, HTML had so many loose SVG tags scattered around the web that browsers made a special case in the parser to cover them without needing a namespace.

And we all know how that played out.

Posted from an xhtml foreignObject on my SVGphone

internet_points 2 days ago|||
> you need the escape hatches

Isn't this a strawman? Even Haskell has unsafePerformIO and Debug.Trace etc. It just also provides enough ergonomics that you don't need them so often, and they "light up" when you see them, which is what we want: to know when we're mutating.

josephg 3 days ago|||
> If you want a language where const is the default and mutable is a keyword, try F# for starters. I switched and never looked back.

Rust is also like this (let x = 5; / let mut x = 5;).

Or you can also use javascript, typescript and zig like this. Just default to declaring variables with const instead of let / var.

Or swift, which has let (const) vs var (mutable).

FP got there first, but you don't need to use F# to have variables default to constants. Just use almost any language newer than C++.

eitland 2 days ago|||
In Java you can use final[1]. And yes, if final points to an ArrayList you can change it, but you can also use final together with immutable data structures[2].

[1]: https://www.baeldung.com/java-final

[2]: https://www.baeldung.com/java-immutable-list

haspok 2 days ago||
Did you know that "final" does not actually mean final in Java (as in: the variable can be constant folded)? Reasons include reflection and serialization (the feature that nowadays nobody uses, but due to backwards compatibility the Java language developers always have to worry about?). There was an excellent talk about this recently, I think triggered by a new JEP "stable values": https://youtu.be/FLXaRJaWlu4
Fire-Dragon-DoL 3 days ago||||
In typescript and js you get immutable references, but the data is mutable. Definitely not the same thing
dougherty 2 days ago||
You have `as const`. Yes I know it's not enforced at runtime, but the type system does support it.
danenania 2 days ago||
There’s Object.freeze for enforcing at runtime.
bathtub365 3 days ago|||
Are there languages that automatically extend this to things like data structure members? One of the things I like about the C++ const keyword is that if you declare an instance of a struct/class as const it extends that to its members. If the instance isn’t const, you can still mutate them (as long as they aren’t declared const within the structure itself)
orlp 2 days ago|||
Rust works this way, yes. There are escape hatches though, which allow interior mutability.
snalty 2 days ago||
Yeah, here's an example: https://play.rust-lang.org/?version=stable&mode=debug&editio...
umanwizard 2 days ago|||
If I understand what you’re asking correctly, rust is also like this. If you have a non-mut value of (or non-mut reference to) an object, you only get non-mut access to its members.
physicles 2 days ago|||
Agreed, and Carmack as always was ahead of the curve here.

In case anyone here hasn’t seen it, here’s his famous essay, Functional Programming in C++:

http://sevangelatos.com/john-carmack-on/

He addresses your point:

> I do believe that there is real value in pursuing functional programming, but it would be irresponsible to exhort everyone to abandon their C++ compilers and start coding in Lisp, Haskell, or, to be blunt, any other fringe language. To the eternal chagrin of language designers, there are plenty of externalities that can overwhelm the benefits of a language, and game development has more than most fields.

tasn 3 days ago|||
Functional programming languages (almost always?) come with the baggage of foreign looking syntax. Additionally, imperative is easier in some situations, so having that escape hatch is great.

I think that's why we're seeing a lot of what you're describing. E.g. with Rust you end up writing mostly functional code with a bit of imperative mixed in.

Additional, most software is not pure (human input, disk, network, etc), so a pure first approach ends up being weird for many people.

At least based on my experience.

kragen 3 days ago|||
Rust is not very suitable for functional programming because it is aggressively non-garbage-collected. Any time Rustaceans want to do the kind of immutable DAG thing that gives functional languages so much power, they seem to end up either taking the huge performance and concurrency hit of fine-grained reference counting, or they just stick all their nodes in a big array.
tayo42 3 days ago||
Using a big array has good performance though?
kragen 3 days ago|||
Computer memory is already a big array. Probably what you are thinking of is that processing array items sequentially is a lot faster than following pointers, but in the cases I'm talking about, you end up using array indices instead of pointers, which isn't much faster.
gf000 2 days ago|||
Yeah, but now logic bugs can cause memory leaks, doing use-after-frees, etc, without any kind of tooling to prevent it (nothing like valgrind to catch them). Sure, they won't crash the program, but sending money from a wrong account is worse than a segfault, imo.
gf000 2 days ago||||
Foreign looking is just a person's biases/experience. C is just as foreign looking to a layperson, you just happened to start programming with C-family languages. (Also, as a "gotcha" counterpoint, I can just look up a Haskell symbol in hoogle, but the only language that needs a website to decipher its gibberish type notation is C https://cdecl.org/ )

Nonetheless, I also heavily dislike non-alphabetical, library-defined symbols (with the exception of math operators), but this is a cheap argument and I don't think this is the primary reason FPs are not more prevalent.

acdha 2 days ago||
I think you could construct a stronger version of this complaint as FP languages not prioritizing usability enough. C was never seen as a great language but it was relatively simple to learn to the point that you could have running code doing something you needed without getting hit with a ton of theory first. That code would probably be unsafe in some way but the first impression of “I made a machine do something useful!” carries a lot of weight and anyone not starting with an academic CS background would get that rush faster with most mainstream languages.
rapind 3 days ago||||
> come with the baggage of foreign looking syntax

Maybe they're right about the syntax too though? :)

kragen 3 days ago||
Which one, Erlang, Lisp, or ML?
tmtvl 2 days ago|||
Lisp syntax is objectively superior because you can write a predicate like thus:

  (< lower-bound x-coordinate upper-bound)
Instead of having to do the awful ampersand dance.
kragen 2 days ago||
In Python or Icon (or Unicon) that's

    lower_bound < x_coordinate < upper_bound
except that usually you want

    lower_bound <= x_coordinate < upper_bound
which is also legal.

In Python this is a magical special case, but in Icon/Unicon it falls out somewhat naturally from the language semantics; comparisons don't return Boolean values, but rather fail (returning no value) or succeed (returning a usually unused value which is chosen to be, IIRC, the right-hand operand).

And in SQL you have

    `x-coordinate` between `lower-bound` - 1 and `upper-bound` + 1
which is obviously the best possible syntax.
rapind 2 days ago||||
ML superfan here. I don’t mind lisp simplicity either. Erlang is too alien for me, but maybe once I was used to it.
impossiblefork 2 days ago||
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 one exercise in each language, then you're obviously going to have to waste a lot of time on syntax, but that's never a situation you encounter while actually programming.

kragen 2 days ago|||
This is far from true in my experience. I'm no Lisp hater (I wrote a self-compiling compiler in Scheme) but different syntaxes have dramatically different degrees of familiarity, like Latin letters and Cyrillic. How long do you think it would take you to learn to read phonetically in Cyrillic as fast as you do in the Latin script? It takes the humans months or years, if they ever arrive. But, also, some notations are more usable than others, even for experts, just as with other kinds of user interfaces. Flat is better than nested, simple is better than complex, complex is better than complicated, Perl and MUMPS are unnecessarily error-prone, etc.
impossiblefork 1 day ago||
I shouldn't have mentioned LISP because I don't use it and I actually find the parentheses to be annoying, but it's a paradigm and you need them. Cyrillic at full speed is obviously weeks. But Erlang is very math-notation-y and when I introduced people to some Erlang code I'd written they understood it once I'd given a presentation on it and were then able to do similar things.
rapind 2 days ago||||
I disagree, at least for my own case. I greatly prefer reading ML code than C style syntax.
runevault 2 days ago|||
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).

nickpeterson 3 days ago|||
Honestly I find ML derived languages the most pleasant to look at.
kragen 14 hours ago||
I prefer Piet, but it has some real drawbacks when it comes to readability: https://www.dangermouse.net/esoteric/piet/samples.html
dragonwriter 2 days ago||||
> Functional programming languages (almost always?) come with the baggage of foreign looking syntax.

That increases the activation energy, I guess, for people who have spent their whole programming life inside the algol-derived syntax set of languages, but that’s a box worth getting out of independently of the value of functional programming.

theSIRius 2 days ago||||
> Functional programming languages (almost always?) come with the baggage of foreign looking syntax.

At least for me, this was solved by Gleam. The syntax is pretty compact, and, from my experience, the language is easily readable for anyone used to C/C++/TypeScript and even Java.

The pure approach may be a bit off-putting at first, but the apprehensions usually disappear after a first big refactoring in the language. With the type system and Gleam's helpful compiler, any significant changes are mostly a breeze, and the code works as expected once it compiles.

There are escape hatches to TypeScript/JavaScript and Erlang when necessary. But yeah, this does not really solve the impure edges many people may cut themselves on.

rao-v 2 days ago||||
Exactly this! I’d love a modern C++ like syntax with the expressiveness of python and a mostly functional approach.

C# is not that far I suppose from what I want

tjk 2 days ago|||
Everybody's mileage will vary, but I find contemporary C# to be an impressively well rounded language and ecosystem. It's wonderfully boring, in the most positive sense of the word.
LogicHound 2 days ago||
I can't stand modern C#. They've bung in a bunch of new keywords and features that are of dubious benefit every release.
mrsmrtss 2 days ago||
I'm interested what are those new keywords and features that are of dubious benefit?
LogicHound 2 days ago||
There is a huge amount of syntactic sugar that has been added over the years that doesn't do whole lot IMO. It is often imported from other languages (usually JavaScript and/or Python).

e.g. Just a very simple example to illustrate the point

    if (customer != null)
    {
        customer.Order = GetCurrentOrder();
    }
vs

    if (customer is not null)
    {
        customer.Order = GetCurrentOrder();
    }
Is there really any benefit in adding "is/is not"? I would argue no. So I categorise that as being of "dubious benefit" and there are many similar small features, keywords etc. that get added each release where they might save a few lines of code somewhere but I've never seem them used that often.
mrsmrtss 2 days ago|||
In your sample there really is no benefit to using the "is" operator over just checking for null (assuming you haven't overloaded the "!=" operator). However, the "is" operator is a lot more powerful, you can match an expression against a pattern with it. Would you say that these samples show no benefit to using the "is" operator?

if (obj is string s) { ... }

if (date is { Month: 10, Day: <=7, DayOfWeek: DayOfWeek.Friday }) { ... }

https://learn.microsoft.com/en-us/dotnet/csharp/language-ref... https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...

skeezyjefferson 2 days ago|||
> In your sample there really is no benefit to using the "is" operator over just checking for null

Microsoft give the same example though. I understand what hes saying, theres conceptual overlap between is and ==. Many ways to do the same thing.

Why couldnt it just be...

if (obj == string s) { ... }

LogicHound 2 days ago|||
The issue is that I dislike the overall mentality of just adding a bunch of language features. Things just seem to be dumped in each release and I think to myself "When I am going to use that?".

> Would you say that these samples show no benefit to using the "is" operator?

I didn't say no benefit. I said dubious benefit.

I didn't really want to get into discussing specific operators, but lets just use your date example:

   if (date is { Month: 10, Day: <=7, DayOfWeek: DayOfWeek.Friday }) { ... }
This following would do the same thing before the is operator:

    static bool IsFirstFridayOfOctober(DateTime date)
    {
        return date.Month == 10
            && date.Day <= 7
            && date.DayOfWeek == DayOfWeek.Friday;
    }
And then:

    if IsFirstFridayOfOctober(date) {
       ...
    }
I understand it is more verbose. But do we really need a new operator for this? I was getting on fine without it.

Each release there seems to be more of these language features and half the time I have a hard time remembering that they even exist.

Each time I meet with other .NET developers either virtually or in Person they all seem to be salivating over this stuff and I feel like I've walked in on some sort of cult meeting.

rao-v 5 hours ago|||
I have to admit this really does seem like beautiful syntactic sugar despite me not being a fan of accumulating keywords in languages. Your example of writing a function instead of a neat little lambda is clunkier to quickly scan for correctness.
mrsmrtss 2 days ago|||
I agree that they should not add new stuff lightly, but the "is" operator actually should be looked together with switch expression in the context of pattern matching. How else could you enable powerful and succint pattern matching in c#?
LogicHound 2 days ago||
Arguments about whether the is and switch operators should exist is missing the forest for the trees. I am sure there are circumstances where it very useful.

It isn't any one language feature it is the mentality of both the developer community and Microsoft.

> I agree that they should not add new stuff lightly

It seems though kinda do though. I am not the first person to complain that they add syntactic sugar that doesn't really benefit anything.

e.g. https://devclass.com/2024/04/26/new-c-12-feature-proves-cont...

I have a raft of other complaints outside of language features. Some of these are to do with the community itself which only recognise something existing when Microsoft has officially blessed it, it is like everyone has received the official permission to talk about a feature. Hot Reload was disabled in .NET 6 IIRC for dubious reasons.

1718627440 2 days ago|||
In Python '==' and 'is' are not the same thing. '==' checks for equality, 'is' for identity.
LogicHound 2 days ago||
I am aware. I probably should have said "inspired".
dionian 2 days ago|||
Scala
keeda 3 days ago|||
We are still living with the hangover of C, which was designed for the resource-starved machines of eons ago, and whose style later languages felt they had to copy to get any kind of adoption. (And as you point out, that is how things turned out.)

My bet is functional programming will become more and more prevalent as people figure out how to get AI-assisted coding to work reliably. For the very reasons you stated, functional principles make the code modular and easy to reason about, which works very well for LLMs.

However, precisely because functional programming languages are less popular and hence under-represented in the training data, AI might not work well with them and they will probably continue to remain fringe.

johnisgood 2 days ago||
Just use OCaml in which you can mix imperative, functional, and OOP. I use all of them in a single codebase, whichever, wherever appropriate.
johncolanduoni 3 days ago|||
I’ve done a significant amount of functional programming (including F#) and still reach for it sometimes, but I don’t think it provides substantial advantages for most use-cases. Local mutability is often clearer and more maintainable.

Also, category theorists think how excited people get about using the word monad but then most don’t learn any other similar patterns (except maybe functors) is super cringe. And I agree.

LogicHound 2 days ago|||
> It's funny how functional programming is slowly becoming the best practice for modern code (pure functions, no side-effects),

I once mentioned both these concepts to a room of C# developers. Two of them were senior to me and it was a blank expression from pretty much everyone.

> yet functional programming languages are still considered fringe tech for some reason.

You can use the same concepts in non-functional programming languages without having to buy into all the other gumpf around functional programming languages. Also other programming languages have imported functional concepts either into the language itself or into the standard libraries.

Past that. It is very rare to be able to get a job using them. The number of F# jobs I've seen advertised over the last decade, I could count on one hand.

brrrrrm 3 days ago|||
one thing I've learned in my career is that escape hatches are one of the most important things in tools made for building other stuff.

dropping down into the familiar or the simple or the dumb is so innately necessary in the building process. many things meant to be "pure" tend to also be restrictive in that regard.

runevault 3 days ago||
Functional languages are not necessarily pure though. Actually outside Haskell don't most functional first languages include escape hatches? F# is the one I have the most experience with and it certainly does.
gf000 2 days ago||
For what it's worth, Haskell has plenty of escape hatches itself as well.
Terr_ 3 days ago|||
While it's amusing, I think it's sensible: One of the main tasks in most businessy programming is to take what a human wants, translate it to code, reverse-translate it back to human understanding later, modify it, and translate it again to slightly different code.

This creates friction between casual stakeholder models of a mutable world, versus the the assumptions an immutable/mostly-pure language imposes. When the customer describes what they need, that might be pretty close to a plain loop with a variable that increments sometimes and which can terminate early. In contrast, it maps less-cleanly to a pure-functional world, if I'm lucky there will at least be a reduce-while utility function, so I don't need to make all my own recursive plumbing.

So immutability and pure-functions are like locking down a design or optimizing--it's not great if you're doing it prematurely. I think that's why starting with mutable stuff and then selectively immutable'ing things is popular.

Come to think of it, something similar can be said about weak/strong typing. However the impact of having too-strong typing seems easier to handle with refactoring tools, versus the problem of being too-functional.

gf000 2 days ago|||
It's because you want a tasteful mix of both.

I believe Scala was pretty ahead here by building the language around local mutability with a general preference for immutable APIs, and I think this same philosophy shows up pretty strongly in Rust, aided by the borrow checker that sort of makes this locality compiler-enforced (also, interior mutability)

dionian 2 days ago||
Worth nothing that idiomatic scala uses constants by default, variables are discouraged and frankly rare.
the__alchemist 3 days ago|||
I think it's because (I'm looking at Haskell in particular) there are a lot of great ideas implemented in them, but the purity makes writing practical or performant time-domain programs high friction. But you don't need both purity and the various tools they provide. You can use the tools without the pure-functions model.

In particular: My brain, my computing hardware, and my problems I solve with computers all feel like a better match for time-domain-focused programming.

cogman10 3 days ago||
My problem with functional languages is there never seems to be any easy way to start using them.

Haskell is a great example here. Last time I tried to learn it, going on the IRC channel or looking up books it was nothing but a flood of "Oh, don't do that, that's not a good way to do things." It seemed like nothing was really settled and everything was just a little broken.

I mean, Haskell has like what, 2, 3, 4? Major build systems and package repositories? It's a quagmire.

Lisp is also a huge train wreck that way. One does not simply "learn lisp" There's like 20+ different lisp like languages.

The one other thing I'd say is a problem that, especially for typed functional languages, they simply have too many capabilities and features which makes it hard to understand the whole language or how to fit it together. That isn't helped by the fact that some programmers love programming the type system rather than the language itself. Like, cool, my `SuperType` type alias can augment an integer or a record and knows how to add the string `two` to `one` to produce `three` but it's also an impossible to grok program crammed into 800 characters on one line.

v9v 2 days ago|||
> Lisp is also a huge train wreck that way. [...] There's like 20+ different lisp like languages.

Lisp is not a language, but a descriptor for a family of languages. Most Lisps are not functional in the modern sense either.

Similarly, there are functional C-like languages, but not all C-likes are functional, and "learn c-likes" is vague the same way "learn lisp" is.

umanwizard 2 days ago||
You’re right and this is also a bit of a pet peeve of mine. “Lisp” hasn’t described a single language for more than forty years, but people still talk about it as if it were one.

Emacs lisp and Clojure are about as similar as Java and Rust. The shared heritage is apparent but the experience of actually using them is wildly different.

Btw, if someone wants to try a lisp that is quite functional in the modern sense (though not pure), Clojure is a great choice.

valcron1000 2 days ago|||
> I mean, Haskell has like what, 2, 3, 4? Major build systems and package repositories? It's a quagmire.

Don't know when was the last time you've used Haskell, but the ecosystem is mainly focused on Cabal as the build tool and Hackage as the official package repository. If you've used Rust:

- rustup -> ghcup - cargo -> cabal - crates.io -> hackage - rustc -> ghc

cogman10 2 days ago||
It's admittedly been years.

ghcup didn't exist, AFAIK. Cabal was around but I think there was a different ecosystem that was more popular at the time (Started with an S, scaffold? Scratch? I can't find it).

Freedom2 3 days ago|||
Decades of blog posts, articles and books about "best practices" led to a suspicion of anything that wasn't bog standard OOP. This site in particular has also contributed to that, especially in the early 2000s, where you can easily find comments disparaging FP.
jeffreygoesto 2 days ago||
I think there's a deeper mechanism in these discussions. They all tend to go "If you do <insert_arbitrary_method_here> fully correct[0], it solves all of your problems."

But [0] is never possible.

themafia 2 days ago|||
I want a language that helps me write software. I do not need a language that's hellbent on expressing a particular ideology.
skeezyjefferson 2 days ago|||
> If you want a language where const is the default and mutable is a keyword

whats the difference between const and mutable?

Thorrez 2 days ago||
"const" means something can't be changed. "mutable" means it can be changed.

You don't need both a "const" keyword and a "mutable" keyword in a programming language. You only need 1 of the keywords, because the other can be the default. munchler is saying the "const" keyword shouldn't exist, and instead all variables should be constant by default, and we should have a "mutable" keyword to mark variables as mutable.

As opposed to how C++ works today, where there is no "mutable" keyword, variables are mutable by default, and we use a "const" keyword to mark them constant.

alcover 2 days ago||
> you don't need both a "const" keyword and a "mutable" keyword

What if the lang has pointers? How express read-only?

Thorrez 1 day ago|||
You can make everything read-only by default, and if you need non-read-only, you use "mutable".
alcover 1 day ago||
You need two keywords. One for assignability and one for writability :

    const ptr;  // can't reassign, can't write-through (if r/o by default)
    const mut ptr;  // can write
skeezyjefferson 2 days ago|||
compiler flags with line and column number seems like the easiest way
bmitc 2 days ago|||
I get your sentiment, but I side on it's infuriating that it's taken this long. Lol.

F# is wonderful. It is the best general purpose language, in my opinion. I looked for F# jobs for years and never landed one and gave up. I write Rust now which has opened up the embedded world, and it's nice that Rust paid attention to F# and OCaml.

otikik 2 days ago|||
Don't get too comfortable, history likes oscillation. If it becomes the norm then someone will have a "actually writing imperatively makes things go super fast".
charcircuit 3 days ago|||
Const by default is not functional programming.
umanwizard 3 days ago||
Indeed, but it's one of the (many) good ideas from functional programming that have filtered into more mainstream languages.
ehsankia 3 days ago|||
functional programming has a lot of wonderful concepts, which are very interesting in theory, but in practice, the strictness of it edges on annoying and greatly hurts velocity.

Python has a lot of functional-like patterns and constructs, but it's not a pure functional language. Similarly, Python these days allow you to adds as much type information as you want which can provide you a ton of static checks, but it's not forced you like other typed languages. If some random private function is too messy to annotate and not worth it, you can just skip it.

I like the flexibility, since it leads to velocity and also just straight up more enjoyable.

danenania 2 days ago||
It’s because FP, great as it is, is most beneficial when 80/20’d.

Trying to do it 100% pure makes everything take significantly longer to build and also makes performance difficult when you need it. It’s also hard to hire/onboard people who can grok it.

swiftcoder 2 days ago||
Rediscovering one of the many great decisions that Erlang made
DarkNova6 2 days ago||
To be fair, Carmack has advocated for immutability and other good practices at least since the 2000s.
signa11 2 days ago|||
erlang predates that.
eps 2 days ago||
I doubt the GP tried to imply the opposite.
signa11 2 days ago||
maybe, i don't really know.

his comment was in response to the

```

    Rediscovering one of the many great decisions that Erlang made
```

and seemed to me to insinuate just that.

rurban 2 days ago|||
Maybe he read SICP then. But he still didn't write a compiler since
gorgoiler 2 days ago||
I still have a habit of naming variables foo0, foo1, foo2, from a time working in Erlang many years ago.
ronnier 3 days ago||
Immutability was gaining huge traction with Java... then large parts of the industry switched to golang and we hardly make anything immutable.
XorNot 2 days ago||
Go desperately needs support for immutable structs that copy cleanly.

I want to be able to write `x := y` and be sure I don't have mutable slices and pointer types being copied unsafely.

ottah 3 days ago|||
I would kill for an immutable error type
antonvs 3 days ago||
Go is the new PHP.
LogicHound 2 days ago||
Much like PHP, you can actually get stuff done unlike a lot of other programming languages.
antonvs 2 days ago||
Oh? Which “lot of” other programming languages can’t you “actually get stuff done” in? Are you sure the problem lies with the programming language?
danenania 2 days ago|||
It’s an exaggeration perhaps but I get the sentiment. FP is elegant and beautiful and everything, but it can lead you to spend all day puzzling out the right abstractions for some data transformation that takes 5 minutes with a dumb for loop in Go.
LogicHound 2 days ago|||
I find there are some environments where you have a positive feedback loop while working in them. PHP is one of them, Go is another at least for me.

I find many of languages I am constantly fighting with dependency managers, upgrades and all sorts of other things.

TheRoque 2 days ago||
I also default to const in javascript. Somehow a "let" variable feels so dirty, but I don't really know why. I guess at this point my experience forged an instinct but I can't even put a theory on it. But it's sometimes necessary and I use it of course.
maleldil 2 days ago||
JS's const doesn't go far enough since you can still mutate the object via its methods. In C++, you can only call const methods (which can't mutate the object) on const variables.
catlifeonmars 2 days ago||
In JS, by using const, you are signalling to the reader that they don’t need to look out for a reassignment to understand the code. If you use let, you are saying the opposite.
duxup 2 days ago||
I'm going to maybe out myself as having limited experience here ...

I don't mind the idea here, seems good. But I also don't move a block of code often and discover variable assignment related issues.

Is the bad outcome more often seen in C/C++ or specific use cases?

Granted my coding style doesn't tend to involve a lot of variables being reassigned or used across vast swaths of code either so maybe I'm just doing this thing and so that's why I don't run into it.

d0mine 2 days ago||
In Python, no user object is modified by a simple assignment to a name. It just binds it.

It is not about mutable/immutable objects , it is about using a name for a single purpose within given scope.

    a = 1
    b = 2
    a = b
"a" name refers to the "2" object. "1" hasn't changed (ints are immutable in Python). If nothing else references it, it might as well disappear (or not).

Though both "single purpose" and immutability may be [distinct] good ideas.

Galanwe 2 days ago||
So essentially he gives 2 arguments:

1) You get intermediate results visible in the debugger / accessible for logs, which I think is a benefit in any language.

2) You get an increased safety in case you move around some code. I do think that it applies to any language, maybe slightly more so in C due to its procedural nature.

See, the following pattern is rather common in C (not so much in C++):

- You allocate a structure S

- If S is used as input, you prefill it with some values. If it's used as output, you can keep it uninitialized or zfill.

- You call function f providing a pointer to that struct.

Lots of C APIs work that way: sockets addresses, time structures, filesystem entries, or even just stack allocated fixed size strings are common.

markstos 2 days ago|
"State is the enemy".

Every new state is an additional condition to check. A mutated variable implies an additional state to test.

One boolean means two states to test. Four booleans that interact is 2^4 (16) states to test.

baruchel 2 days ago|
Which is why functional programmers believe in the separation of Church and state. https://wiki.c2.com/?SeparationOfChurchAndState
More comments...