This is a little story about how dumb I am and my modest attempts to become less dumb.
A while back I was interviewing for a job, and on my resume I stated I have experience with Scheme. I do - believe it or not there are loan origination systems written in Scheme.
The interviewer threw me a bone to see if I really did know scheme, and in general, functional programming.
“So, can you tell me what currying is?”
I couldn’t produce a good answer. The inteviewer was a big fan of functional programming and he could see from a mile away that I didn’t really know anything about it. Needless to say, I didn’t get the job.
I knew currying was a thing that had to do with arguments to a function in a functional programming language but I couldn’t put in to words what it really was. I remember I had to answer this question on a test back in college but all the alcohol seems to have wiped my memory from that time.
Learning Functional Programming
Recently I’ve been learning F# and the subject of currying came back up, so I’m writing out here about currying, in case I have to answer it in another interview. Hey, it’s come up twice already!
If you’re looking for a better explanation I reccomend the Currying article over a F# For Fun And Profit. I’m using code examples from that site.
In general, currying is a technique that if you pass less arguments to a function than the function needs, the program will still compile, and instead of a value being returned from that function, you’ll get a function that only requires the remaining parameters. This is valuable in a functional programming context (or so they tell me, I haven’t done any real-world functional programming apart from gluing some things together in Scheme).
At its core, Currying happens because functional programs only have one parameter passed into a function. This is how LISP (and Scheme) works as processing lists as purely “the first thing” (car) and “the rest of the things” (cdr). This is also how lists in F# work (like in LISP, a list is basically a singly-linked list).
So how come in F# functions can be declared with more than one parameter? The first part of the answer is because F# isn’t a ‘True’ functional programming languge. I’m sure there are nerds who think that because of this, F# is no good. I think of this property of F# being ‘functional’ but not ‘truly functional’ as being more pragmatic and versatile (reminder that I haven’t actually done anything useful with F# yet so this is a baseless opinion).
The second more technical answer is that programs are compiled down into one-argument functions. The Simple example from F# for fun and profit demonstrates it best.
//the developer writes this code: let printTwoParameters x y = printfn "x=%i y=%i" x y
//the compiler compiles into (something like) this: let printTwoParameters x = // only one parameter! let subFunction y = printfn "x=%i y=%i" x y // new function with one param subFunction // return the subfunction
F# uses scoping to handle the issue of multiple parameters in a function.
This isn’t just a compiler method but highly useful for programmers. If you have a function that takes two parameters, you can pass only one into it. What is returned in this case? You get back a brand new function that is awaiting the second parameter.
With the strong type system in F# this allows for composable and stable programming.
// call that function with one parameter: printTwoParameters 1
// and f# returns a function! val it : (int -> unit) = <fun:printTwoParameters@286-3>
Obviously this scales out to more than two parameters and F# handles the edge cases with compile-time errors.
I’ll end this post with a quote from a very wise person I once worked with:
“Always make your programs fail at compile time, not run time”.