We need a function to do our validations and add a person to the database. What might it look like? It should accept the attributes of a person and return
either an id (on successfully validation and insertion), or an error message, representing what went wrong. Since we don’t have exceptions or hashes - just arrays -
we’re going to have to get creative.

Let’s create a convention in our system that every business logic methods returns an array of size 2. The first element is the return value on success, and
the second element is an error message on failure. The presence or absence of data in one of these slots indicates the result.

Now that we’ve sorted out what we accept as arguments and what we’re going to return, let’s write our function:

123456789

add_person=->(name,birthdate,gender){return[nil,"Name is required"]ifString(name)==''return[nil,"Birthdate is required"]ifString(birthdate)==''return[nil,"Gender is required"]ifString(gender)==''return[nil,"Gender must be 'male' or 'female'"]ifgender!='male'&&gender!='female'id=insert_person.(name,birthdate,gender)[[name,birthdate,gender,id],nil]}

If you aren’t familiar with String(), it is a function that coalesces nil to the empty string, so we don’t have to check for both.

With this function, what we’d like to do is call it in a loop until the user has provided correct input, like so:

We can envision that our code is going to have a lot of if result[1] == nil in it, so let’s wrap it in a function.
The great thing about functions is that they allow us to re-use structure, as opposed to logic. The structure here is
checking for an error and doing one thing on success and another on error.

Notice what the use of handle_result allows us to explicitly name variables, instead of using Array de-referencing. Not only can we name error_message, but, using Ruby’s
array-extraction syntax, we can “explode” our person array into its attributes via the ((id,name,birthdate,gender)) syntax.

So far, so good. This code is probably a bit weird looking, but it’s not terribly verbose, or complex.

Clean code uses more functions.

One thing that might seem odd is that our person has no real structure or formal definition. We simply have an array, and a
convention that the first element is the name, second element is birthdate, etc. Our domain is pretty simple as-is, but let’s
suppose we want to add a new field: title. What happens to our code when we do this?

Our database team delivers new versions of insert_person and update_person to us:

add_person=->(name,birthdate,gender,title){return[nil,"Name is required"]ifString(name)==''return[nil,"Birthdate is required"]ifString(birthdate)==''return[nil,"Gender is required"]ifString(gender)==''return[nil,"Gender must be 'male' or 'female'"]ifgender!='male'&&gender!='female'id=insert_person.(name,birthdate,gender,title)[[name,birthdate,gender,title,id],nil]}

And, since we use these extractions in get_new_person, that has to change, too. Ugh:

This is the very definition of high-coupling. get_new_person really shouldn’t care about the particular fields of a person; it
should simply read them in, and then pass them to add_person. Let’s see if we can make that happen by extracting some of this code into new functions.

We’ve now abstracted the way in which we store a person into two functions: read_person_from_user and person_id. At this
point, get_new_person will not need to change if we add more fields to a person.

If you’re confused about the use of * in this code, here’s a brief explanation: * allows us to treat an array as a list of arguments and vice versa. In person_id, we
use the parameter list *_,id, which tells Ruby to place all arguments to the function, save the last, into the variable _ (so-named because we don’t care about its value),
and place the last argument in the variable id. This only works in Ruby 1.9; in 1.8 only the last argument of a function may use the * syntax. Further, when we call
add_person, we use the * on the results of read_person_from_user. Since read_person_from_user returns an array, we want to treat that array as if it were an argument
list, since add_person accepts explicit arguments. The * does that for us. Nice!

Back to our code, you’ll note that we still have coupling between read_person_from_user and person_id. They both are intimate with how we store a person in an array.
Further, if we added new features to actually do something with our people database, we can envision more methods coupled to this array-based format.

We need some sort of data structure.

Data structures are just functions

In non-degenerate Ruby, we’d probably make a class at this point, or at least us a Hash, but we don’t have access to those
here. Can we make a real data structure just using functions? It turns out we can, if we create a function that treats its first argument as an attribute of our data
structure:

