Most active commenters
  • LogicHound(6)
  • kragen(5)
  • gf000(4)
  • rapind(3)
  • umanwizard(3)
  • mrsmrtss(3)
  • skeezyjefferson(3)
  • bmitc(3)

←back to thread

498 points azhenley | 87 comments | | HN request time: 1.093s | source | bottom
1. munchler ◴[] No.45767832[source]
> 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.

replies(19): >>45767880 #>>45767882 #>>45767891 #>>45767892 #>>45767898 #>>45767926 #>>45767975 #>>45767989 #>>45768118 #>>45768188 #>>45768230 #>>45769840 #>>45769875 #>>45770104 #>>45770306 #>>45771134 #>>45771926 #>>45772136 #>>45775848 #
2. Terr_ ◴[] No.45767880[source]
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.

3. Freedom2 ◴[] No.45767882[source]
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.
replies(1): >>45769413 #
4. josephg ◴[] No.45767891[source]
> 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++.

replies(3): >>45768692 #>>45769193 #>>45769524 #
5. ehsankia ◴[] No.45767892[source]
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.

6. tasn ◴[] No.45767898[source]
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.

replies(7): >>45767931 #>>45768098 #>>45768136 #>>45769309 #>>45770165 #>>45771129 #>>45772143 #
7. the__alchemist ◴[] No.45767926[source]
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.

replies(1): >>45768081 #
8. ◴[] No.45767931[source]
9. jandrewrogers ◴[] No.45767975[source]
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.

replies(6): >>45768501 #>>45769165 #>>45769360 #>>45770644 #>>45771080 #>>45771947 #
10. keeda ◴[] No.45767989[source]
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.

replies(1): >>45771913 #
11. cogman10 ◴[] No.45768081[source]
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.

replies(2): >>45769322 #>>45774944 #
12. rapind ◴[] No.45768098[source]
> come with the baggage of foreign looking syntax

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

replies(1): >>45768148 #
13. charcircuit ◴[] No.45768118[source]
Const by default is not functional programming.
replies(1): >>45768144 #
14. kragen ◴[] No.45768136[source]
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.
replies(1): >>45768441 #
15. umanwizard ◴[] No.45768144[source]
Indeed, but it's one of the (many) good ideas from functional programming that have filtered into more mainstream languages.
16. kragen ◴[] No.45768148{3}[source]
Which one, Erlang, Lisp, or ML?
replies(3): >>45768958 #>>45770119 #>>45771398 #
17. brrrrrm ◴[] No.45768188[source]
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.

replies(1): >>45768228 #
18. runevault ◴[] No.45768228[source]
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.
replies(1): >>45770194 #
19. johncolanduoni ◴[] No.45768230[source]
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.

20. tayo42 ◴[] No.45768441{3}[source]
Using a big array has good performance though?
replies(2): >>45768613 #>>45770186 #
21. jancsika ◴[] No.45768501[source]
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

22. kragen ◴[] No.45768613{4}[source]
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.
23. bathtub365 ◴[] No.45768692[source]
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)
replies(2): >>45769515 #>>45769534 #
24. nickpeterson ◴[] No.45768958{4}[source]
Honestly I find ML derived languages the most pleasant to look at.
25. Fire-Dragon-DoL ◴[] No.45769165[source]
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
replies(1): >>45769353 #
26. Fire-Dragon-DoL ◴[] No.45769193[source]
In typescript and js you get immutable references, but the data is mutable. Definitely not the same thing
replies(1): >>45769942 #
27. rao-v ◴[] No.45769309[source]
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

replies(2): >>45769657 #>>45772200 #
28. v9v ◴[] No.45769322{3}[source]
> 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.

replies(1): >>45769571 #
29. black_knight ◴[] No.45769353{3}[source]
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.

30. christophilus ◴[] No.45769360[source]
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.
replies(1): >>45770985 #
31. jeffreygoesto ◴[] No.45769413[source]
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.

32. orlp ◴[] No.45769515{3}[source]
Rust works this way, yes. There are escape hatches though, which allow interior mutability.
replies(1): >>45769554 #
33. eitland ◴[] No.45769524[source]
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

replies(1): >>45769616 #
34. umanwizard ◴[] No.45769534{3}[source]
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.
35. snalty ◴[] No.45769554{4}[source]
Yeah, here's an example: https://play.rust-lang.org/?version=stable&mode=debug&editio...
36. umanwizard ◴[] No.45769571{4}[source]
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.

37. haspok ◴[] No.45769616{3}[source]
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
38. tjk ◴[] No.45769657{3}[source]
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.
replies(1): >>45769893 #
39. otikik ◴[] No.45769840[source]
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".
40. LogicHound ◴[] No.45769875[source]
> 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.

