Showing posts with label functional programming. Show all posts
Showing posts with label functional programming. Show all posts

Monday, March 6, 2017

Functional Programming like an OOP-er?

So, I've been learning much about Functional Programming techniques. Elm-lang is a great budding FP language that transpiles to javascript and is optimized for the browser - haven't seen much in the way of server-side packages for it...but then again, I haven't really looked.

One key feature of the FP languages I wan't to riff on is Currying - basically it's where you create a new function that does the same thing but with less parameters and you set defaults.


In javascript, for example if you had the following function...

    function saySomething(message, person){
        ...
    }

you could curry the message and create a new function to sayHello

    var sayHello = function(person) {
        return saySomething("Hello", person);
    }

Well, that's all well and fine. Our sayHello function would only be able to say "Hello" as that would basically be set in stone for this "instance" of saySomething. I said instance didn't I? Couldn't think of a better OOP way to put it. It's also called a closure isn't it? Basically we are creating a function object that has a locally scoped value of "Hello".

It could also be written like this (which is a bit more re-usable):



    var sayHello = currySaySomething("Hello");

    function currySaySomething(message) {
        return function(person){
            return saySomething(message, person);
        }
    }

//or if you like

    function currySaySomething(message) {
        return function(person){
         var _message = message;
            return saySomething(_message, person);
        }
    }

And in this way, an instance of the function object "saySomething" is returned as a closure with the locally scoped variable "message". It can be done another way...this one is straightforward OOP in javascript.


    var helloSayer = new HelloSayer();
    helloSayer.sayHello({name:"Li"});

    function HelloSayer() {
        var _message = "Hello";
        return { 
            sayHello : sayHello
        };

        function sayHello(person) {
            return saySomething(_message, person);
        }
    }

Well, that's an OOP way to do it, but it still meets the same goal of immutable state that's important to FP. But if you think about it - currying is really setting the internal "state" of a function. It's kind of like using a Factory, although in the example below it might be a bit overkill - could just use new Sayer("Hello"), but that's not the point of a Factory. If you need a Factory, there it is.


    var factory = new SayerFactory();
    var helloSayer = factory.build("Hello");
    helloSayer.sayHello({name:"Li"});

    function SayerFactory() {
        return { build : build };
        function build(message) {
            return new Sayer(message);
        }
    }

    function Sayer(message) {
        var _message = message;
        return { 
            sayHello : sayHello
        };

        function sayHello(person) {
            return saySomething(_message, person);
        }
    }

I guess what it comes down to is how you use the objects. One could have objects that hold internal immutable state. Using an OO language it's often necessary to avoid overly-complex, unreadable code.

Thursday, September 8, 2016

What We Can Learn About Generalization From Clojure

Clojure is a functional programming language based on LISP (List Programming) but built on top of Java runtime. There's a version built on JavaScript as well. A great resource for learning Clojure can be found here.


The link to the Clojure resource goes to the third part of the lessons because I want to highlight how that particular walkthrough goes from something specific, to something more general when it comes to the recursive function. It basically builds a map function from the ground up.


Hold that thought in mind and think about how software is built and how it can generally be improved over time. Software is "soft", it is malleable. It is meant to be changed so that we humans can take something that is so general "hardware" and plug in some instructions, in a language that we understand, for the generic computer to perform specific operations.


Generalizing functions/methods is the holy-grail of software. Big idea, I know. But here's why I say that - when we generalize functions they become reusable. When they are reusable, we don't have to keep rewriting them. If we never strove for re-use, everything could be hardware - hardcoded ICs that were task specific. And we wouldn't have very good technology at all. That was the state at one time. But since we have Software, we have re-use.


But, we can't generalize world. We wouldn't choose to use different languages if we could generalize indefinitely. Or the generalization would be so unwieldy that it would become a language of its own. But isn't that what a software language is? An ultimate generalization? Point is, there's a limit to generalization. It's situational most times and depends on the use cases.