Have you ever hit F12 on any C++ std function or data structure? Every time I do it genuinely feels like I'm back at day 1 freshman year of an undergrad CS degree.
The problem with C++ template metaprogramming style is symbol length, the notation ordering, and diagnostics generated from those that easily turn into absurdity.
https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a0109...
Honestly I don't think it's that bad if you can look past all the underscores. I looked around for something worse but maybe I'm just accustomed to the eyebleed that C++ has to offer. To me, Rust is uglier, but that's because it's been around a quarter of the time that I've been using C++ and I don't know what all the symbols do without looking up a cheatsheet.
I don't see any fundamental reason why that should be the case. It seems to me that while it's true that most engineers would have a hard time navigating these languages today, it's mostly due to socio-historical accident. It's not because the languages are particularly difficult or arcane, it's mainly because people don't already know it, and people don't like to learn to do things differently: their experience stands in the way.
The main decision I am thinking about is lazy evaluation. Lazy evaluation forces authors to write pure code, which drove Haskell’s community to build libraries that expressed effects in the type system, which made things like STM possible. If I wanted to design a Haskell-like for industry use, I would give it non-lazy evaluation (I’m not gonna say “strict” because I think the compiler should be free to omit the evaluation of any expression, but it sure would be convenient if we had more predictable performance characteristics).
I’m also not saying that you can’t use Haskell in industry. Obviously, people do that.
That said, the type system _does_ stand in the way of learning it - though it's very powerful once you get your head around it - and lazy evaluation means you do spend more time than you'd generally like hunting down space leaks if you're writing the sort of code that's capable of getting space leaks.
It may be subjective, but even for the syntax I felt a much stronger cognitive load working with Haskell.
I beg to differ. I studied compsci BSC at an eastern european university. The professors decided to test that theory and decided to introduce programing to everyone in our program through Haskell. Every year about 500 new students were thaught Haskell. I don’t know a single one of us who stuck with it. Probably there are a few odd ones, but if it were only a question of familiarity you would expect that more people from there would keep programing in it.
A lot of us here have read "Learn You A Haskell for a Great Good". We've used it.
It's not a socio-historical incident, and it's not just beginners who struggle with the language either.
Your point is perfectly valid. I'm just saying the thread has just become a sequence of assertions and not particularly enlightening.
I'm somewhat of a fan of Haskell (though its standard library is awful) and very much a fan of Idris (at the very least it's a better-Haskell, at best, dependent types!), but hard disagree.
These languages are difficult and arcane, compared to eg Python. A beginner to programming can get started with Python immediately, it reads like pseudocode.
Get started with Haskell or Idris, you quickly hit higher kinded types, monad transformers, free monads, final tagless. It's a different universe.
How is any new developer hitting any of these "quickly"? I'm working on a mature production codebase with plenty of advanced Haskell, and we barely have any tagless final code - much less free monads. Even HKDs and monad transformers are relatively recent additions to our toolbox that we reach for when appropriate - most of the code uses plain old datatypes and one or two concrete monad types.
My experience of learning Haskell is that many production codebases use advanced features because they are big boons to productivity, but few learning resources make reference to them. In fact, Haskell's biggest problem is probably the gap in knowledge between simple, low-productivity code written by newer developers, and the kind of code that actually goes into production with all the optional advanced features. A budding developer can easily write a whole application that never goes beyond `IO` without issue.
And yet everyone in my intro to CS class in uni managed to pick up Java within a week or two. Haskell is a bit more involved than Python, but not more involved than most languages.
Rust has ADTs, so I'm not sure what you're saying here. Can you expand on how you think unions would make code nicer than disjoint unions? They definitely make generics much harder to think about for me.
I mean typescript has those because the underlying runtime is Javascript, which tracks the types of stuff and handles some kind of polymorphism, so you can get away with undiscriminated unions because the runtime is doing the job of discriminating them
It was introduced 18 years after JavaScript but feels like a perfectly natural evolution of JavaScript. TypeScript _should_ feel like a wonky bolt on but it’s wonderful. A testament to the folks who built it
Sometimes during the late 2.x series TypeScript really came into stride with ability to express more "dynamic" types, using a functional style and having arrays-behaving-like-tuples,etc and the 3.x and 4.x series has really made it polished.
TL;DR; It's quite great now, but don't dismiss sceptical people because early versions of it kinda DID suck.
I think Ruby is much better than Python for building large applications.
Ruby is essentially Smalltalk with a neat Algol-like syntax and some Perl-isms. Its OO system is a joy to work with.
Python got so popular in data-oriented applications because it's a really simple procedural language.
More importantly, it had the right libraries (NumPy, SciPy and Matplotlib) when Torch (implemented in Lua) was no longer viable (due to LuaJIT limitations).
You’re right, they’re dicts unless slots are used. I read the parent comment and saying you can define types easily. But you can with dataclasses
Sorry what? This is absolutely not true.
Global variables are stored in a dict (`vars()`). Unless you use slots, an object is essentially a dict
Doesn't really disturb me because they're not used like a dict in practice though
Also I remember the dependency management system was a pain in the ass to deal with, especially with modules with native libraries.
Python had some issues with 2, but when 3 came around and fixed all that, it became the language of choice specifically because of its consistency.
Given that almost every cloud native project is written in Go I'd say this is entirely not true.
Plenty of them are still Java and .NET based, as the ecosystems counter reacted to Go's adoption hype, and Rust is the new kid on the block specially for cloud native Webassembly projects and eBPF.
Like Helm creators nowadays doing mostly Rust, https://deislabs.io/posts/
...x86_64? ;)
> Rust makes enormous binaries
Rust binaries are optimized to be fast (by default, fast != small), this [0] explains pretty well why, and min-sized also has many optimizations [1]. > and compiles slow
You can have a very slow compiler with all the optimizations and safety checks, or a fast one which doesn't. This however doesn't mean there is no room for improvement.One thing that can definitely improved on is how cargo manages dependencies, I am tired of each of my project's /target directory using >2GB of disk space, there at least should be some kind of opt-in global cache.
I am also worried about dependencies going in the same direction as the JS ecosystem, many of my projects only have 3-5 top level dependencies, but I end up downloading hundreds. A few are only compile-time, but this makes auditing very difficult and does make compile times a lot longer.
[0]: https://lifthrasiir.github.io/rustlog/why-is-a-rust-executab... [1]: https://github.com/johnthagen/min-sized-rust
But it DOES make binaries. Such a breath of fresh air after years of Java/Scala.
Like docker, for instance. If I had to write "java -jar docker.jar -cp ..." and fuck around for a week trying to figure out where the env vars, JVM flags, and arguments to the actual program go, I would not use docker. Let alone piping input through grep, less and tail.
Cargo has been working to resolve this, it's been testing a new feature that lazily fetches fine-grained index info over HTTP rather than the legacy approach, which is to clone the entire index stored as a git repo (which worked fine when crates.io was young and small, but hasn't scaled well). You can enable it on nightly Rust via the sparse-registry config flag, and it was recently accepted for the 1.68 release in March (which means you can try it out on the beta channel right now). In the future, it will become the default behavior.
https://doc.rust-lang.org/nightly/cargo/reference/registries...
It's quite verbose, as well, or was the last time I looked at it.
I don't demand a Perl level of terseness (that's going too far the other way), but neither is reinventing the verbosity of COBOL a good idea.
For example, imagine the following in an imaginary version of Rust with union types:
#[derive(PartialEq)]
struct Option<T> {
value: T | (),
}
impl<T> Option<T> {
fn some(value: T) -> Self {
Self { value }
}
fn none() -> Self {
Self { value: () }
}
fn is_none(&self) -> bool {
match self.value {
_: () => true,
_: T => false,
}
}
}
What does `Option::some(()).is_none()` return? Is `Option::some(()) == Option::none()`?
Ruby is still great for throwing something together fast and maintaining it until it runs into scale problems. It added gradual typing with sorbet and RBS.
Crystal is a neat typed, compiled Ruby-alike but it's buggy.
Rust hits more of these but it's ugly. Uglier than Python and approaches C++-level eyebleed. Rust generics aren't as flexible as they could be because type constraints don't have union and specialization is painful. Tag structs are laborious. Go hits more of these except it's not as flexible and not quite as safe as Rust. Rust makes enormous binaries and compiles slow and the cargo index download is glacial, I'm surprised they don't have an "sccache" for it. Go is easy to learn but then the capability of it plateaus. Go compiles and tests insanely fast.
Rust should rebase its type system to have union types, i.e., foo: i32 | f32. Also, more granular and specialized type constraints (negation, union) on generic trait parameters.
Elixir (on erlang) can be productive. It's gorgeous, it's fast, it's powerful, and fairly expressive.
Haskell and Idris are beautiful and powerful, but inaccessible to most software engineers.
Pony is beautiful, productive, extremely safe, and fast.
Zig, Nim, Kotlin and friends are all moving in the right general directions. Swift is alright too.