Functional vs. Imperative
When trying to describe Up, a word I often embrace is “declarative”, as in the opposite of “imperative.” Why tell the compiler “how” to do things step-by-step when you just describe “what” you want and let it derive the steps? That has been a primary goal in each of the languages I designed prior to Up, but looking back at them now, I see they were still just imperative languages with a few domain-specific declarative facilities.
Where I went wrong was saying “declarative” when I really meant “functional”. I’m ashamed to admit it now, but I’ve always run away screaming from functional programming. The closest I‘ve come to it was occasionally replacing “for” loops with a little bit of “map” and “filter”. I was always curious, but too focused on getting things done to endure the pain of flipping my worldview upside down.
When I began studying Haskell and Clojure while designing the latest version of Up, it finally clicked. Functional is not the impractical, gratuitous exercise in code gymnastics I thought it was. No, it is the missing ingredient that I needed to make Up a truly declarative language.
I’ve come to think of a functional program as being data masquerading as code. Your “program” is like a database of relationships, and you only need a tiny bit of imperative code to put that data into action.
I’m not yet sold on functional purity. I still think imperative code is the best way to speak to external systems which are also imperative. Also, some algorithms that are just awkward to expression in pure functional terms. You could use monads to try and emulate imperative execution, but I’d prefer to just write actual imperative code.
The key, I think, it to write as little imperative code as possible, and to ensure that its side effects are predicatable. So, even though Up will support imperative code, its standard library will offer mostly functional solutions, and I hope that will be enough to create a culture that puts imperative in its proper place.