2

I want to model simple objects as functions, to see where the pure functional approach gets me. Let's say my object is a person. There is some function that returns me a new person, but instead of just some data structure, it returns me a function that represents the person. I'm having difficulties to see what this function should exactly look like, because I mostly associate data/state with a person but not any function. So if I call this person, which is a function now, what input should it take and what should it return?

If I look at the lambda calculus and some examples of how to model numbers, 0 is just the identity function. 1 is a function that takes another function and a value as input and returns the argument function applied to the value. 2 applies the function twice, etc.

So should the implementation of a person be a function that takes another function as input and applies it to the person, returning its output? So it's actually just a container for the person's data allowing other functions to operate on it.

May be it makes no sense to think about this without knowing exactly what a persons consists of. In a most simple case a person could be just a name. A briefly tried to outline this in Clojure:

(defn new-person [firstname lastname] (fn [f] (f firstname lastname)))
(defn get-firstname [person] (person (fn [x y] x)))
(def p (new-person "Maja" "Abel"))
(get-firstname p)
"Maja"

Then again the names are strings and not very functional ...

Hope this makes some sense, glad if anybody has some thoughts on it!

asked Jan 26, 2014 at 15:35

1 Answer 1

6

We can implement numerics as pure functions – but we don't actually do so for performance reasons. We can model a cons cell (and thus arbitrary lists) through pure functions, but we don't usually do that. Again, for performance reasons. And if we can model numbers and lists, we can model arbitrary strings or other things.

However, it might be useful to think about that cons cell/a pair for a moment.

A cons constructor takes two elements and returns something. The car function somehow accesses the first element in this something, whereas the cdr accesses the second entry. Here is one implementation in JavaScript:

function cons(x, y) {
 return function (gimme_first) {
 if (gimme_first) return x;
 return y;
 };
}
function car(cell) {
 return cell(true);
}
function cdr(cell) {
 return cell(false);
}

So essentially what we did was return a closure over the state. We can access the state by applying the closure to a specific identifier.

We can easily extend this to arbitrary objects: Our constructor sets up some contents of the object, and returns a closure over it. This closure can be applied to a field name to return a value or a method (which also closes over the object's data):

function Person(firstname, lastname) {
 // set up the methods as closure over our data
 // they could also take parameters if you'd like
 var get_firstname = function() { return firstname; };
 var get_lastname = function() { return lastname; };
 var get_fullname = function() { return firstname + " " + lastname; };
 // set up the dispatcher
 return function(method) {
 if ("get-firstname" == method) return get_firstname;
 if ("get-lastname" == method) return get_lastname;
 if ("get-fullname" == method) return get_fullname;
 throw "Unknown method name " + method;
 }
}

Now we can instantiate multiple objects:

var maja = Person("Maja", "Abel");
var freddy = Person("Freddy", "Smith");
maja("get-firstname")(); // Maja
freddy("get-lastname")(); // Smith

How does inheritance work? Our constructor defers to another constructor, and our dispatcher passes control to the parent:

function Employee(firstname, lastname, department) {
 // set up the parent object
 var parent = Person(firstname, lastname);
 // override a method
 var get_fullname = function() {
 return parent("get-fullname")() + " (from " + department + ")";
 };
 // set up the dispatcher:
 return function (method) {
 if ("get-fullname" == method) return get_fullname;
 return parent(method); // method lookup continues here
 };
}

Etc.

This is actually quite similar to how JavaScript handles object orientation anyway: The dispatcher is usually a dictionary (called "object" anyway) which is more efficient than our functions, and object state is communicated via the implicit this parameter instead of closures.

answered Jan 26, 2014 at 16:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.