Functional Programming is Dead, Long Live Expression-Oriented Programming

It’s funny how over time the meaning of a technical word will converge to something halfway between what the experts intended and some fuzzy notion consisting of the most easily graspable components of that idea. In this inevitable process an idea is stripped of all of its flavor and is reduced to a set of bullet points graspable in an hour long presentation. Over the last few years this has happened to functional programming, right along with its popularization.

From Wikipedia:

  • First-class and higher-order functions
  • Pure functions
  • Recursion

Now that almost every language has tacked-on “functional features”, the functional party is over. The term has become just as perverted as Object-Oriented is to its original idea. It seems as though these days all it takes is lambda expressions and a higher order functions library to claim your language supports functional programming. Most of these languages don’t even bother to include any kind of proper support for simple tail recursion, much less efficient co-recursion or function composition. Oh, and any kind of inclination toward even encouraging purity? You wish.

But this isn’t necessarily a bad thing. The term functional isn’t at all evocative of the actual properties that make functional languages so wonderful. The term we should have been using all along is Expression-Oriented Programming. It’s the composition of expressions, the building of programs by sticking together little modular pieces, that makes functional languages great and first class functions are just a small part of enabling that. Expression-Oriented Programming tends towards first classing everything.

However, even the term first class is too weak to pin down this concept. All first class means is “as good as most other things” and this can still imply a really awful lowest common denominator. Just take a look at Microsoft’s C#. Sure, functions are first class, but it’s still a pathetic attempt at emulating what is possible in functional programming languages because the rest of the language isn’t.

Let’s end with a simple example to drive home the point. In C#, because the switch statement doesn’t produce an expression, you can’t assign its result to a variable. You even get an error that tells you so.

However, F# does a much better job of supporting Expression-Oriented Programming as almost every language construct outside of type definitions is itself an expression.

Expression-Oriented programming a simple idea, just programming with little composable parts, but it leads to beautiful and expressive code. It is at the core of why programs in functional languages are small, simple and less error prone. We should give credit where the credit is due, not to just the functions who are but one small player in the Expression-Oriented story.

Enjoy this post? Continue the conversation with me on twitter.

Tags: , , , , , , , ,

