8 ms·
It was right then, but it's kind of dated and misses an evolutionary lesson: beautiful code isn't enough, it has to be safe, beautiful, maintainable, productive
by cvccvroomvroom 4y ago
It was right then, but it's kind of dated and misses an evolutionary lesson: beautiful code isn't enough, it has to be safe, beautiful, maintainable, productive, understandable, and resource efficient.
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.
- jimbob45 4y agoapproaches C++-level eyebleed 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.
- arthurcolle 4y agoPost a pic
- klyrs 4y agoA random file in the standard library: https://gcc.gnu.org/onlinedocs/gcc-4.6.3/libstdc++/api/a01099_source.html 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.
- stefncb 4y agoIf you want ugly look at the MSVC std.
- keithalewis 4y agoParty pooper. Don't you know we are just here to bitch and moan?
- klyrs 4y agoLook, I'll admit, it looks terrible from the view that gdb gives... but when you see the whole file, it's just not so bad.
- cvccvroomvroom 4y agoThe C++ library is algorithmically and data structure feature complete for most purposes. It doesn't have what boost and other libraries have, but that's okay. Ideally, a platform should ship without a standard library and use package management for all but built in types. The problem with C++ template metaprogramming style is symbol length, the notation ordering (insane levels of nesting), and diagnostics generated from those that easily turn into absurdity. Another issue is static languages lack universal diagnostics, introspection, and symbolic evaluation capabilities of dynamic languages with REPLs and remote debuggers. Dynamic languages are often missing "compile" (deployment)- or at-boot-runtime type checking, data race condition borrow/mutability/concurrency analysis, and monkeypatch protections.
- epgui 4y ago> Haskell and Idris are beautiful and powerful, but inaccessible to most software engineers. 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.
- creata 4y agoImo, one "fundamental" reason is that Haskell has a much smaller, nicer core than most languages, so it builds everything out of that core. For example, most languages have variable update statements in their core. Haskell defines at least two data types of "programs that have stateful variables" (ST and State). The result is that people want to see how everything is broken down into pure functions under the hood, and that means it takes more time to learn the language.
- dietrichepp 4y agoI do see fundamental reasons. Haskell was designed from conception to be a platform for research and education. I’d say it was a wild success at those two things. Certain decisions that made it successful as a platform for research and education make it less suitable for use writing applications in industry. 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.
- thedataangel 4y agoHaving used Haskell in industry, I can say it's actually _surprisingly_ good at boring run-of-the-mill software. The strong focus on correctness and the ecosystem-wide consistency of it's core design patterns means you spend a lot less time debugging things, and a lot more time writing the thing you actually want to write. 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.
- creata 4y ago> Tag structs are laborious... Rust should rebase its type system to have union types, i.e., foo: i32 | f32. 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.
- komadori 4y agoPerhaps they mean anonymous (discriminated) unions of some kind with that syntax?
- consilient 4y agoADTs = discriminated unions + tuples. They likely mean undiscriminated unions, as in typescript.
- nephanth 4y agoBut since rust is compiled, in practice that would be like C unions, right? A pain to work with 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
- zozbot234 4y agoAt the time I'm writng this, there's a separate thread on Rust's "ugly" syntax. The issue with complex trait constraints, specialization etc. is that they impact forward compatibility: it is possible that a new version of some external dependency will add trait implementations in a way that ends up breaking your existing code. It's understandable that Rust devs would want to avoid this.
- tejinderss 4y agoYou missed TypeScript, which has advanced generics with union support and the JS ecosystem is getting better each day and it’s ubiquitous.
- goodoldneon 4y agoTypeScript is fantastic —- such a flexible type system. 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
- whizzter 4y agoTo be honest early TypeScript was quite bad with class dependence (functional style was an afterthought) and "namespaces" (That was still used in the mainline TS compiler until recently iirc, behaved like nested objects in JS, kind-of useful but totally missed the NodeJS file-based-module-separation) felt a lot like they wanted _Java_ or C#. 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.
- goodoldneon 4y ago“Felt like they wanted C#” makes sense because Anders Hejlsberg was involved with TypeScript. Glad they stopped forcing C# into it and let it be its own thing. Not that C# is bad though!
- nextos 4y ago> 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. 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).
- AdamN 4y agoThat's sort of outdated. Python now has type hints, protocol oriented programming support, and is quite fast (for what it is). This wasn't the case back in the day but it's all there now.
- anthonygd 4y agoPython might have nice features, but it also has terrible features. Like using dicts for everything. It's not enough to allow good practices, you have to prevent (or at least reduce) bad practices.
- gautamdivgi 4y agoYou can use dataclasses instead of dict now.
- ElectricalUnion 4y agoUnless you use __slots__, aren't all class-based objects [specifically python2 new style `class MyClass(object): pass` or all python3 classes] dicts in Python?
- gautamdivgi 4y agoI was talking about the dataclasses.dataclass annotation in 3.10/3.11. You can use slots with it. 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
- aerfio 4y ago> Go is easy to learn but then the capability of it plateaus. Given that almost every cloud native project is written in Go I'd say this is entirely not true.
- pjmlp 4y agoThat was the past, helped by Kubernetes and Docker respective decisions to migrate from Java and Python into Go. 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/ https://deislabs.io/posts/
- intelVISA 4y agocloud native web assembly... ...x86_64? ;)
- pjmlp 4y agohttps://krustlet.dev/ https://krustlet.dev/ https://learn.microsoft.com/en-us/azure/aks/use-wasi-node-pools https://learn.microsoft.com/en-us/azure/aks/use-wasi-node-po... https://www.docker.com/blog/docker-wasm-technical-preview/ https://www.docker.com/blog/docker-wasm-technical-preview/ https://www.fermyon.com/platform https://www.fermyon.com/platform
- intelVISA 4y agoGotta respect the grift I guess! Like MLM crypto schemes maybe I just Don't Get It, or I'm not the mark...
- Nullabillity 4y agoWASM is architecture-independent (ARM servers are becoming a thing, for better or worse) and has a lot of investment into sandboxing it performantly (since it also has to run in browsers).
- tincholio 4y agoI totally agree with your take (at least for the languages I know, out of the ones you mention). For me that right balance of beauty, productivity, and so on came with Clojure. I now find it painful to use any other language, tbh.
- catfishx 4y ago> 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-executable-large.html https://lifthrasiir.github.io/rustlog/why-is-a-rust-executab... [1]: https://github.com/johnthagen/min-sized-rust https://github.com/johnthagen/min-sized-rust
- mrkeen 4y ago> Rust makes enormous binaries But it DOES make binaries. Such a breath of fresh air after years of Java/Scala.
- ludovicianul 4y agoJava also makes binaries with GraalVM.
- wing-_-nuts 4y agoI never really understood this, especially in the age of small docker containers? You just yeet your jar into the container and deploy. Ok, so rust and go don't need a jvm. Why does it matter? Disk space is dirt cheap. It's not like statically linked binaries are small by any measure anyway.
- mrkeen 4y agoBecause I run binaries. 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.
- kibwen 4y ago> the cargo index download is glacial 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.html#registry-protocols https://doc.rust-lang.org/nightly/cargo/reference/registries...
- Turing_Machine 4y ago> Uglier than Python and approaches C++-level eyebleed. 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.
- Nullabillity 4y agoType arguments, union types, and a sound type system: pick any two. 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()`?