A few of my favorites include: first-class functions, algebraic data types and opaque data types.
First-class functions
Because of all the cool abstractions — map
, filter
, accumulate
, fold
etc — you can build with them.
(define (map f l)
(if (null? l)
'()
(cons (f (car l)) (map f (cdr l)))))
Algebraic data types
Especially sum types. I think all languages should support this feature. They make it really convenient to precisely model your domain.
Ruling out invalid data makes your code shorter, simpler, and more reliable. By making sure the set of possible values in code exactly matches the set of valid values in real life, many problems just go away. — Types as Sets
type RemoteData e a
= NotAsked
| Loading
| Failure e
| Success a
Opaque data types
Data abstraction allows you to hide implementation details and it makes it favorable to change representations. For e.g. you can start with a naive implementation and change to a more efficient representation if it proves critical to the overall performance of the system. Opaque data types are frequently used to implement abstract data types.
module Stack
( Stack
, empty, push, pop
) where
data Stack a
= Empty
| Stk a (Stack a)
empty :: Stack a
empty = Empty
push :: a -> Stack a -> Stack a
push x s = Stk x s
pop :: Stack a -> Stack a
pop Empty = Empty
pop (Stk _ s) = s
And you?
Top comments (11)
Rust has Enums and Traits which are Sum Types and ADTs in other languages. They are really nice to use because Rust forces you to account for all the possibilities when you match against an Enum. Also Traits allow for a really nice way to extend and use familiar interfaces in new ways. Traits are also used for overloading operators like
+
or-
on custom defined types. Rust'sIterator
trait is really interesting and is used in a lot of different places.Ruby is my main love, so blocks are a really wonderful feature that are similar to lambdas. They are so easy to use and allow the nice functional stuff like
map
,reduce
, etc. Also Ruby's metaprogramming syntax is a little too easy, but is also super powerful when you need it.Yeah, Rust is really nice.
I like that you can do systems level programming using high-level programming abstractions. And its borrow checker, I'd love to learn the theory behind it someday.
What are you working on with Rust?
The borrow checker is actually surprisingly simple, although the consequences of having it are complex. Basically you can either borrow immutably, borrow mutably, or own data. An immutable borrow can be shared in many contexts at a time, a mutable borrow can only be shared with one context at a time, and ownership means you're giving up that data to another context.
I've been working on a raytracer/pathtracer. Although I'm not very good at the trig yet. I also wrote a Piet language interpreter.
Interesting that you're working on a raytracer. That is the project I plan to do when I decide to learn Rust.
I started implementing one many years ago in C but never completed it. Then, I did one in Python to relearn the concepts but it's obviously slow as hell. Rust would be ideal.
All the best with your raytracer.
Thanks! You too.
My picks (from Elm):
case of
expressions and Pattern matching: being able (obligated) to exhaustively check all possible patterns of a given expression makes programs much more robust.|>
operator: Cleaner code by getting rid of the parenthesis.I can live without everything but ADTs and pattern matching. In languages without these features, everything feels so clunky.
Yes, +1 for immutability and pattern matching on tagged unions as well.
By ADTs do you mean algebraic or abstract data types?
Union Types and Product Types, the ones supported by Elm.
Not sure i have a favorite feature, i am more a structure/architecture lover.
But if i had to pick, then i would go back to the basics and say functions.
Simply because i cannot imagine writing software without them.
Everything else can go, but i don't wanna goto'.
I've found that certain features can lead you to structure your app differently. The two go together in my experience.
Definitely. Abstraction is central to problem solving and programming. And functions are the key ingredient.