Rust from 0 to 80% for JavaScript Developers
michaelsalim.co.uk
michaelsalim.co.uk
> It’s an error handling magic for async functions
The question mark operator is unrelated to async - you might say "fallible functions" instead.
> This indicates that it’s a macro. Basically a shortcut.
I don't think "shortcut" has a specific meaning that is related to macros in either Javascript or Rust.
> An implementation of trait. So class (?).
Not really a class. There isn't a good parallel to this in most other languages. It is the link between a trait and a type, and provides a specific implementation of the trait.
> Unlike JS, Rust has a type for the result of the promise/future called Result
The `Result` type is not related to futures. Any function can return a `Result`, and a future can yield any type (not necessarily a `Result`, although it is commonly used in that way).
> The Result enum has Ok and Err. If the future is successful, it returns Ok, otherwise Err.
Again, no relation between `Result` and futures.
> Use this when you’re confident that it won’t error.
Personally I would recommend never using `unwrap` outside of tests. If you want to panic on the `Err` case, then `expect("...")` allows you to provide an explanation for why the `Err` case should not have been possible.
This jumped out at me too and I think it would be better stated as “this function doesn’t handle this error” or “this function may produce this error”, which is basically checked exceptions ~without error handling as arbitrary control flow.
> Not really a class. There isn't a good parallel to this in most other languages.
It’s a lot more like a class than the next most obvious TypeScript idiom (structural type compatibility/duck typing). It has to be explicitly defined and that’s the most important part coming from a JS/TS background.
I agree with and fully endorse the rest of this comment.
With the `?` operator, Rust behaves identically to a language with checked exceptions as it also has "arbitrary control flow" in that the code may "jump" elsewhere on errors. The implementation may be different, but the abstraction is identical.
The trickiest thing is ownership and lifetimes, but that's not really something you can understand just by reading. You need to build an intuition for how ownership and lifetimes work.
The best place to start is still the Rust book: https://doc.rust-lang.org/book/ and then start coding with it. I'd also suggest you learn some C along the way, if you only have a JS background.
And agreed, the Rust book is excellent.
I did have experiences with C which made going into Rust that much easier. But for others that don't, wouldn't you think going straight to Rust would be easier than learning C on the side?
- if a good article would be useful to you, the best resource will almost definitely be The Rust Book which is just a really well organized and easily accessible website
- if you prefer just exploring, Rust and its ecosystem is a lot easier to just wander into and try stuff than JS; but it’s going to feel really strict and have unfamiliar rules even if you’re used to strict TS
- even if you bail out of either it’s worth the time, I guarantee you’ll learn something even if it doesn’t show its value right away
Btw, I feel like I should learn rust now.
If you've got a Cat named puss, the call puss.meow() is effectively shorthand for something like Cat::meow(&puss) where that first parameter was the &self parameter to your "method".
Because this is namespaced, there's no problem if your Cat type has this meow() method and a Trait (say, AnimalNoises) it implements also has a meow() function, Rust knows those are different functions and the confusion only arises for a human reader, and only in code that actually wants to call one of the two identically named functions.
AnimalNoises::meow(&puss) and Cat::meow(&puss) are distinct, but writing thing.meow() requires inspecting other nearby code to discover whether from context this code knows thing is a Cat or just wants to make AnimalNoises. Where this might be confusing you should write AnimalNoises::meow(&thing) to make your intention clear to humans, and have it checked by the compiler.
Only the type's author gets to implement it, and only once (the standard library and especially core are special) so there's an essential distinction between SomeType::function() which was necessarily provided by the SomeType author, and just third party code that works with this type.
[Edited, this used to suggest it's a typo, but probably it's just a different way to think about what's happening, so I removed this claim]. There almost certainly isn't a Cat::clone and in fact what's happening is that Clone is in the prelude, so this is:
Clone::clone(&puss)
[edited to add]
Which is really even:
<Cat as Clone>::clone(&puss)
and because Rc is a Smart Pointer it implements DeRef and so that's ultimately:
<Cat as Clone>::clone(<Rc as Deref>::deref(&puss))
Definitely understandable that people want to write puss.clone() instead.
By the way, misfortunate::Multiplicity demonstrates Deref and DerefMut nicely, providing a type which has two things inside it but references to it act like one thing when being mutated and like the other when merely referenced...
Not something for absolute beginners, but worth seeing to build correct intuitions (and to underscore Rust's admonition not to implement Deref and DerefMut if you aren't a smart pointer -- misfortunate is like Jackass, this is for entertainment and not to be attempted in your real Rust projects).
But it’s true that much of the inspiration for Rust comes from functional languages, and the trait system is definitely inspired by Haskell.
1. Rust's traits are unary relations (i.e., predicates) on types, whereas Haskell's type classes support relations of arbitrary arity ("multi-parameter type classes").
2. Rust's traits do not support higher kinds, so you can't define many things which are considered pretty basic to Haskell programmers (Functor, Monad, etc.).
But despite these limitations, Rust's traits are still great and better than what 99% of other languages have.
Rust has great PR but I found it to be a profound waste of time. YMMV.
Crates to check out:
- clap for command and argument parsing
- anyhow for “easy” error handling
- log + env_logger for logging
- reqwest for HTTP requests (start off by using the blocking client)
- serde + serde_json for handling JSON
- rayon to “magically” parallelize your code (using multiple threads)
Nim has a huge stdlib.
We use Rust for regular boring old backend servers at work. Not for speed or efficiency either. Rust doesn't need to be just a hot mess of memory manipulation (and you're never going to learn it like that)
If you want to learn it, don't do the weird stuff first, it'll just be confusing
Actually quite the opposite. You would appreciate Rust in applications that manage non-memory resources. RAII is a breath of fresh air compared to all those try-with-resources / AutoCloseable hacks.
The cargo-edit tool gives you yarn-like commands to edit your packages. The main command, "cargo add", will be integrated into mainline cargo next update (I think).
Examples: * Immutable by default with a verbose syntax (let mut..), compare this with Kotlin val to var. It appear clear that rewritability has not been well thought, if thought at all. This basically means writing variables is a pain, your thinking process is constantly stopped by making things no longer.. constants.
Options. yeah null is so impure. Except you now have done the worst thing you could have ever done to a language, wrapped types... The unergonomy and verbosity is strong. When you see Typescript, Kotlin, C# and Dart non nullable types and smart casts you clearly realize Rust has made a permanent historical accident here. If you don't know what I'm referring, it only cost one google search.
Results, same problem as options. Verbose, thought interrupting. The cognitive noise of polluting return types is strong, very potent. If they wanted pure thinking nazism they could have added optionally or not, exceptions on the type signature, like java checked exceptions, or the incoming exception signatures in typescript. The number of rust error handling libraries is a testimony to this failure. When such core features are lacking, a language is a failure.
Throwing away object oriented programming is the cringiest mistake of rust though. Because it's not cool enough in 2022. Rustc was first designed in Ocaml, with all the cognitive biases this imply. If composition is that nice well make it a proper pattern like Kotlin delegation, except rust did not. And even if delegation was ergonomic, inheritance still is the most sensible approach both in terms of semantics (yes not everything is a has, hypernyms matters) and in terms of features. OOP allow encapsulation which is essential, better code reuse , visibility control, contracts and overriding. Rust do not have constructors so the method to instanciate a resource is conventional.. All of that because people have seen too much memes on twitter about Java factorySingletonDank which are indeed non-representative about reasonable code in the wild. see also concrete examples: https://medium.com/hackernoon/why-im-dropping-rust-fd1c32986...
bonuses: String types hell
no named parameters in 2022, do they fail to realize denoting and accessing semantics is the most important thing in programming? That means in many context, rust code is much less understandable.
no unified async runtime..
There are other omissions, such as no overloading, this post is non-exhaustive.
That you disagree or not with some or all of my quantifiers is a thing but you have at least to agree that there is a real market for a better C++ that would be non-hipster and pragmatic with a goal of maximizing code clarity and the developper cognitive bandwith while retaining runtime performance. That better C++ would be C#/Kotlin-like but leverage LLVM and have no-GC.
A testimony from a previously rust fanboy that has following rustc development since its pre-1.0.
Edit yes flagging me is a good sign validating the belief of HN being an effective echo chamber that force-align allowed thoughts and beliefs and amplify them.