7 ms·
Can you give an example for #2? I picked up Rust this year and never found that to be the case. In fact Rusts type system is extremely clear to me and was prett
by hansonkd 4y ago
Can you give an example for #2? I picked up Rust this year and never found that to be the case. In fact Rusts type system is extremely clear to me and was pretty straight forward coming from a Python world. I don't think I ever encountered anybody quoting Category theory at me.
I used Haskell for a few years and the main problem with it is that to do anything you need to use Monads, Functors and a lot of complex types. It's a requirement to even write the most basic program. "strange" functional stuff proliferates haskell like `foldl` and `foldr` and a extremely discouraging Lazy computation model that makes it almost impossible to know what the compiler will do unless you have a near perfect comprehension of all the language.
Rust to me is as simple as writing annotated Python or Typescript, with the only addition that a beginner needs to know is that there is a new option that those two languages don't have which is pass by reference or pass by value. The lifetime stuff was really easy to get, "pass a value into a function, can't use it anymore."
The Rust compiler gives extraordinarily useful error messages. I don't know if haskell improved but you can end up with some very strange stuff to figure out.
The only real hiccup I had when learning Rust was that going from `sync` to `async` code had a bit of a learning curve. It was simple for basic stuff, but the problem were that Future's have their own Lifetime that depends on every piece of data used in the computation between `await` calls. This means all your data needs to be Sync + Send if you want to use Async.
- petesergeant 4y ago> the only addition that a beginner needs to know is that there is a new option that those two languages don't have which is pass by reference or pass by value I think anyone who's done anything beyond beginner JavaScript is going to understand the difference between pass by value and pass by reference, even if they don't call them that? function foo1( val : string ) { val = "hi" } function foo2( val : [string] ) { val[0] = "hi" } const bar : [string] = ["yo"]; foo1( bar[0] ); console.log( bar ); foo2( bar ); console.log( bar );
- iterateoften 4y agoThe big difference when I use Rust is that in Rust every variable you accept in a function requires you to make that choice. Whereas JS it’s kind of chosen for you. In your example you had to go out of your way to do it. So just a bit more mental overhead for implementing libraries. But not a huge deal.
- ptero 4y agoIt is not just the abstract knowledge of the difference, but the fact that "let b = a" makes a undefined and, especially, some comfort with a Rust-ic way of dealing with this. My 2c.
- gavinray 4y ago> I think anyone who's done anything beyond beginner JavaScript is going to understand the difference between pass by value and pass by reference, even if they don't call them that? Pass-by-reference is a concept that is unfamiliar to many (most?) modern JS/TS developers, as the common idiom is that you "return" a new object or value at the end of your function. If you want to update a value in an existing object, you pass it by value and return a clone of it with the updated values Performance doesn't matter, you can do the most pants-on-head-stupid thing you can imagine, or have your frontend page/component be re-rendering 20 times on every state change, and it makes no perceptible difference. (This has been my experience) It wasn't until I learned C that I realized you might even program in this fashion (somewhat to my horror) where passing variables to functions could mutate them
- petesergeant 4y ago> It wasn't until I learned C that I realized you might even program in this fashion (somewhat to my horror) where passing variables to functions could mutate them If you pass an array to a function in JavaScript, then any changes you make to it will mutate the version the caller has.
- nyanpasu64 4y agoSome Rust programmers, when faced with performing operations on a sum type (like Result) or container, tend to reach for point-free map-filter-reduce code stuffed with higher-order functions, lambdas, trait generics, and return type inference, requiring looking up the documentation or implementation of multiple helper microfunctions, and asking the compiler for the inferred return type. My preference is usually to write imperative code matching over objects or looping over iterators, except in cases like "minimum of list" where the loss of clarity of a loop exceeds the loss of clarity of a reduce() method call. Separately, to express code which creates multiple non-const references into a single object (trivial in any other imperative or OOP language), you need compromises like verbose Cell, overhead RefCell, ugly and footgun-filled UnsafeCell and raw pointers, unsafe confusing (and currently unsound, see https://github.com/rust-lang/rust/issues/63818 https://github.com/rust-lang/rust/issues/63818) Pin, or experimental ghost cells (https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf https://plv.mpi-sws.org/rustbelt/ghostcell/paper.pdf, not sure the current implementations).
- hansonkd 4y agoYMMV but I personally have never faced either problem having written tens of thousands of lines of Rust at this point. But to be honest I never worked on a large team of Rust engineers. One of the benefits of Rust is that it gives you an option to switch to imperative style if thats what you choose which isn't the case for Haskell or purely functional languages. Tacit programming was never a problem as the IDE does a pretty phenomenal job of telling you the types anyway. If the IDE can't figure out the type, the compiler won't either. non-const references in a single object can simply be solved by making the whole object mutable, which is essentially what Python et al. do for you anyways. I never had to use any unsafe code or pointers. Not sure if that way of thinking is carried over from C and C++ engineers. The only time I think I use Cell or the like is if I have a global static variable that I need to fill in at runtime. But that is more of a code-smell for most or at best a more advanced programming design that beginners don't need to worry about. The best way to solve the last problem is to understand your data model from the start and make what objects need to be mutable mutable.
- jononor 4y agoTo be fair, this kind of thing even happens in JavaScript. Some use functional programming with immutable datastructures, higher order functions, super generic code, using some niche FP library with its own idiosyncrasies - when simple and imperative would do just great.