Skip to content

Instantly share code, notes, and snippets.

@H2CO3
Last active May 18, 2018 19:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save H2CO3/6d590fb821b507d77636741cbbe97ca1 to your computer and use it in GitHub Desktop.
Save H2CO3/6d590fb821b507d77636741cbbe97ca1 to your computer and use it in GitHub Desktop.
Rust…
- is functional
- but not pure, so you can printf-debug without IO() ALL THE FUNCTIONS
- has a strong Hindley-Milner type system
- but has convenient implicit coercions too, so you don't have to cast all over the place
- safe and high-level (with ownership, static/dynamic borrowing, Send and Sync)
- yet deterministic and fast with zero-/low-cost abstractions and RAII
- has a standard build system and dependency management
- but it doesn't force you to use it, and it has a simple Make-like CLI that doesn't hurt
- lets you write your code in the 'modern' IDE of your choice with all bells and whistles
- but also in Emacs or Vim if you just wanna get shit done
- looks like C, feels like C with safety belts (the compiler) and airbags (runtime checks)
- but syntax is 'name: Type', so even a dumb, context-unaware, naive, recursive descent parser can handle it
- and while we are at syntax: Types are UpperCamel, funcs_and_vars are snake_case
- but if you are not willing to write it the Right Way, you can turn off the warnings
- and while we are at C: it has sane precedence rules, so 'flags & 1 << MY_FLAG' does what you think
- but… no 'but's. This is just The Right Thing To Do™.
- you can #[derive()] most of the boilerplate, and the Debug format is beautiful
- but you can implement it yourself if you don't like the default
- unused imports are warnings, not errors
- and the Go programmers in your neighborhood are green with envy
- has generics
- and see the previous item about Go programmers
- has a real, hygienic, AST-node-rewriting-based macro system that Just Works™.
- and the Lisp programmers in your neighborhood are green with envy as well.
(((Un((like their))) ((mac)ro)s)), Rust's macros can actually be read.
- warnings are yellow, errors are red
- and roses are blue, but there no roses in Rust, only notes - which are also blue.
- uses Result<T, E> for error handling, no stupid exceptions and implicit control flow
- it's very apparent from a function's type if (and how!) it can fail, and
because foo()? is just sugar for match foo() { Ok(val) => val, Err(err) => return Err(err) },
there's no need to worry about any of the "Exception Safety" bullshit
- `impl From<T> for Option<T>` allows `foo.into()` instead of `Some(foo)`, which is almost as non-intrusive
as an implicit conversion would be, yet it's explicit and not magical.
- Makes expensive `.clone()`s explicit, unlike C++ copy ctors. I learned to love this feature.
- Has no inheritance! This turns out to be an advantage as well, as subtyping is very hard to get right,
and no "true OO" language seems to have achieved that to this day. Also, YAGNI.
- and Rust also has real sum types, which are very nice (as long as you are not trying to write a GUI widget toolkit).
- doesn't have call-site function parameter names (cf. Swift)
- it helps somewhat if you keep your parameter lists short – which you should do _anyway_.
Rust…
- allows shadowing variables :(
- I couldn't find a compiler warning that would disable it
- doesn't let you iterate over a Vec<_> or HashMap<_, _> without & or .iter() :(
- but… no buts here either, this sucks.
- calls int and uint isize and usize
- which is annoying and not too intuitive
@0cjs
Copy link

0cjs commented May 24, 2017

It seems that Haskell is "not pure" by your definition either, since you can do printf debugging in various ways. :-) Some of them, such as observe, I think are nicer than traditional printf debugging. (See also further discussion on SO.)

More generally, Haskell does not enforce purity itself; it enforces declarations of purity. As with a function such as trace :: String -> a -> a (effectively, idenitity with a side effect), there's nothing stopping you from making functions that have side effects without declaring them as such, using things like unsafePerformIO or the FFI. You typically wouldn't do that for reasons similar to those you wouldn't remove all const modifiers from your C programs, but it's there when you need it.

(As a side note, though I've never used Rust, I can understand how powerful type systems can be when helping with memory management. Quite a few years back I had to write some fairly low-level Haskell code to interface with the 1990s-era Windows DDI library functions, and it blew my mind the first time GHC pointed out that I'd forgotten to free something I'd malloc'd.)

@H2CO3
Copy link
Author

H2CO3 commented May 27, 2017

Well, unsafePerformIO seems like cheating, anyway. "it enforces declarations of purity" — yes, and of course this means purity, as long as you don't cheat. If you do cheat, however, you can break the rules in — I would say — any practical language. So, honestly, I would not be too comfortable with such things in Haskell, exactly because the interface is lying.

Observers seem a lot more civilized, although if my understanding is correct, they still do something fishy behind the scenes (I can't say if they do unsafePerformIO as well, I haven't looked at their implementation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment