9 ms·
I was thinking of learning Rust but it seems a bit overkill due to manual memory management as compared to languages with similar speed like Nim, Zig, and Cryst
by cercatrova 5y ago
I was thinking of learning Rust but it seems a bit overkill due to manual memory management as compared to languages with similar speed like Nim, Zig, and Crystal. How would one compare these languages?
Is it worth learning Rust or Zig and dealing with the borrow checker or manual memory management in general, or are GC languages like Nim or Crystal good enough? I'm not doing any embedded programming by the way, just interested in command line apps and their speed as compared to, say, TypeScript, which is what I usually write command line apps in.
- mlindner 5y agoMemory has to be managed by something. The more decisions that are made for you in how that happens the less flexibility there is for certain situations.
- cercatrova 5y agoSure but my use cases would be stuff I'd normally write in TypeScript or Python that already have garbage collection. Like I said I'm not doing embedded programming so I don't have too much of a need to manage memory. My question could be further constrained then to be, is learning Rust or Zig despite its manual memory management worth it for applications that are normally already garbage collected in their current implementations? Or are languages like Nim and Crystal enough? Does Rust and Zig have other benefits despite manual memory management?
- adgjlsfhk1 5y agoimo, most code can do just fine with GC. modern GCs can be relatively low overhead even with guaranteed small pauses (10ms). furthermore, most code that can't handle pauses can be written to not allocate any memory (so GC can be temporarily turned off). as such, the only two places where you need manual allocation are for OS development, and hard real time requirements.
- Comevius 5y agoWhen tail latency (high-percentile latency) is important GC is not a good choice. Wait-free (threads progress independently) concurrent algorithms also need wait-free memory reclamation with bounded memory usage to be able to guarantee progress. But most software are throughput-oriented.
- pjmlp 5y agoAdditionally, not all GCs are made alike, and languages like D, F#, C#, Nim, Swift, among others, also offer value types and manual memory management, if desired.
- elcritch 5y agoAlso Swift and Nim w/ ARC use reference counting, which generally give much better latency and lower memory overhead. Reference counting is part of the reason iOS devices don’t need as much RAM. Nim’s ARC system also doesn’t use atomic or locks which means it’s runtime overhead is very low. I use it successfully on embedded devices for microsecond timed events with no large tail latencies.
- pjmlp 5y agoReference counting is a GC algorithm. I wouldn't buy into much Apple marketing regarding its performance though, https://github.com/ixy-languages/ixy-languages https://github.com/ixy-languages/ixy-languages It makes sense in the context of tracing GC having been a failure in Objective-C due to its C semantics, while automating Cocoa's retain/release calls was much safer approach. Swift naturally built on top of that due to interoperability with Objective-C frameworks. Nim has taken other optimizations into consideration, however only in the new ORC implementation. Still, all of them are much better than managing memory manually.
- elcritch 5y ago> I wouldn't buy into much Apple marketing regarding its performance though, I wouldn’t make claims on Swifts overall performance, but just it’s memory usage (really Obj-Cs) and particularly for GUI development. Java’s GCs have always been very memory hungry, usually to the tune of 2x. Same with .Net. Though to be fair Go’s and Erlang’s GCs have much better memory footprints. Erlang’s actor model benefits it there. Agreed, they’re all better than manual memory management.
- MarcusE1W 5y agoThe way you describe your use case I think you are fine with a language with garbage collection like Nim (which has has a syntax a bit like Python) or Crystal. I would also throw Go in the ring or if you are interested to learn a bit of functional programming then you also could look at Ocaml. Zig has no garbage collection btw, but makes it easier than C to handle that. Another language without garbage collection that helps a lot to avoid memory issues is Ada (Looks a bit like Pascal). So there are alternatives to Rust.
- mlindner 5y agoRust's memory management is "manual" but it feels automatic for most uses.
- sanxiyn 5y agoZig uses manual memory management too (even more manual than Rust), so that's a bit strange question.
- cercatrova 5y agoInteresting, based on their code samples it looked to me like a GC language since (at least from what I saw) I didn't see anything regarding memory management.
- sanxiyn 5y agoI am not sure what code samples you looked at, but https://ziglearn.org/chapter-2/ https://ziglearn.org/chapter-2/ should give you an idea.
- elcritch 5y agoIt’s easy, IMHO, to mistake Zig as a GC’ed language or more broadly as a memory safe systems language. It’s neither but it is a nicer C.
- zigger69 5y agoIt's really easy in Zig to be honest. Just put `defer thing.deinit()` in the right scope and you're done. You gain explicitness and know exactly what's going on in your Code. Everything is obvious. That's the reason Zig is so incredible simple and easy to read. Zig also has a GPA that will tell you about memory leaks or anything.
- puffoflogic 5y agoAnd in rust you just put `` in the right scope and you're done. This is perfectly explicit and you know exactly what's going on in your code. Everything is obvious.
- zigger69 5y agoYou can execute arbitrary code on drop operations by implementing `std::ops::Drop` for a type.
- throwaway239i3j 5y agoOf the ones you mentioned, Zig is the only one that has explicit memory management. > Is it worth learning Languages are easy to pick up once you understand fundamentals. The borrow checker is intuitive if you have an understanding of stack frames, heap/data segment, references, moved types, shared memory. You then should be asking "Is it worth using?", then evaluate use cases.. pros/cons.. etc. For CLI, Rust is likely the easiest given it's macros, but if you struggle with the borrow checker then it won't be. You will be fighting the compiler instead of developing something. Depending what your CLI program is doing, you might want to evaluate what libraries are available, how they handle I/O, and parallelism. JavaScript has incredibly easy and fast concurrent I/O thanks to libuv and v8.
- travisgriggs 5y ago>> Is it worth learning > Languages are easy to pick up once you understand fundamentals. The borrow checker is intuitive if you have an understanding of stack frames, heap/data segment, references, moved types, shared memory. I see this sentiment often. In the last 10 years, I have come up a level in raw C, learned Kotlin, Swift, Python, Elixir/Erlang, and a smattering of JavaScript, all coming from a background that included Fortran and Smalltalk. My problem with the dialogue is what is meant by “learn.” I have architected, implemented, and maintain different components of our products in all these languages currently. I think that demonstrates I have “learned” these languages, at least at this level of “picked up.” But I can’t write Python the way Brett Canon does. Or Elixir the way Jose Valium does. Or any of their peers. And in that regard I still very much feel I have not “learned”. I spent a couple days playing with Zig a month or so ago. I became familiar with the way it worked. I could spend another month or so in that phase, and then could probably comfortably accomplish things with it. But I don’t think I’d feel like I’d “learned” it. It reminds me of my experience learning Norwegian. I lived in Norway for 2 years and did my best to speak as much Norwegian as I could. At six months I could definitely get by. At 13 months, as I embraced the northern dialect, I was beginning to surprise Norwegians that I was from the states. I started dreaming in Norwegian at some point after that. But even at 24 months, able to carry on a fluid conversation, I realized I still could “learn” the language better than I currently knew it. So I guess, it always seems there needs to be more context, from both the asker and the answerer, when this “should I learn X” discussion is had. Learning is not a merit badge.
- Starlevel001 5y ago
- nicoburns 5y agoIf you're doing things like command-line apps you'll probably find Rust much easier to work with than Zig. You can write high-level code that looks basically like TypeScript in Rust, whereas Zig is more manual. Nim and Crystal are easier from a language perspective, but they have much smaller ecosystems.
- jgillich 5y agoI've found that Go is not elegant enough for me and Rust is too difficult to write (I started using Rust in 2015 and after years of trying I eventually realized Rust doesn't make sense for most apps), so I'm all in on Crystal. Despite not having much prior Ruby experience, I absolutely love the language.
- zozbot234 5y agoModern Rust is much more straightforward than it was in 2015. It's effectively two different languages, albeit maintaining backward compatibility (i.e. code written for Rust 1.0 should still compile today, with proper edition settings).
- bscphil 5y agoSuppose I wanted to try learning Rust again; is there a resource for someone with a lot of (hobbyist) programming experience, and experience with low level languages and memory management (e.g. C), but not complicated low-level languages, like C++? When I tried to work with Rust a few years ago I found it utterly impenetrable. I just had no idea what the borrow checker was doing, did not understand what the error messages meant, and honestly couldn't even understand the documentation or the tutorials on the subject. Understanding what is happening in C or Zig is pretty easy; in Rust it's always been a nightmare for me. I just really don't grok the "lifetime" concept at all, it feels like I'm trying to learn academic computer science instead of a programming language. Rust feels to me like a powerful, expressive language for professional programmers at the top of their game. That's a complement for any language. But it comes at the cost of mind-numbing complexity for anyone who's not an expert.
- zozbot234 5y ago> Suppose I wanted to try learning Rust again; is there a resource for someone with a lot of (hobbyist) programming experience, and experience with low level languages and memory management (e.g. C), but not complicated low-level languages, like C++? The official Rust book is targeted at novices with some programming experience. There's also Rustlings https://github.com/rust-lang/rustlings https://github.com/rust-lang/rustlings for a more practical approach. > When I tried to work with Rust a few years ago I found it utterly impenetrable. I just had no idea what the borrow checker was doing, did not understand what the error messages meant, and honestly couldn't even understand the documentation or the tutorials on the subject The compiler diagnostics have improved a lot over time. It's quite possible that some of the examples you have in mind return better error messages. > in Rust it's always been a nightmare for me. I just really don't grok the "lifetime" concept at all, it feels like I'm trying to learn academic computer science instead of a programming language. Academic computer science calls lifetimes "regions", which is perhaps a clearer term. It's a fairly clean extension of the notion of scope that you'd also find in languages like C or Zig. It's really not that complex, even though the Rust community sometimes finds it difficult to convey the right intuitions.
- lijogdfljk 5y agoIt's funny i came to Rust from Go, Python, NodeJS, etc after a combined .. 15 years or so. I've been using Rust full time (work & home) for ~2 years now. Obviously i'm biased, but i quite enjoy it. I find i am more efficient now than before, because it manages to give me the ease of the "easier" languages quite often with a rich set of tooling when i need to go deeper. Personally i feel the concern over the borrow checker is way overblown. 95% of the time the borrow checker is very simple. The common worst case i experience is "oh, i'm borrowing all of `foo` when i really want `foo.bar` - which is quite easily solved by borrowing just the `.bar` in a higher scope. The lifetime jazz is rarely even worth using when compared to "easier" languages. Throw a reference count around the data and you get similar behavior to that of them and you never had to worry about a single lifetime. Same goes for clones/etc. I often advocate this. For beginners to use the language like it was a GC'd language. A clone or reference count is often not a big deal and can significantly simplify your life. Then, when you're deeper into the language you can test the waters of lifetimes. So yea. Your mileage will vary i'm sure. But i find Rust to be closer to GC'd languages than actual manual languages, in UX at least. You won't screw up and leak or introduce undefined behavior, which is quite a big UX concern imo.
- melony 5y agoThe problem is that when lifetimes cause you problems, it can force the entire feature development to stop until the problem is fixed. There is no reasonable escape hatch or alternative (clone doesn't always work).
- klabb3 5y ago+1. My programming style normally consists of trial-and-error style prototyping for a couple of iterations, and then later refining that into something that's solid and robust. I find Rust's inofficial "prototyping mode" difficult to combine with it's regular "production grade mode" for practical purposes.
- pornel 5y agoRc/Arc is usually the escape hatch. I presume you put raw pointers under the "no reasonable" caveat, but if the borrow checker is wrong and you're right, they can be the right tool too. They're not unreasonable if the alternative was to use a different language that couldn't guarantee this safety either. I know dealing with the borrow checker can feel like a dead-end sometimes, but dealing with it is something that you can learn. Things that it can't handle fall into a handful of common patterns (like self-referential structs). Once you learn what not to do, you can recognize and avoid the issues even before you write the code.
- pizza234 5y ago> or are GC languages like Nim or Crystal good enough? Any programming language is good enough for their own use cases :) It's a matter of understanding which the use cases are. I'm a big Rust fan, but I nonetheless believe that the use cases for programming languages with manual memory management are comparatively small, in particular, since GC has been improved a lot in the last decade. For undecided people, I conventionally suggest Golang. Those who at some point need deep control, will recognize it and change accordingly.
- kaba0 5y agoWhy Go? It is quite terrible in expressiveness and if you do commit to a GC you have plenty of better choices. But to each there own, otherwise I agree that systems programming is a niche and a good GC is an overwhelmingly good tradeoff in almost every case.
- phendrenad2 5y agoI recommend C. Once you get the hang of it, it's as fast as writing Rust code (and you don't have to think about borrow checks).
- cercatrova 5y agoYeah, I sure love debugging segfaults. I've used C before and it was cool to learn but I haven't used it since.
- phendrenad2 5y agoOnce you've used C enough, you get the skill to avoid writing segfaults, and when a segfault happens, they're a lot easier to debug. However, since you're just interested in writing a fast command-line app, what about the JVM or .NET? Those have a startup time issue, but once they're running they're very fast, less than an order of magnitude slower than C/Rust/Zig/etc.
- kaba0 5y agoMy biggest gripe with C is not even the manual memory management, since with Valgrind and friends they are not that hard to debug. But how do you solve such a basic issue like having a vector-like data type for different types? Its “macro” system is just a disgusting hack, I could just as well write a sed script instead. And the other option is runtime-overhead or copy-pasting code..
- phendrenad2 5y ago> vector-like data type for different types When using C, if you want something from a higher-level language, usually you'd just do what that language's runtime does internally. So for a vector of heterogeneous objects, you could do a linked-list of pointers to the data objects. Something like: struct VecItm { struct VecItm next; void *data; size_t data_len; char objTypeId; }; Is it more work? Yes. But at this point I would stop and consider if I really need a heterogeneous collection. Do we really need to store a list of objects with arbitrary sizes? What if we have 3 types of objects, in 3 arrays, and we store index into those arrays? struct Foo { unsigned byte x; }; struct Bar { unsigned word x; }; struct Baz { unsigned long x; }; struct Foo foos[256]; struct Bar bars[256]; struct Baz bazzes[256]; // objTypeId: 0 = foo, 1 = bar, 2 = baz struct VecItm { struct VecItm next; unsigned int idx; char objTypeId; }; Or what if we can do something even better? What if Foo, Bar, and Baz all have a max size that isn't too wildly different? Can we store them all in an array directly? // objTypeId: 0 = foo (x contains 8 bits), 1 = bar (x contains 16 bits), 2 = baz (x contains 32 bits) struct VecItm { unsigned long x; char objTypeId; }; struct VecItm vecItms[256]; > Its “macro” system is just a disgusting hack It's really not that bad. It can result in spaghetti-code where your macros are using other macros and they're spread all over a header file. But if you use them surgically, only when needed, they don't cause much trouble. > I could just as well write a sed script The benefit of C macros over sed is if you use some language-aware tooling like an IDE (such as CLion), it will syntax-check and type-check your macros.
- deleted 5y ago[deleted]
- fyzix 5y agoNim strikes a great balance. No need for a low level language for cli and general software. I liked crystal but the lack of support on windows and lackluster dev experience made me stick to Nim. Nim also can double as a web language by transpiling to JS.
- quazar 5y agoI would not recommend Nim.
- throwamon 5y agoThank you so much for such a profoundly insightful comment. I'm now even thinking of changing professions thanks to it.
- planetis 5y agoI like Nim.
- exikyut 5y agoI haven't properly looked into Nim yet, and the sibling comments here make for some interesting signalling.
- arc776 5y agoNim's super power is being ridiculously productive (at least for me). Hack stuff out like a Python script, yet it runs really fast and is a tiny self contained executable, so you can just use it as is and move on to the next task. If you want manual memory management, that's easy too. Want to use a C/C++ library? No worries you have ABI compatibility. As you mention compiling to JS lets you use it as a web language and share code and types between front and back end. Then you can automate code generation with the sublime macros, which are just standard Nim code to create Nim code. No new syntax or special rules required - any Nim code can be run at compile time or run time, so you can use standard/3rd party libraries at compile time to write macros and give the user a slick syntax whilst removing boilerplate. I really miss languages without straight forward metaprogramming after using Nim. It's something that multiplies the power of a language, rather than just adds to it.
- Tozen 5y agoBesides Rust and Zig, you might want to check out Vlang and Odin, who are in the same category.
- cercatrova 5y agoI remember reading a lot of controversy about V back when I first heard about it so I decided not to look into it further [0], but I'll take a look again. Odin looks interesting, Pony does as well. [0] https://news.ycombinator.com/item?id=25511556 https://news.ycombinator.com/item?id=25511556
- Tozen 5y agoA lot of the so-called Vlang controversy appears to have been disguised allegiance and competition between the newer languages. Looks more like various people defending their interests. Languages like Odin, Zig, Nim, Crystal are far older than Vlang. When Vlang came along and got a lot of sudden popularity and funding, looks like various competitors sought to bash it and hoped it would disappear. In addition, such detractors were acting like a brand new programming language would be a finished polished product from day 1, when that was not the case for their far older languages. For instance, Odin and Crystal are older than Vlang, but has been surpassed by it in various respects. And don't get me wrong, I like Odin. That's because Odin is among the newer breed of languages that have continued the trend in which Go started of non class-based OOP and more generalized OO, that are contenders to be alternatives to C/C++ (like Zig). In the case of Vlang, it has clearly been developing rapidly and consistently, and continually gaining in popularity. Simply looking at their releases (and release schedule) along with their documentation (which various newer contenders are lacking in even that), will show a lot of the controversy is without merit or distortions of language development reality. https://github.com/vlang/v/releases https://github.com/vlang/v/releases https://github.com/vlang/v/blob/master/doc/docs.md https://github.com/vlang/v/blob/master/doc/docs.md https://modules.vlang.io/ https://modules.vlang.io/
- kaba0 5y agoIt doesn’t help that plenty of claims on the V website was simply ridiculous, like transpiling C to V and making it memory safe (or some insane compile speed claim transpiling Doom, if I remember well?). Also, memory safe without a runtime and without a rust-like borrow-checker.. these are simply impossible lies. Not sure about its current state, hopefully these are all removed and the sane claims are in progress.
- zigger69 5y agoCrystal: compilation speed is just too slow, sadly. Nim and Zig: I'd definitely just go with Zig. It's an extremely simple language, has no macros (but something much better than macros), is explicit, and in the long run it's just going to be worth it much more than Nim.
- pyjarrett 5y agoAda is another option without a GC. I wrote a search tool for large codebases with it (https://github.com/pyjarrett/septum https://github.com/pyjarrett/septum), and the easy and built-in tasking and pinning to CPUs allows you to easily go wide if the problem you're solving supports it. There's very little allocation since it supports returning VLAs (like strings) from functions via a secondary stack. Its Alire tool does the toolchain install and provides package management, so trying the language out is super easy. I've done a few bindings to things in C with it, which is ridiculously easy.
- deleted 5y ago[deleted]
- Siira 5y agoI haven’t tried Zig yet, but I liked Common Lisp better than Go and Rust for fast CLI apps/scripts. You need to dump an image with all your deps already loaded, and then you can run small scripts with instant compilation very fast. It’s an ergonomic language with good IDE support in emacs. There are some rough edges around (inconsistent API design, the package manager not using HTTPS, …), but tolerable.
- cercatrova 5y agoCommon Lisp doesn't offer features like sum types right? I am under the impression that it is a dynamically typed language like most Lisps, but I could be wrong.
- Siira 5y agoIt has optional typing, but as it’s fast without it, I haven’t dug into them. I don’t know about a union type though.
- adenozine 5y agoYou might peek at Coalton. https://coalton-lang.github.io/reference/ https://coalton-lang.github.io/reference/ I don’t think it has sum types, but it offers a rather sophisticated and very functionally oriented type system that compiles back to SBCL. It looks neat, haven’t found time to play yet…
- deleted 5y ago[deleted]
- cxr 5y ago> just interested in command line apps and their speed as compared to, say, TypeScript There are no fast languages, only fast language implementations. NodeJS/V8 is pretty fast (even faster than you probably think)—particularly if you're already doing things like making the sort of compromises where you limit yourself to writing only programs that can be expressed under the TypeScript regime. It's usually the case that it's not the NodeJS runtime that is the problem but rather the NodeJS programming style that is the source of the discomfort with "speed" that you will have experienced.