6 ms·
For me (and I'm going to sound like a massive fan boy here) Rust has surpassed functional programming. It gives me mutable data when needed and immutable when s
by AlexanderDhoore 7y ago
For me (and I'm going to sound like a massive fan boy here) Rust has surpassed functional programming. It gives me mutable data when needed and immutable when shared. So ONLY having immutable data structures now seems stupid. We can have best of both worlds.
Read this if you don't follow: "In Rust, ordinary vectors are values" http://smallcultfollowing.com/babysteps/blog/2018/02/01/in-rust-ordinary-vectors-are-values/ http://smallcultfollowing.com/babysteps/blog/2018/02/01/in-r...
- deleted 7y ago[deleted]
- marcosdumay 7y agoFrom the abstract, the main point of the article is: > ...higher-order functions and lazy evaluation, can contribute significantly to modularity. You can not have lazy evaluation without referential transparency, and you can not get referential transparency with mutable variables. Rust does good use of high-order functions, but gets nothing near the modularity of Haskell code.
- rtfeldman 7y ago> Rust does good use of high-order functions, but gets nothing near the modularity of Haskell code. This has not been my experience. After years of doing pure functional programming (in Elm) professionally, I was surprised how much Rust felt like writing in an ML family language. I still prefer referential transparency (though I don't think it would have been the right design for Rust), but "nothing near" does not fit my experience. I'd say the ergonomics of borrow checking versus a GC (which you don't have to think about) is the bigger gap. John Hughes is a big believer in the value of laziness. There are many of us who believe laziness turned out to be a dead end; it makes some code nicer/more elegant, makes performance optimization much harder, and brings space leaks into your life. Are those costs worth the benefits? Not even close to worth it, if you ask me. I'll gladly take the referential transparency and pass on the laziness. Almost all the researchers who started working on Haskell specifically because they wanted to explore the power of laziness...ended up pivoting to research type theory instead. I don't think that's a coincidence.
- zenhack 7y agoDon't get me wrong, I like Elm a lot, but the drop in expressiveness/ability to build abstractions from Haskell is substantial. Especially when you're looking at modularity, there are a bunch of things that Elm can't abstract out that both Rust and Haskell can manage just fine. I haven't used Rust heavily enough to comment on how it compares in great detail, but comparing to Elm as a proxy for Haskell doesn't really work. Frankly, paradigms are a really lousy way to think about languages. I wrote a series of blog posts about this[1], but this opening lecture from one of Brown's PL courses I think does a better job of making the point: https://www.youtube.com/watch?v=3N__tvmZrzc https://www.youtube.com/watch?v=3N__tvmZrzc It's useful to talk about what say, GC, laziness, lifetimes, ownership, typeclasses/traits, higher-kinded types, higher rank types, variants, elm-style records, etc. do to a language, and how they compose, but I think you can't go very far talking about how "paradigms" compare. [1]: https://zenhack.net/2018/07/14/three-funerals-in-the-name-of-clarity-3-systems.html https://zenhack.net/2018/07/14/three-funerals-in-the-name-of...
- rtfeldman 7y ago> It's useful to talk about what say, GC, laziness, lifetimes, ownership, typeclasses/traits, higher-kinded types, higher rank types, variants, elm-style records, etc. do to a language, and how they compose, but I think you can't go very far talking about how "paradigms" compare. Sure. My experience has been: * GC, lifetimes, and ownership are all high-benefit and high-cost. The cost with GC is at runtime (where the cost is so high that in many domains GC is not tolerated at all; in many others, of course, we take it for granted as fine), and the high costs of lifetimes and ownership are at development time. * Variants and records are high-benefit, low-cost. * Higher-rank types are low-cost, low-benefit. * Laziness and higher-kinded types are both features with costs that significantly outweigh their benefits. It sounds like you disagree with the last bullet point. If so, then either we've had different experiences or we walked away with different conclusions from them.
- zenhack 7y ago> * Laziness and higher-kinded types are both features with costs that significantly outweigh their benefits. > It sounds like you disagree with the last bullet point. If so, then either we've had different experiences or we walked away with different conclusions from them. I more or less agree on laziness (at least lazy-by-default; having a lazy type as found in OCaml available is a big win for little downside). Re: Higher-kinded types: I'm curious as to what you think the high costs are? My impression is that they've mostly been left out of Elm due to pedagogical concerns. Is it just that or are there other things?
- zenhack 7y ago> you can not get referential transparency with mutable variables Sure you can: https://homepages.inf.ed.ac.uk/wadler/topics/linear-logic.html#linear-types https://homepages.inf.ed.ac.uk/wadler/topics/linear-logic.ht... Rust's ownership types and lifetimes actually allow for this just fine. The latter is the essence of how Haskell's ST Monad works; you can use lifetimes to get locally-mutable state without violating global invariants, since once they go out of scope they can't be reused. It's interesting to observe that, without "magic" standard library functions and `unsafe`, Rust's type system actually completely constrains mutability, and if a function doesn't have `mut` somewhere in its type signature, it doesn't break referential transparency. That said, in practice, the language does have magic functions that violate this property, and they do so in a way that means you can't use the above reasoning principle at all. Also, mutability being constrained by the types is not the same thing as typical code not using it everywhere, which is the situation with rust-as-found.
- igouy 7y ago> You can not have lazy evaluation without referential transparency, and you can not get referential transparency with mutable variables. "… allowed to update the unique object destructively without any consequences for referential transparency." Uniqueness Typing https://clean.cs.ru.nl/download/html_report/CleanRep.2.2_11.htm#_4.5.1_Basic_Ideas https://clean.cs.ru.nl/download/html_report/CleanRep.2.2_11....
- ojnabieoot 7y agoBeing an OCaml/F# fan, I find this comment amusing. Rust is in fact heavily influenced by functional languages, particularly OCaml - OCaml-style algebraic datatypes and pattern matching are huge advantages Rust brings over C++ in terms of reasoning about complex domain logic. And OCaml/F# both have variables which are immutable by default but can be labelled as mutable in (e.g.) performance-sensitive regions. So it's odd to say Rust "surpassed" what other functional languages have been doing for literally decades now. I almost think of Rust as a lower-level OCaml (faster and better support for memory management, but with somewhat weaker support for typeclasses and an inconvenient ADT syntax). An ML language you can conceivably write an OS in, but I would personally be nervous to write a complex finance application vs. OCaml. And of course Rust also has typeclasses, with a design strongly influenced by (but somewhat weaker than) Haskell. Monads and Readers are all over the shop in modern Rust precisely because they are so useful in modern Haskell. Basically, the reason why Rust is such a good low-level programming language is the reason that functional programming matters.
- steveklabnik 7y agoFun fact: rust’s original implementation was in OCaml.
- jolux 7y agoI sometimes lament it's not more OCamlish, to be frank ;P Learning Rust inspired me to go learn OCaml. Not being a systems programmer and wanting pervasive garbage collection I don't want to go back now!
- foldr 7y agoOCaml's type system isn't capable of preventing shared mutable references. So you don't get the same compile-time safety guarantees in OCaml when you use mutation.
- brmgb 7y ago> you don't get the same compile-time safety guarantees in OCaml when you use mutation. OCaml is a garbage collected and mono-thread language. You obviously have the same guarantees in that you can't do what would be problematic. As a side note, a lot of the people currently writing Rust would ihmo be better served by Ocaml. You rarely need the protections Rust provides and they have a real complexity cost.
- nestorD 7y agoI love Rust but comes from an Ocaml/F# background (and, as others have said, the inspiration is palpable) and you seem to have a common misunderstanding around immutable datastructures. Immutable datastructures in functional languages are not datastructures that cannot be mutated, they are datastructure that efficiently produces a new, updated, version on each operation (such as the cons list). While they are slower than traditional datastructure for a typical use case, they tend to be a lot easier to think about, make parallel code much easier and let you easily get back in time to previous versions of your datastructures (when discovering rust, I was actually disapointed that they were not available in the std). The im[0] crate offers what seem to be good Rust implementations of that kind of datastructures (with abetter explanaition of why you would want them). [0]: https://docs.rs/im/13.0.0/im/ https://docs.rs/im/13.0.0/im/
- foldr 7y ago>Immutable datastructures in functional languages are not datastructures that cannot be mutated, This claim seems dubious. But in any case, I think the OP was just talking about immutable data, i.e., in Rust terms, data to which there is no mutable reference. The data in question could be a simple integer.
- nestorD 7y agoIt seems dubious because the FP community tends to use the expression 'immutable data structures' were 'persistent data structures' would be the proper term. As a matter of fact I have seen data structures, in FP language, called immutable while having operations to mutate them in place. I believe the OP spoke of both Rust immutable data and the fact that most FP languages have only immutable datastructures (different mecanism to deal with similar problems).
- foldr 7y agoI think they were referring to an actual difference between Rust and OCaml, Haskell, etc. Rust allows you to mutate data via mutable references that are guaranteed to be unique. Mainstream functional programming languages do not allow you to do this (though linear typing may land in GHC soon).