22 ms·
A Rust shaped hole
- JoelMcCracken 1y agoWow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening. regarding redefining functions, what could the author mean? using global function pointers that get redefined? otherwise redefining a function wouldn't effect other modules that are compiled into separate object files. confusing. C is simple in that it does not have a lot of features to learn, but because of e.g. undefined behavior, I find its very hard to call it a simple language. When a simple bug can cause your entire function to be UB'd out of existence, C doesn't feel very simple. In haskell, side effects actually _happen_ when the pile of function applications evaluate to IO data type values, but, you can think about it very locally; that's what makes it so great. You could get those nice properties with a simpler model (i.e. don't make the langague lazy, but still have explicit effects), but, yeah. The main thing that makes Haskell not simple IMO is that it just has such a vast set of things to learn. Normal language feature stuff (types, typeclasses/etc, functions, libraries), but then you also have a ton of other special haskell suff: more advanced type system tomfoolery, various language extensions, some of which are deprecated now, or perhaps just there are better things to use nowadays (like type families vs functional dependencies), hierarchies of unfamiliar math terms that are essentially required to actually do anything, etc, and then laziness/call-by-name/non-strict eval, which is its own set of problems (space leaks!). And yes, unfamiliar syntax is another stumbling block. IME, Rust is actually more difficult than Haskell in a lot of ways. I imagine that once you learn all of the things you need to learn it is different. The way I've heard to make it "easier" is to just clone/copy data any time you have a need for it, but, what's the point of using Rust, then? I wonder if the author considered OCaml or its kin, I haven't kept track of whats all available, but I've heard that better tooling is available and better/more familiar syntax. OCaml is a good language and a good gateway into many other areas. There are some other langs that might fit, like I see nim as an example, or zig, or swift. I'd still like to do more with swift, the language is interesting.
- tines 1y ago> Wow, a lot of stuff in here surprises me. C definitely can/does have spooky at a distance. Just share a pointer to a resource with something else and enjoy the spooky modifications. Changes are local as long as you program that way, but sometimes it can be a bit not-obvious that this is happening. I think the author means that the language constructs themselves have well-defined meanings, not that the semantics don't allow surprising things to happen at runtime. Small changes don't affect the meaning of the entire program. (I'm not sure I agree that this isn't the case for e.g. Haskell as well, I'm just commenting on what I think the author means.) > IME, Rust is actually more difficult than Haskell in a lot of ways. I imagine that once you learn all of the things you need to learn it is different. Having written code in both, Rust is quite a lot easier than Haskell for a programmer familiar with the "normal" languages like C, C++, Python, whatever. The pure functionality of Haskell is quite a big deal that ends up contorting my programs into weird poses, e.g. once you run into the need to compose Monads the complexity ramps way up. > The way I've heard to make it "easier" is to just clone/copy data any time you have a need for it, but, what's the point of using Rust, then? Memory safety. And the fact that this is the example of Rust complexity just goes to show what a higher level Haskell's difficulty is.
- JoelMcCracken 1y agoThanks for explaining what you think the author meant; i meant to reiterate that I was trying to actually understand as opposed to argue, but I forgot; I think sometimes "hey I don't get what you're saying because of reasons XYZ..." comes across as "I think you're wrong". Composing monads is another one of those painful parts of haskell. I remember being so frustrated while learning Haskell that there was all of this "stuff" to learn to "use monads" but it seemd to not have anything to _do_ with `Monad`, and people told me what I needed to know was `Monad`. Someday I wanna write all that advice I wish I had received when learning Haskell. A _lot_ of it will be about dealing with general monad "stuff". The thing that frustrated me in Rust coming from something like Ruby was how frequently I could not _do_ a very straightforward thing, because, for example, some function is a fnOnce instead of fnMulti, or the other way around, or whatever. Here's some of the experience from that time https://joelmccracken.github.io/entries/a-simple-web-app-in-rust-pt-4-cli-option-parsing/ https://joelmccracken.github.io/entries/a-simple-web-app-in-.... It became clear to me eventually that some very minor changes in requirements could necessitate massive changes in how the whole data model is structured. Maybe eventually I'd get good enough at rust that this wouldn't be a huge issue, but I had no way of seeing how to get to that point from where I was. In contrast, I can generally predict when some requirement is going to necessitate a big change in haskell: does it require a new side effect? if so, it may need a big change. If not, then it probably doesn't. But, I've found it surprisingly easy to make big changes from the nice type system. I really don't get when rust folks claim "memory safety" like this; we've had garbage collection since 1959. Rust gives you memory safety with tight control over resource usage; memory safety is an advantage that Rust has over C or C++, but not over basically every other language people still talk about. If you just clone/copy every data structure left and right, then you're at a _worse_ spot than with garbage collection/reference counting when it comes to memory usage. I _guess_ you are getting the ability to avoid GC pauses, but, why not use a reference counted language if that's the problem? copy/clone data all of the time can't be faster than the overhead from a reference counting, can it?? In haskell, I did find that once I understood the various pieces I needed to work with, actually solving problems (e.g. composing monads) is much easier. I don't generally have a hard time actually programming Haskell. All that effort is front-loaded though, and it can be hard to know exactly what you need to learn in order to understand some new unfamiliar thing. Your preferring Rust over Haskell is totally fine BTW, I'm just trying to draw a distinction between something that's hard to _use_ vs something that's hard to _learn_. Many common languages are much harder to use IME; I feel like I have to think so hard all of the time about every line of code to make sure I'm not missing something, some important side effect that I don't know about that is happening at some function call. With Haskell, I can generally skim the code and find what's important quite quickly because of the type system. I do plan to learn Rust at some point still whenever the planets align and I need to know something like it. Until then, there are so many other things that interest me, and not enough hours in the day. I still wonder if I have really missed out on some benefit from learning to think more about data ownership in programs.
- blashyrk 1y agoSomeone really needs to show Nim to the author :). It checks all of their boxes and then some
- Symmetry 1y agoI was thinking that too. There are many cases where you do want to manage memory yourself, and in that case you should likely use Rust or maybe Zig if you can choose your own tool. But if you don't want to manage your own memory Nim works nicely, though IMO it requires adherence to a style guide more than most languages.
- timeon 1y agoDepends what you do but most of the time you do not need to do anything special about memory management in Rust. That is why people try to use it for other things then just system programming.
- elcritch 1y agoYep it’s ideal for this sort of application without the headache of Rust. Plus it’s helpful it can compile to C,C++, or JavaScript. So take your pick.
- turboponyy 1y ago> While I can jump through hoops to compile JavaScript into a binary, such wouldn't feel "solid". And the very point of writing a native program in the first place is to make it feel solid You can use Bun to compile to native binaries without jumping through hoops. It's not mature, but it works well enough that we use it at work.
- genshii 1y agoIt's definitely nice for certain use cases. I just wish the binaries weren't so huge (~60MB + your actual source code).
- selfmodruntime 1y agoI write Gleam for this. A rust like language on the erlang VM. It's neat, but not widely used.
- giancarlostoro 1y agoI have been wanting to use Gleam more, but I havent found the right project or time. I can prototype drastically easier using Python.
- liampulles 1y agoI've written some Gleam as an exploration, and I liked it, but the "not widely used" thing is a concern. I need there to be some well maintained libraries for enterprise stuff. I know this is not the fault of the language, and that is unfortunate.
- DarkNova6 1y agoThe table in the end sums it up nicely. Rust allows low level programming and static compilation, while still providing abstraction and safety. A good ecosystem and stable build tools help massively as well. It is one of the few languages which managed to address a real life need in novel ways, rather than incrementing on existing solutions and introducing new trade offs.
- tux3 1y ago>To paraphrase Norvig's Latency numbers a programmer should know, if we imagine a computer that executes 1 CPU instruction every second, it would take it days to read from RAM. It's a detail, but this is a little bit off. RAM latency is roughly around ~100ns, CPUs average a couple instructions per cycle and a few cycles per ns. Then in the analogy, a stall on RAM is about a 10 minute wait; not quite as bad as losing entire days.
- jlokier 1y agoIn current machines, that's way off depending on how you choose to count "1 CPU instruction" for the metaphor. Take Apple's latest laptops. They have 16 CPU cores, 12 of those clocking at 4.5 GHz and able to decode/dispath up to 10 instructions per cycle. 4 of those clocking at 2.6 GHz, I'm not sure about their decode/dispatch width but let's assume 10. Those decoder widths don't translate to that many instructions-per-cycle in practice, but let's roll with it because the order of magnitude is close enough. If the instructions are just right, that's 824 instructions per nanosecond. Or, roughly a million times faster than the 6502 in the Apple-II! Computers really have got faster, and we haven't even counted all the cores yet. Scaling those to one per second, a RAM fetch taking 100ns would scale to 82400 seconds, which 22.8 hours, just short of a day. Fine, but we forgot about the 40 GPU cores and the 16 ANE cores! More instructions per ns! Now we're definitely into "days". For the purpose of the metaphor, perhaps we should also count the multiple lanes of each vector instruction on the CPU, and lanes on the GPU cores, as if thery were separate processing instructions. One way to measure that, which seems fair and useful to me, is to look at TOPS instead - tera operations per second. How many floating-point calculations can the processor complex do per second? I wasn't able to find good figures for the Apple M4 Max as a whole, only the ANE component, for which 38 TOPS is claimed. For various reasons tt's reasonable to estimate the GPU is the same order of magnitude in TOPS on those chips. If you count 38 TOPS as equivalent to "CPU instructions" in the metaphor, then scale those to 1 per second, a RAM fetch taking 100ns scales to a whopping 43.9 days on a current laptop!
- tux3 1y agoIf you're counting all instruction executing in parallel with the maximum on-paper IPC on all CPUs, accelerators, and GPUs, the number your get has no clear relation to RAM latency. It really is comparing apples and oranges. This scenario where all your 16 cores are doing 10 instructions per clock assumes everything is running without waiting, at full instruction-level and CPU-level parallelism. It's a measure of the maximum paper throughput when you're not blocked waiting on memory. You could compare that to the maximum throughput of the RAM and the memory subsystem, and that would give you meaningful numbers (for instance, how many bytes/cycle can my cores handle? How many GB/s can my whole system process?). Trying to add up the combined throughput of everything you can on one side and the latency of a single fetch on the other side will give you a really big number, but as a metaphor it will be more confusing than anything.
- genshii 1y agoThis hits close to home. TypeScript is also my language of choice for 90% of the software I write. I agree with the author that TypeScript is very close to the perfect level of abstraction, and I haven't seen another language with a type system that's nearly as enjoyable to use. Of course, TS (any by extension JS) obviously has its issues/complications. Bun solves a lot of the runtime-related issues/annoyances though. For the other 10% software that is performance-sensitive or where I need to ship some binary, I haven't found a language that I'm "happy" with. Just like the author talks about, I basically bounce between Go and Rust depending on what it is. Go is too simple almost to a fault (give me type unions please). Rust is too expressive; I find myself debugging my knowledge of Rust rather than the program (also I think metaprogramming/macros are a mistake). I think there's space in the programming language world for a slightly higher level Go-like language with more expressiveness.
- ashishb 1y agoTypeScript is good as a language. You can't generate static binaries out of it (except Docker images) and that itself is a deal breaker.
- genshii 1y agoYeah, that's definitely a huge drawback. Bun lets you get pretty close though with the `--compile` flag: https://bun.sh/docs/bundler https://bun.sh/docs/bundler Too bad the binaries are 60MB at a minimum :(
- Tade0 1y agoI mean you can, they're just inappropriately large.
- wk_end 1y agoI'd love to see someone develop a compiler for TypeScript that got, say, Ocaml-like performance. There's a bunch of reasons why that'd be tough though - you'd probably want a language very-similar-to-but-not-quite-like-TypeScript.
- tptacek 1y agoI don't think you need an elaborate process of elimination when one of your axioms is "must manage memory manually".
- eviks 1y agoHe's saying exactly the opposite > Rust... But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.
- yccs27 1y ago> Memory management was indeed the sore sticking point, why Rust hadn't appealed to me earlier. The author doesn't want manual memory management, but still decides to go with Rust.
- tptacek 1y agoTheir rubric is literally just 3 items: "native compilation", "abstractions", and "manual memory management". Had they put that little table at the front of the article, there wouldn't even need to be an article: the table basically says "I'm going to use Rust". That's fine!
- JoelMcCracken 1y agoThe author really doesn't want to do manual memory management. The table is there to summarize things discussed, but he never says he wants to do manual memory management. I just went back and checked. If you do find something that indicates that, I'd appreciate you pointing it out to me, because idgi
- ashishb 1y agoI actively seek out tools written in static languages. They are less fragile and have a longer shelf life. https://ashishb.net/programming/maintaining-android-app/ https://ashishb.net/programming/maintaining-android-app/
- Expurple 1y agoI agree so hard. That's why I use Hugo for my website. Speed was always only a bonus
- slowcache 1y agoOdin has been really growing on me lately as a language that checks all of those boxes. String types, first class allocators, built in tests, a batteries included philosophy, and ease of use are some of the things that really drew me towards it. I really wanted to like rust and I wrote a few different small toy projects in it. At some point knowledge of the language becomes a blocker rather than knowledge the problem space, but this is a skill issue that I'm sure would lessen the more I used it. What really set me off was how every project turned into a grocery list of crates that you need to pull in in order to do anything. It started to feel embarrassing to say that I was doing systems programming when any topic I would google in rust would lead me to a stack overflow saying to install a crate and use that. There seemed to be an anti-DIY approach in the community that finally drew me away.
- klntsky 1y agoWhat's the difference between anti-DIY and "batteries included"?
- tialaramex 1y agoIf Ginger Bill thinks some niche feature might be useful then baking it into Odin is "batteries included" if not, having it would be anti-DIY. This is very much Bill's language. If what you're looking for is that auteur stamp you won't find it in C or Rust or Typescript but you will find it in languages like Jai, Odin, Hare, maybe Zig. If that creator's vibe happens to match yours this could be beautiful, at least for personal projects. It's hard to imagine this scaling. A triple A studio hiring panel: "You've applied for a job but we write only Jai here. We notice you haven't submitted any obsessive fan art about Jonathan Blow. Maybe talk us through the moment you realised he was right about everything?"
- mrkeen 1y agoBatteries included is a fat, opinionated standard library. I think for some devs, if you import from the standard library, that somehow counts as DIY, whereas if you import from libraries that aren't distributed with the compiler, it's anti-DIY.
- 1y ago
- bee_rider 1y agoI’m not sure what his abstraction column really means, nuts and bolts-wise. But, Fortran is native, you get to allocate your own memory, and it has object oriented features (maybe that’s abstraction).
- tines 1y agoVery cool, I wish the author good luck! I've been writing a compiler in Rust for a few months now and I absolutely love it. The ways it solves most of the problems it addresses feel like the "right" way to do things. There are some things that feel a little weird, like the fact that often when you want a more complex data structure you end up putting everything in a flat array/map and using indices as pointers. But I think I've gotten used to them, and I've come up with a few tricks to make it better (like creating a separate integer type for each "pointer" type I use, so that I can't accidentally index an object array with the wrong kind of index). Rust is one of those languages that change how you think, like Haskell or Lisp or Forth. It won't be easy, but it's worth it.
- lenkite 1y agoThe best way to use Rust is to circumvent use of the borrow-checker and lifetimes and use indices everywhere! Suddenly, it becomes more pleasant and easy to refactor :).
- uecker 1y agoIt is a bit unclear to me why somebody who rejects C++ because "I once spent an entire year in the heaven of C++, walking around in a glorious daze of std::vector and RAII, before one day snapping out of it and realizing that I was just spawning complexity that is unrelated to the problem at hand." (which I can absolutely agree with!) is picking Rust from all options. If there is a language that can rival C++ in terms of complexity, it is Rust.
- dijit 1y agoYou’re right that Rust is a ball of complication. I am a fan of Rust but it’s definitely a terse language. However there are definitely signs that they have thought about making it as readable as possible (by omitting implicit things unless they’re overwritten, like lifetimes). I’m reminded also about a passage in a programming book I once read about “the right level of abstraction”. The best level of abstraction is the one that cuts to the meat of your problem the quickest - spending a significant amount of time rebuilding the same abstractions over and over (which, is unfortunately often the case in C/C++) is not actually more simple, even if the language specifications themselves are simpler. C codebases in particular, to me, are nearly inscrutable unless I spend a good amount of time unpicking the layers of abstractions that people need to write to make something functional. I still agree that Rust is a complex language, but I think that largely just means it’s frontloading. a lot of the understanding about certain abstractions.
- uecker 1y agoI do not really agree with respect to C. I often have to deal with C code written by unexperienced programmers. It is always relatively easy to refactor it step by step. For C++ this is much more painful because all the tools invented to make the code look concise make it extremely hard to follow and change. From the feature set, I would say that Rust is the same (but I have no experience refactoring Rust code).
- AstralStorm 1y agoIn personal experience, the much stronger and composite type model in Rust makes it easier to refactor. Adding features in particular is a breeze and automatically the compiler/language will track for you the places that use only old set of traits. Tooling is still newer though and needs polish. Generic handling is interesting at times and there are related missing features for that in the language, vis a vis specializations in particular. Basic concurrency handling is also quite different in Rust than other languages, but thus usually safer.
- jplusequalt 1y ago>There is an apocryphal story about Euler in elementary school solving all the math problems that the teacher gave to the class in a jiffy, so the teacher tells him to sum up the numbers to a thousand to get him to stop pestering for more. The expectation was that Euler would go through the numbers "imperatively", like C, summing them up. Instead, what Euler did was discover the summation formula and solved it "declaratively" like Haskell, in one go, as an equation. I've heard this story be accounted to Gauss, not Euler.
- n4r9 1y agoYes, it's Gauss. In fact the technique is sometimes known as "Gaussian summation". The New Scientist has an article where the author chases down early references to the story: https://www.americanscientist.org/article/gausss-day-of-reckoning https://www.americanscientist.org/article/gausss-day-of-reck... The earliest reference is a biography of Gauss published a year after his death by a professor at Gauss' own university (Gottingen). The professor claims that the story was "often related in old age with amusement and relish" by Gauss. However, it describes the problem simply as "the summing of an arithmetic series", without mention of specific numbers (like 1-100). Also, it was posed to the entire classroom - presumably as a way to keep them busy for a couple of hours - rather than as an attempt to humiliate a precocious individual.
- lblume 1y agoYes. In Germany the formula n(n+1)/2 is actually called the Gaussian sum formula, or even the "small Gauss". [0] [0] https://de.wikipedia.org/wiki/Gaußsche_Summenformel https://de.wikipedia.org/wiki/Gaußsche_Summenformel
- B4uler5 1y agoIf anyone reads this and like me fears the difficulty and complexity of rust, but still wants a language that is competitive in performance, works for system level programming as well as something more general purpose definitely give Swift a go. Over the last year I’ve started to write every new project using it. On windows, on linux and mac. It is honestly a wonderful language to work with. Its mature, well designed, has a lot of similarities to rust. Has incredible interop with C, C++, Objective-C and even Java as of this year which feels fairly insane. It also is ergonomic as hell and well understood by LLM’s so is easy to get into from a 0 starting point.
- tines 1y agoHow tied to the Mac ecosystem is Swift these days? Also, how is its type system and metaprogramming? Does it have type polymorphism, typeclasses, macros, etc?
- _mlbt 1y agoIt supports Linux, Windows, and even Android. It has all those things and more.
- B4uler5 1y agoSome of the functionalities in the core/foundation library don’t quite match between operating systems so sometimes you do need to put an “#if os(macos) do” etc, but for the most part its super straight forward working on one or another platform. In terms of its language features it has all of those and more, sometimes too many in my opinion. I personally favour languages that are clear in their vision. However at its core Swift is a highly performant language that is designed really well, has beautiful syntax, and in the last 5 or so years I have been impressed with its direction. It is being developed by a good team who listen to their community but not at the expense of the languages vision. My favourite aspect of using it though is its versatility. Wether you’re working on embedded systems, a game, a web server, or even a static site generator, it always feels like the language is there to support your vision, but still give you the fine grained control you need to optimise for performance. I also collaborate with a friend who is a Rust developer and he’s always super happy to work on a Swift project with me so I feel like that’s enough praise when you can pull a rest dev away from their beloved.
- Expurple 1y ago> If someone posts a patch or submits a PR to a codebase written in C, it is easier to review than any other mainstream language. There is no spooky at a distance. [..] Changes are local. Lol, wut? What about about race conditions, null pointers indirectly propagated into functions that don't expect null, aliased pointers indirectly propagated into `restrict` functions, and the other non-local UB causes? Sadly, C's explicit control flow isn't enough to actually enable local reasoning in the way that Rust (and some other functional languages) do. I agree that Go is decent at this. But it's still not perfect, due to "downcast from interface{}", implicit nullability, and similar fragile runtime business. I largely agree with the rest of the post! Although Rust enables better local reasoning, it definitely has more complexity and a steeper learning curve. I don't need its manual memory management most of the time, either. Related post about a "higer-level Rust" with less memory management: https://without.boats/blog/notes-on-a-smaller-rust/ https://without.boats/blog/notes-on-a-smaller-rust/
- shmerl 1y agoYeah, and C can get unreadable fast. Obfuscated C contest is a great example: https://www.ioccc.org https://www.ioccc.org But that doesn't mean it's a good idea to use such style for PRs, lol.
- Expurple 1y agoThat's a really weird example to give. You can write unreadable code in any language if you're determined enough
- pron 1y ago> And the very point of writing a native program in the first place is to make it feel solid. What does that mean, and what is it about native programs (i.e. programs AOT-compiled to machine code) that makes them feel solid? BTW, such programs are often more, not less, sensitive to OS changes. > realizing that I was just spawning complexity that is unrelated to the problem at hand Wait till you use Rust for a while, then (you should try, though, if the language interests you). For me, the benefit of languages with manual memory management is the significantly lower memory footprint (speed is no longer an issue; if you think Haskell and Go are good enough, try Java, which is faster). But this comes at a price. Manual memory management means, by necessity, a lower level of abstraction (i.e. the same abstraction can cover fewer implementations). The price is usually paid not when writing the first version, but when evolving the codebase over years. Sometimes this price is worth it, but it's there, and it's not small. That's why I only reach for low level languages when I absolutely must.
- Expurple 1y ago> such programs are often more, not less, sensitive to OS changes. You may be technically correct that they are more sensitive to the kernel interface changes. But the point is that native, static binaries depend only on the kernel interface, while the other programs also depend on the language runtime that's installed on that OS. Typical Python programs even depend on the libraries being installed separately (in source form!)
- pron 1y ago> But the point is that native, static binaries depend only on the kernel interface Many binaries also depend on shared libraries. > while the other programs also depend on the language runtime that's installed on that OS You can (and probably should) embed the runtime and all dependencies in the program (as is easily done in Java). The runtime then makes responding to OS selection/changes easier (e.g. musl vs glibc), or avoids less stable OS APIs to begin with.
- Expurple 1y ago
- lmm 1y agoIf they're serious about their criteria they should go with OCaml (or maybe, like, Swift, or any of dozens of languages in that space). (Of course they actually do want Haskell but they probably need to get there gradually)
- zem 1y agoright! the table at the end just screamed "use ocaml and be happy"
- legobmw99 1y agonobody gives OCaml a thought in these discussions. It’s such a wonderful language!
- tayo42 1y agoDoes ocaml have a mature ecosystem of libraries and dependencies? And easy way to manage them? Even rust with all its hype lacks in this area imo.
- lmm 1y agoNo, and that's part of why I use Scala instead. But this person is looking to make a binary to do a small thing on their desktop and does not list dependency management among their criteria.
- deleted 1y ago[deleted]
- myaccountonhn 1y agoDepends on what you're doing and how you structure your program. It certainly does not match the ecosystem of Go, Rust or C++
- sealeck 1y agoIt doesn't have a great ecosystem of libraries, but it _does_ have a good way to manage them: https://dune.build/ https://dune.build/, which as I understand it was developed at Jane Street (lots of code and dependencies) and is now open source. > Even rust with all its hype lacks in this area imo. This is surprising to me! I find that Rust has pretty excellent tooling, and Cargo is substantially better than the package manager in most other languages...
- TOGoS 1y agoI'm interested in the long piecewise elimination section. Presumably that's where they explain why not use Ocaml/Nim/yaddah yaddah. If I were to write such a list, the answer would probably come down to "because I wanted to pick ONE and be able to stick with it, and Rust seems solid and not going anywhere." As much as Clojure and Ocaml are, from what I've heard, right up my alley, learning all these different languages has definitely taken time away from getting crap done, like I used to be able to do perfectly well with Java 2 or PHP 5, even though those are horrible languages.
- nektro 1y ago> If someone posts a patch or submits a PR to a codebase written in C, it is easier to review than any other mainstream language. short-circuited reading this
- brian_herman 1y agoDeno creates binary files from typescript. https://deno.com/blog/deno-compile-executable-programs https://deno.com/blog/deno-compile-executable-programs
- Sophistifunk 1y agoSounds like a Zig-shaped hole to me ;-)
- Expurple 1y agoThey complain that Go is too low-level for their needs. Zig, with its explicit allocators, is definitely even lower-level. Rust seems low-level too, but it isn't the same. It allows building powerful high-level interfaces that hide the complexity from you. E.g., RAII eliminates the need for explicit `defer` that can be forgotten
- Sophistifunk 1y agoTrue, but I think the "low-level" complaint against Go in the article was just referring to all the stupid repetitive ceremony required for error handling, which Zig mostly skips over.
- Expurple 1y agoFair enough. That's what they seem to be saying. But then I want to chime in and argue that the repetitive syntax isn't even close to being the main problem with Go: https://home.expurple.me/posts/go-did-not-get-error-handling-right/ https://home.expurple.me/posts/go-did-not-get-error-handling...
- sgt 1y agoSo, while on that subject; does Zig get error handling right?
- Expurple 1y agoIdk, I'm not familiar enough with Zig to say
- lblume 1y agoIt does seem to: https://pedropark99.github.io/zig-book/Chapters/09-error-handling.html https://pedropark99.github.io/zig-book/Chapters/09-error-han... However errors do not seem to commonly wrapped, tagged or contextualized as is the case in Rust. This might weight lower verbosity as more important than extremely structured error handling which definitely constitutes an interesting approach.
- spooneybarger 1y agoI've written a ton of C in my life and a C lot of Go and I was rofl at the "no spooky action at distance" lines. This was brilliant performance art. Bless your heart Dear Author, I adore you.
- blamestross 1y agoEveryone who has said the phrase "Spooky action at a distance" has been proven wrong :)
- outside1234 1y agoRust is an amazing language once you get over the initial mental hurdle. An important thing to go in with: 99% of programs should not require you to manage lifetimes (‘a notation) If you find yourself doing this and aren’t writing a inner loop high performance library, back up and find another way. Usually this entails using a Mutex or Arc (or other alternatives based on the scenario) to provide interior mutability or multiple references. This statement might not make sense now but write it down for when it will. I use Rust now for everything from CLIs to APIs and feel more productive in it end to end than python even.
- thasso 1y agoA nice thing about C is that you can be pretty confident that you know all major footguns (assuming you spent some time reading about it). With languages that are young or complex there is a much greater chance you’re making a terrible mistake because you’re not aware of it.
- dwattttt 1y agoI'm yet to see someone be confident in this way on anything more than a trivial program, and be right. Just way too many footguns. My personal memorable one was bit shifting 32bit values by varying amounts, and our test vectors all failing after a compiler update, because some of the shifts were by 32. Undefined behaviour.
- tialaramex 1y agoIt is nice that, unlike C++, the C language standard does list all the Undefined Behaviour (in Annex J.2), it's a pretty long list and IMO it's terrifying, not so much because of specifics like this: "A searching or sorting utility function is called with an invalid pointer argument, even if the number of elements is zero" But because of broad choices like: "The execution of a program contains a data race" "An object is referred to outside of its lifetime" These are essentially categories of mistake we know programmers make, and in C the result is... Undefined Behaviour. No diagnostics, no exit, no errors, just throw your hands in the air and give up, anything might happen.
- self_awareness 1y agoI've seen this argument for years. "C is an easy language and it's easy to code review it.". Maybe if you want to skip all the off-by-1 errors, double frees, overflows, underflows, wrong API usage, you don't need to maintain multiplatform build environment, and you don't support multiple architectures. I mean, in this sense, assembly is even easier than C. Its syntax is trivial, and if that would be the only thing that matters, people should write assembly. But they don't write assembly, because it's not the only thing that matters. So please stop considering C only in terms of easy syntax. Because syntax is the only thing that's easy in C.
- junon 1y ago> Rust, from what I've heard, has a similar abstraction level as TypeScript, perhaps even closer to Haskell but that's good, I could do with a bit more help from the compiler. But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me. Eh.... yeah? I suppose technically? But not _really_. Rust gives you the option to do that. But most programs outside of "I'm building an operating system" don't really require thinking too hard about it. It's not like C where you're feeding memory manually, or like C++ where you have to think about RAII just right.
- pavlov 1y ago> “Rust, from what I've heard, has a similar abstraction level as TypeScript, perhaps even closer to Haskell but that's good, I could do with a bit more help from the compiler. But it requires me to manage memory and lifetimes, which I think is something the compiler should do for me.” The Rust compiler does manage memory and lifetimes. It just manages them statically at compile-time. If your code can’t be guaranteed to be memory-safe under Rust’s rules, it won’t compile and you need to change it.
- PartiallyTyped 1y agoYou can use runtime ownership structures like ref cells, arcs, etc as well.
- pavlov 1y agoSure. The part that people often complain about is that they have to make these decisions, rather than having a runtime default picked for them by the language.
- PartiallyTyped 1y agoIsn’t that having your cake and eating it too? Like if you find the performance penalty acceptable, use an RC, and you have imho a better swift.
- pavlov 1y agoI agree! As an Objective-C veteran, I feel a lot of people overthink these decisions. You can write highly performant applications with prevalent reference counting, and Rust lets you optimize where it actually counts.
- flohofwoe 1y agoMy two 'language poles' are Typescript as the 'north pole', and C as the 'south pole', with Python, C++, Zig (and to a lesser extent, Rust and Odin) placed somewhere along the latitudes. I think that of all those options, Typescript and Zig feel closest related. Zig has that same 'lightness' when writing code as Typescript and the syntax is actually close enough that a Typescript syntax highlighter mostly works fine for Zig too ;)
- sesm 1y ago> I once spent an entire year in the heaven of C++, walking around in a glorious daze of std::vector and RAII, before one day snapping out of it and realizing that I was just spawning complexity that is unrelated to the problem at hand. Good luck to the author with trying Rust. I hope he writes an honest experience report.
- alt187 1y agoYou may want to try the criminally underrated OCaml. It's fast, compiles to native code AND javascript, and has garbage collection (so no manual memory management). As an added bonus, you can mix Haskell-like functional code and imperative code in a single function.
- d--b 1y ago> That leaves me with the following options — C, C++, Go, Rust. > Technically, there are a lot more options, and I wrote a long section here about eliminating them piecewise, but after writing it I felt like it was just noise. Uh? I am guessing OP doesn't like virtual machines maybe, cause Java and C# sound like something that fits what they want. Both support AoT compilation though now... Also the assumption about Typescript to Wasm being not "solid" seems wrong. I mean I find it super weird that the author's only option for "native typescript" is Rust.
- nlitened 1y ago> To paraphrase Norvig's Latency numbers a programmer should know, if we imagine a computer that executes 1 CPU instruction every second, it would take it _days_ to read from RAM. I think the author probably misread the numbers. If CPU executed 1 instruction every second, it would take just 1—2 minutes to read from uncached RAM, no need to be overly dramatic. Overall, this reads to me like a very young programmer trying to convince themselves to learn Rust because he heard it's cool, not an objective evaluation. And I'm totally on board with that, whatever convinces you, just learn new things!
- rob74 1y agoOh, another one of those articles where people try to logically explain why they absolutely need to learn Rust and no other language will do. This time, even with religious connotations (https://en.wikipedia.org/wiki/God-shaped_hole https://en.wikipedia.org/wiki/God-shaped_hole). I mean, if you want to learn Rust, good for you, go ahead, no need to write a whole blog post rationalizing your decision!
- liampulles 1y agoI like the "lower level of abstraction" of Go. It was a transition coming from writing Spring Boot Java code to having to actually implement the "magic", but I like that I can clearly see the control flow of things in Go. Out of all the languages I've used, Go programs are the ones that have the highest percentage chance of working "first try". I think that has a lot to do with the plain and strongly typed style.