new_person acts like a constructor, but instead of returning an object (which don’t exist for us), we return a function that, when called, can tell us the values of the
various attributes of our person. We explicitly itemize the possible attributes, so we have a fairly firm definition of what the type of a person is.

Interesting. The size of these two bits of code is more or less the same, but the class-based version is full of special forms. Special Forms are essentially magic provided by the language or runtime. To understand this code, you need to know:

what class means

that calling new on the class’s name calls the initialize methods

what methods are

that prepending @ to a variable makes it private to the class’ instance

the difference between a class and an instance

what attr_reader does

Compared to our functional version, all you need to know is:

how to define a function

how to invoke a function

Like I said, I find this interesting. We have two ways of writing essentially the same code, and one way requires you to have a lot more special knowledge than the other.

OK, now that we have a real data structure, let’s rework our code to use it, instead of arrays:

123456789101112131415161718192021222324252627282930313233343536

read_person_from_user=->{puts"Name?"name=gets.chompputs"Birthdate?"birthdate=gets.chompputs"Gender?"gender=gets.chompputs"Title?"title=gets.chompnew_person.(name,birthdate,gender,title)}add_person=->(person){return[nil,"Name is required"]ifString(person.(:name))==''return[nil,"Birthdate is required"]ifString(person.(:birthdate))==''return[nil,"Gender is required"]ifString(person.(:gender))==''return[nil,"Gender must be 'male' or 'female'"]ifperson.(:gender)!='male'&&person.(:gender)!='female'id=insert_person.(person.(:name),person.(:birthdate),person.(:gender),person.(:title))[new_person.(person.(:name),person.(:birthdate),person.(:gender),person.(:title),id),nil]}get_new_person=->{handle_result.(add_person.(read_person_from_user.()),->(person){puts"Successfully added person #{person.(:id)}"person},->(error_message){puts"Problem: #{error_message}"get_new_person.()})}

add_person is a bit noisier, due to the syntax of getting an attribute, but we can now add new fields very easily and keep things structured.

Object-orientation is just functions

We can also add derived fields. Suppose we want a saluation for the person that uses their title? We can make that an attribute of the person:

We’ve created classes, objects, and inheritance, all with just functions, and in just a few lines of code.

In a sense, an object in an OO language is a set of functions that have access to a shared set of data. It’s not hard to see why adding an object system to a functional
language is considered trivial by those knoweldgable in functional languages. It’s certainly a lot easier than adding functions to an object-oriented language!

Although the syntax for accessing attributes is a bit clunky, I’m not feeling a ton of pain by not having classes. Classes seem almost like syntactic sugar at this point,
rather than some radical concept.

One thing that seems problematic is mutation. Look at how verbose add_person is. It calls insert_person to put our person into the database, and
gets an ID back. We then have to create an entirely new person just to set the ID. In classic OO, we’d just do person.id = id.

Is mutable state what’s nice about this construct? I’d argue that its compactness is what’s nice, and the fact that this compactness is implemented via mutable state is just
incidental. Unless we are in a severely memory-starved environment, with terrible garbage collection, we aren’t going to be concerned about making new objects. We are going
to be annoyed by the needless repetition of building new objects from scratch. Since we already know how to add functions to our, er, function, let’s add one to bring back
this compact syntax.

