1. 11
  1.  

  2. 8

    I am one of the non-functional programmers who’s still skeptical. I’m learning Haskell very slowly in my spare time. I’m also a math person but I generally don’t find myself appreciating FP’s math-y-ness.

    Anyone, responses to the slides:

    1) Pure functions - I think an appreciation of pure functions extends to multiple domains. I’d say standard imperative or oo design would say “better pure than impure” but wouldn’t insist on pure all the time. FP’s focus on pure functions seems to involve

    2) Immutable data - This doesn’t seem like good stuff relative to monads. Rather, monads are a counter-intuitive approach that is extremely useful for dealing with data when you want to maintain the assumption that this data is immutable. Immutable data seems like a real mess if one going to quickly write, say, an Asteroids-like game (a programmer friend told me about spend two months trying and failing to write Asteroids in Haskell). After reading more, I found the argument that if Asteroids is considered a simulation, then having each cycle of a simulation conditionally produce a bunch of diffs and then putting them together is a better way - and that can very appropriately be done with monads.

    And all this adds up, in my mind to something like FP being a “good, right way to design a program” and FP languages being tools that enforce this goodness. Which makes FP very much not analogous to either OO design and FP languages very much not analogous in purpose to OO languages. Especially, OO is much more like “just a tool” - you can use OO techniques to add another datasource to some huge piece of enterprise software by creating an interface that makes the new datasource look the old datasource. And the rest of program wouldn’t even need to be designed in a sane, OO way at all. Such an action may akin to organ transplants for dying patients but it’s still the stuff that many programmer’s jobs are made of.

    FP isn’t an alternative to OO as such but an alternative to giant craptastic enterprise somewhere overall. I may be skeptical

    But anyway, I suppose my main conclusion is that the level that FP operates at often isn’t made clear by its proponents. It would be easier to understand if presented as “a discipline for producing a globally superior architecture” rather than generically better programming “approach” since the latter statement isn’t clear the level the approach operates on.

    Or you can consider this my effort to describe what I think I understand and tear into it as you will.

    1. 9

      So, I’ll bite. I am a “functional programmer,” I guess you could say, in that I’ve taught myself a lot about functional languages, do problems and side projects in Haskell, and so on; but my day job is and has always been in imperative languages. For the last three years, I’ve written Java and Ruby. Before that, I wrote Python and PHP, and now I’m back to Python again. The omnipresent scourge of Javascript haunts me everywhere I go, of course, but that goes without saying.

      I use functional principles when designing, refactoring, and critiquing code in all of these languages. I find that it gives me a clarity of purpose in places where other methodologies are “fuzzy,” where there aren’t easy answers or the answers that you can find are merely questions of taste. The approach I take centers around purity, immutability, transparency, and transformation-oriented code. I will use (anonymized) examples from a code review that I did today.

      def generate_something(config, a_flag=True)
          if config['unrelated']
              fail "Cannot generate anything without the unrelated values!"
          end
      
          result = []
      
          config['things'].each do |thing|
              next if thing['foo']
      
              result << "#{@bar}/#{@baz}: #{thing}"
              result << "#{@bar}/#{@quux}: #{thing}" if a_flag
          end
      
          result
      end
      

      This is pretty typical code, I think, that people wouldn’t bat an eye at. It’s not beautiful, but it serves a purpose, and usually people wouldn’t be tempted to refactor it. In this code review, I made several points:

      1. The test for the config['unrelated'] flag should be done elsewhere, because the values aren’t used inside the function.
      2. The loop can be clearer if expressed as a transformation of a list.
      3. Pass in only the data that is necessary; don’t use objects that know too much.
      def generate_something(things, a_flag=True)
          things.select { |t| !t['foo'] }.flat_map do |t|
              baz = "#{@bar}/#{@baz}: #{thing}"
              quux = "#{@bar}/#{@quux}: #{thing}" if a_flag
              a_flag ? [baz, quux] : baz
          end
      end
      

      This is a more functional approach: it has less access to the outside world. It’s not modifying anything internally. Its loop is a transformation. This method almost has the type [Thing] -> Bool -> [String]. Almost, because there are those pesky instance variables. If I wanted to completely make this functional, I’d have the method accept a different argument:

      def generate_something(things, string_templater)
          things.select { |t| !t['foo'] }
              .flat_map { |t| string_templater.call(t) }
      end
      

      This would give the method the type [Thing] -> (Thing -> [String]) -> String. It isn’t necessary, because the implicit self object is actually an argument to all methods, but that’s how it could proceed, if needed.

      Why learn to do this? Ultimately, it’s because I like to have a set of principles which I can trust in the context of almost any problem. I think that many of the object oriented techniques that we have learned, in particular the SOLID principles and some “design patterns,” are halfway to functional programming from the “real world” side. That’s great! It’s good to have techniques that are proven in practice rather than theory; but without the theory, it starts to become difficult to know how to apply those principles in places where you don’t have any practice.

      As another example, consider the “Null Object” pattern. Null is a problem throughout object oriented programming. Tony Hoare famously called it his “billion dollar mistake.” Fine: we can address it with the “Null Object” pattern, right? Except that, in order to make consistent use of this pattern, you need to implement a null object for every class in your system. You have to religiously use them, and they don’t even eliminate null checks.

      if (pet == null) pet = Pet.NULL_PET;
      

      On the other hand, if you approach this from a category theoretical perspective, you get… monads. The semantics of Maybe a work for all types a, because they must. It’s just math. There are no null checks because there are no nulls; if a null result is possible, then you’ll return Maybe Pet and be done with it.

    2. 8

      The title reads, “Is it worth it?” and there are 57 slides. Not one of the slides attempts to set up a comparison in order to understand “worth it compared to what?” and not one of them attempts to establish a measurable value that can be compared to anything. Toward the end, the message becomes “you’re already doing FP” if you do x, y, or z.

      I am unsure what value this presentation provides over similar presentations that have been made in recent years.

      1. 3

        Not one of the slides attempts to set up a comparison in order to understand “worth it compared to what?” and not one of them attempts to establish a measurable value that can be compared to anything.

        This is wrong. The list of “useful things” (slide 18) all have natural opposites to compare them with (e.g. “pure functions” has impure functions, “immutable data” has mutable data, etc) – there’s your “worth it compared to what”. And then each of those useful things gets its own “Why _______?” slide in which the advantages to the approach are explained.

        The message of the presentation is that developers coming into FP shouldn’t ignore the fundamental principles because of a distaste or misunderstanding of the tools which help us apply the principles. If it’s been said before, good.

        1. 4

          OK, to be more specific then, I would say the slides provide a very superficial comparison. There is an insufficient value calculation to suggest it addresses the “Is it worth it?” title.