26 comments

  1. Yep, love how similar the F# can be to its Erlang cousin

    X = case N of
    1 -> “one”;
    2 -> “two”;
    _ when is_number(N) -> “number”;
    _ -> “no idea”
    end,

  2. I’m with you on this one. Composition is my favorite aspect of programming, so I find languages that foster composition particularly attractive. Reliance on expressions (over statements and state) is the single greatest factor toward reliance on composition.

    I don’t agree that expression-oriented leads toward first-classing everything. Perhaps I haven’t recognized your line of argument. My resistance comes from my awareness that in the J programming language higher-order functions are not first-class. (First-order functions are.) This does not, that I can tell, undermine or reduce J’s extremely expression-oriented nature.

    • Well, if it’s not first class how can it compose well? Perhaps if it has separate syntax but the same functionality? I just see “first class all the things” as an easy way to enable composition.

      Would you mind providing a sample? I’m curious about how higher-order functions might work if they aren’t first class.

      • I’m unsure how best to communicate the way modifiers (higher-order functions) aid composition in J despite not being first-class. What I can do easily is offer a J program that is similar to what you’ve used in your examples. After the six definitional sentences will be a few examples of use.

        cases =: ‘one’;’two’;’number’
        pick =: >@{
        which =: [: {. I.,_1:
        matchValue=: 1 2 = ]
        byAtom =: “0

        describe=: (cases pick~ [:which matchValue) byAtom

        x =: describe 2
        x
        two
        i. 2 2
        0 1
        2 3
        describe i. 2 2
        number
        one

        two
        number

        In the final example the input value is a 2-by-2 array of integers and the result is a 3D array of characters, one list of characters for each of the numbers comprising the input.

        The overall program, named ‘describe’, is an expression comprised largely of other named expressions. The composition of expressions occurs throughout. There are no “statements” here. One of the named entities, ‘byAtom’, is a modifier. As I said, modifiers are not first-class because a modifier cannot be an argument to anything. ‘byAtom’ facilitates composition, in this case, by assuring that the resulting verb is applied appropriately to its argument. As a result ‘describe’ will compose neatly within larger expression.

  3. Totally agree and that’s what makes Lisp (Clojure etc) awesome :)

  4. So, following the example, Ruby is closer to be an Expression-Oriented programming language than C#? :)

    x = case n
    when 1 then ‘one’
    when 2 then ‘two’
    else ‘number’
    end

    or

    x = if some_condition
    statement_if_true
    else
    statement_if_false
    end

  5. Ternary Operator is a cool guy.
    var x = n == 1 ? “one” : n == 2 ? “two” : “number”;

    Gotta agree with your sentiment, however. I can’t count the number of times that not even my good friend mr. ternary could help with writing an elegant expression, because the language support just wasn’t there.

  6. Switch statement is awful in all the C languages. Buy with ternary operator you can fix it:

    var x = n == 1? “one”:
    n == 2? “two”:
    “number”;

    Of course pattern matching is more powerful, but C# makes an excellent in the expression-oriented-programming battle: It has expression trees, something that almost no other one has.

    • It’s a syntactic example, not a functional one.

      Most of F#’s constructs don’t have a direct C# equivalent. Match is actually a ton more powerful than switch, but I was looking for something somewhat comparable here.

  7. There’s a reason the c# “switch” doesn’t behave as an expression: because you *are not required to have a result from each branch*. Or even any branch. You are comparing apples and oranges, and then complaining that they taste different.

    “switch” is **not** “match”, and directly comparing the two is disingenuous.

    Now, the following isn’t as direct/elegant, but consider:

    Func x = n => {
    switch (n) {
    case 1: return “one”;
    case 2: return “two”;
    default: return “number”;
    }
    };

    • Yes, this is a fundamental difference with F# and is precisely why it’s better at expression oriented programming. F# even has a special type for expressions that don’t return anything called unit.

  8. Sorry, in the above, angle-brackets got stripped. Should be:

    Func<int, string> x = n => {
    switch (n) {
    case 1: return “one”;
    case 2: return “two”;
    default: return “number”;
    }
    };

    • +1 Marc’s example. Although C# doesn’t support pattern matching (which would be nice), I am not convinced. It is fully possible to write a C# without any imperative control structures at all, especially with Rx. I agree that you wouldn’t really want to do that until and unless C# allows the same kind of query expression support that F# has, but it’s definitely possible.

  9. Actual expression-oriented programming has another distinguishing characteristic: configurable evaluation of expressions. Otherwise, all the expressions just evaluate or reduce immediately when eager evaluation is the default, or the expressions never evaluate when lazy evaluation is the default.

    In expression-orientation, everything is an expression including functions. In order to pass a function expression, it can’t be immediately evaluated into its return value at that time, but left unevaluated to be called later by the higher-order expression receiving it. (Or maybe you “partially evaluate” it at the time it’s passed.) Lisp has quoting for that reason.

    If configurable evaluation is missing, then it’s probably not expression-oriented programming.

    • Deciding what ends up being expression oriented or not seems pretty fuzzy using this definition. For example, does partial application imply it? It’s configurable in the sense that you can decide how much to pass in and when. What about pure lazy? You never really get control over when it executes.

      Interesting thoughts though.

  10. F# is very similar to LISP. A language that we all ignored, simply because it consumed too much memory. I’ve never worked with a better language and most likely I won’t work with a better language.

    • Your comment bothers me quite as bit as it’s both ignorant and dismissive. F# code is faster than C# in most cases, and you always have the option to use mutable data structures when necessary. The price you pay for F#’s great properties is a somewhat slower compile time, no price is paid at run time.

  11. I love the expression style over statements and state but it’s a shame that (unit testing aside) debugging them is a pain (because it’s hard to track the intermediate results). I see too much code with locals just to park intermediate results when we should really have more powerful debuggers (when you’ve just gotta use one).

  12. [...] Functional Programming is Dead, Long Live Expression-Oriented Programming (richardminerich.com) [...]

  13. [...] Functional Programming is Dead, Long Live Expression-Oriented Programming (richardminerich.com) [...]

Leave a comment