add_person=->(person){return[nil,"Name is required"]ifString(person.(:name))==''return[nil,"Birthdate is required"]ifString(person.(:birthdate))==''return[nil,"Gender is required"]ifString(person.(:gender))==''return[nil,"Gender must be 'male' or 'female'"]ifperson.(:gender)!='male'&&person.(:gender)!='female'id=insert_person.(person.(:name),person.(:birthdate),person.(:gender),person.(:title))[person.(:with_id,id),nil]# <====}

It’s not quite as clean as person.id = id, but it’s terse enough that it’s still readable, and the code is better for it.

Namespaces are just functions

What I’m really missing is namespaces. If you’ve done any C programming, you know that your code becomes littered with functions that have complex prefixes to avoid
name-clashes. We could certainly do that here, but it would be nice to have proper namespacing, like we get via modules in Ruby or object literals in JavaScript.
We’d like to add this without adding a feature to our language. The simplest way to do that is to implement some sort of map. We can already get explicit attributes
of a data structure, so we just need a more generic way to do so.

Currently, the only data structure we have is an array, and we don’t have methods, since we don’t have classes. The arrays we have are really tuples, and the only general
operations we have are the ability to extract data from them. For example:

12

first=->((f,*rest)){f}# or should I name this car? :)rest=->((f,*rest)){rest}

We can model a map as a list, by treating it as a list with three entires: the key, the value, and the rest of the map. Let’s avoid the “OO style” of making “methods” and
just keep it pureful functional:

people=add.(empty_map,:insert,insert_person)people=add.(people,:update,update_person)people=add.(people,:delete,delete_person)people=add.(people,:fetch,fetch_person)people=add.(people,:new,new_person)add_person=->(person){return[nil,"Name is required"]ifString(person.(:name))==''return[nil,"Birthdate is required"]ifString(person.(:birthdate))==''return[nil,"Gender is required"]ifString(person.(:gender))==''return[nil,"Gender must be 'male' or 'female'"]ifperson.(:gender)!='male'&&person.(:gender)!='female'id=get(people,:insert).(person.(:name),person.(:birthdate),person.(:gender),person.(:title))[get(people,:new).(:with_id,id),nil]}

We could certainly replace our new_person implementation with a map, but it’s nice to have an explicit list of attributes that we support, so we’ll leave new_person as-is.

One last bit of magic. include is a nice feature of Ruby; it lets us bring modules into scope to avoid using the namespace. Can we do that here? We can get close:

1234567891011121314151617181920

include_namespace=->(namespace,code){code.(->(key){get(namespace,key)})}add_person=->(person){return[nil,"Name is required"]ifString(person.(:name))==''return[nil,"Birthdate is required"]ifString(person.(:birthdate))==''return[nil,"Gender is required"]ifString(person.(:gender))==''return[nil,"Gender must be 'male' or 'female'"]ifperson.(:gender)!='male'&&person.(:gender)!='female'include_namespace(people,->(_){id=_(:insert).(person.(:name),person.(:birthdate),person.(:gender),person.(:title))[_(:new).(:with_id,id),nil]}}

OK, this might be over the top, but it’s fairly interesting to think of something like include as just a way to “type less stuff”, and that we can achieve a similar
reduction in “typing stuff” by just using functions.

What have we learned?

With just a few basic language constructs, we can create a fairly usable programming language. We can create bona-fide types, namespaces, and even
do object-oriented programming, without any explicit support for these features. And we can do so in more or less the same amount of code that would be required
by using Ruby’s built-in support. The syntax is slightly verbose compared to the full-blown Ruby equivalent, but it’s not
that bad. We could write real code using this degenerate form of Ruby, and it wouldn’t be too bad.

Does this help us in our everyday work? I think this is a lesson in simplicity. Ruby is fraught with DSLs, abused syntax, and meta-programming, yet we’ve just
been able to accomplish a lot without even using classes! Perhaps the problem you have in front of you can be solved by something simple? Perhaps you don’t
need anything fancy, but can rely on the more straightforward parts of your language.

About Me

I'm a programmer, musician, and author. I speak frequently at national and regional conferences and spend my days currently as a lead engineer at Stitch Fix. I've written applications in C, C++, Perl, Ruby, Scala, and many others, on large and small teams. As a developer, I believe in clean code, making it right, providing a great user experience and using the right tool for the job. As a bass player, I believe in using a pick, locking it down, and ripping off Peter Hook. As an author, I insist on the Oxford Comma, try to avoid semi-colons, and dislike title case.