41. LogicHound ◴[] No.45769893{4}[source]
I can't stand modern C#. They've bung in a bunch of new keywords and features that are of dubious benefit every release.
replies(1): >>45770079 #
42. dougherty ◴[] No.45769942{3}[source]
You have `as const`. Yes I know it's not enforced at runtime, but the type system does support it.
replies(1): >>45771358 #
43. mrsmrtss ◴[] No.45770079{5}[source]
I'm interested what are those new keywords and features that are of dubious benefit?
replies(1): >>45770216 #
44. gf000 ◴[] No.45770104[source]
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)

replies(1): >>45772209 #
45. tmtvl ◴[] No.45770119{4}[source]
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.
replies(1): >>45773270 #
46. gf000 ◴[] No.45770165[source]
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.

replies(1): >>45772360 #
47. gf000 ◴[] No.45770186{4}[source]
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.
48. gf000 ◴[] No.45770194{3}[source]
For what it's worth, Haskell has plenty of escape hatches itself as well.
49. LogicHound ◴[] No.45770216{6}[source]
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.
replies(2): >>45770743 #>>45772955 #
50. physicles ◴[] No.45770306[source]
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.

51. internet_points ◴[] No.45770644[source]
> 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.

52. mrsmrtss ◴[] No.45770743{7}[source]
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...

replies(2): >>45771155 #>>45771865 #
53. pvdebbe ◴[] No.45770985{3}[source]
Same. I strikes me a great shame that there aren't great F#-like languages that targeted the JVM.
replies(1): >>45771956 #
54. fsloth ◴[] No.45771080[source]
"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.

55. theSIRius ◴[] No.45771129[source]
> 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.

56. skeezyjefferson ◴[] No.45771134[source]
> If you want a language where const is the default and mutable is a keyword

whats the difference between const and mutable?

replies(1): >>45771189 #
57. LogicHound ◴[] No.45771155{8}[source]
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.

replies(1): >>45771476 #
58. Thorrez ◴[] No.45771189[source]
"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.

replies(1): >>45771571 #
59. danenania ◴[] No.45771358{4}[source]
There’s Object.freeze for enforcing at runtime.
60. rapind ◴[] No.45771398{4}[source]
ML superfan here. I don’t mind lisp simplicity either. Erlang is too alien for me, but maybe once I was used to it.
replies(1): >>45772580 #
61. mrsmrtss ◴[] No.45771476{9}[source]
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#?
replies(1): >>45771890 #
62. alcover ◴[] No.45771571{3}[source]
> you don't need both a "const" keyword and a "mutable" keyword

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

replies(2): >>45773144 #>>45781369 #
63. skeezyjefferson ◴[] No.45771865{8}[source]
> 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) { ... }

64. LogicHound ◴[] No.45771890{10}[source]
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.

65. johnisgood ◴[] No.45771913[source]
Just use OCaml in which you can mix imperative, functional, and OOP. I use all of them in a single codebase, whichever, wherever appropriate.
66. bmitc ◴[] No.45771926[source]
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.

67. bmitc ◴[] No.45771947[source]
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.

68. bmitc ◴[] No.45771956{4}[source]
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.
69. danenania ◴[] No.45772136[source]
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.

70. dragonwriter ◴[] No.45772143[source]
> 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.

71. dionian ◴[] No.45772200{3}[source]
Scala
72. dionian ◴[] No.45772209[source]
Worth nothing that idiomatic scala uses constants by default, variables are discouraged and frankly rare.
73. acdha ◴[] No.45772360{3}[source]
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.
74. impossiblefork ◴[] No.45772580{5}[source]
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.

replies(3): >>45772801 #>>45775112 #>>45777269 #
75. rapind ◴[] No.45772801{6}[source]
I disagree, at least for my own case. I greatly prefer reading ML code than C style syntax.
76. 1718627440 ◴[] No.45772955{7}[source]
In Python '==' and 'is' are not the same thing. '==' checks for equality, 'is' for identity.
replies(1): >>45773665 #
77. skeezyjefferson ◴[] No.45773144{4}[source]
compiler flags with line and column number seems like the easiest way
78. kragen ◴[] No.45773270{5}[source]
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.
79. LogicHound ◴[] No.45773665{8}[source]
I am aware. I probably should have said "inspired".
80. valcron1000 ◴[] No.45774944{3}[source]
> 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

replies(1): >>45775484 #
81. runevault ◴[] No.45775112{6}[source]
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).

82. cogman10 ◴[] No.45775484{4}[source]
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).

83. themafia ◴[] No.45775848[source]
I want a language that helps me write software. I do not need a language that's hellbent on expressing a particular ideology.
84. kragen ◴[] No.45777269{6}[source]
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.
replies(1): >>45781214 #
85. impossiblefork ◴[] No.45781214{7}[source]
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.
86. Thorrez ◴[] No.45781369{4}[source]
You can make everything read-only by default, and if you need non-read-only, you use "mutable".
replies(1): >>45784475 #
87. alcover ◴[] No.45784475{5}[source]
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