Tip:
Highlight text to annotate it
X
This segment of the course is all about first-class functions. And in this first
segment, I just want to give you a little bit of a sense of what that means,
introduce a little bit of a terminology, and actually start by taking a bit of a
step back and asking what is this functional programming stuff that we've
been doing and will continue to do through this segment. So, functional programming
can mean a few different things. To me, it really is about two concepts that are
actually separate. But for historical and somewhat good reasons, they've been
combined together and we call the result functional programming. The first we've
already studied quite a bit and that's avoiding mutation. Not using assignment
statements, not having data that lives in locations that can change. We've done a
lot of that, we're going to continue to do that. And we'll even see cases where we
don't want that, where actually mutable state is a reasonable programming idiom.
And then the second thing, which is what this section of the course is all about,
is using functions as values. Passing them around and that sort of thing, and that'll
give you a sense very soon of what we mean by that. Now, there are a few other things
that people often think of when they think of functional programming and these are
not necessarily bad aspects of the definition of functional programming, if
you will. First of all, functional programming often uses lots of recursion
and recursive data structures like lists and trees and we've seen that in our
section so far. You'll also often see a programming style or even a syntax that's
much more mathematical. the definitions we write down tend to look much more like the
mathematics that we studied in school than other styles of programming tend to. There
is something that some functional programming languages such as Haskell
have, which is laziness. This is actually a technical term. I'm not saying that
anyone is being lazy. We will study laziness briefly later in the course. Many
courses would emphasize it more than we're going to. That's just a matter of
perspective. And then, there's a lot of definitions that make a whole lot less
sense. sometimes people think that oh, if it's not object-oriented programming, or
it's not C, maybe it's functional programming. And that's pretty sloppy
thinking and we'd like to avoid that one. Now, once we know what functional
programming is, then what is a functional language? And I've taken to decide that
this really doesn't make a whole lot of sense as a yes or no question. a
functional language is one in which you can do functional programming. But I think
I can do functional programming, as described here, in pretty much any
language. It just might be more or less convenient. It might be more or less the
default. So, to me, a functional language is just one where functional programming
is the easy, natural, conventional way to do it. All the libraries are generally
written in a functional style, and so on. Alright. So, if this course is not
entirely about functional programming, it's broader than that. But if that's a
big focus and if a big part of functional programming is using functions as values,
it's about time we really got started on that part of the course. So, a first-class
function is, like in ML, like in many programming languages, a situation where
functions can appear and be used wherever we use other values. Wherever you use
numbers or lists or strings or trees, you could also put functions there. So,
functions can be arguments to other functions. They can be results of
functions. They can be a part of a tuple, you combine them to variables. You can put
them in data type constructors and so on. So, we're not going to do a lot of code in
this introductory segment, but I thought I would show you just a little bit of how
this really can be done in ML. And, in fact, not using any features that we
didn't already have, just ones we didn't think to use this way. So, here's two
functions. One doubles its argument. The other increments its argument. That's not
very interesting . But now, let's make a tuple, we're in the
tuple, this is going to be a triple so I'm going to have three parts. What if in the
first part, I put the function double? So, I'm not calling the function, I'm not
passing it an argument, I'm just going to look double up in the environment, get a
function back and put that in the first part of my tupple. Similarly in the second
part, how do I put increment? And just to contrast the difference between a function
and the result of calling the function what if here I put double of increment of
seven. Now, this third position is going to call increment with seven, get back
eight. Call double with that and get sixteen, alright? And then, we could even,
down here at about eighteen, we could get out using our old hash one operator that
we used before we learned pattern matching. Hash one of a tuple, that is
going to give back the double function and then we could call it with nine. So, this
is an example of first-class functions because I'm putting functions in a tuple
and then later, I'm pulling them out and using them. So, let's make sure I got this
all right. And show you what the RPL shows for this. This will be useful to us and
this over here. and sure enough, it says, as we're used to, double is a function of
type int arrow int. Increment is a function of type arrow int arrow int. This
atuple, very interesting. It is a triple, where the first position holds some
function. The RPL never actually prints out functions, other than to write fn. The
second part is fn and the third part is sixteen, just as I promised. And the type
is a triple int arrow int star int arrow int star int. And finally, eighteen, where
we pulled out the double function from the tuple and then called it with nine, did
actually give us eighteen, alright? So, that's a little sense of the sort of thing
we'll be doing. And later in this section, after we learn the semantics and how to
use first-class functions, we'll see useful idioms. The code there was
obviously on purpose, just a little bit silly, okay? So, to finish up, let me just
give you a couple more terms. The most common use of first-class functions is not
putting them in tuples and pulling them out of tuples, although that can be very
useful. The most common is to pass a function as an argument to another
function or as the result of another function. And when you're doing that, the
function that takes or returns other functions is called a higher-order
function. It's just a term. And higher-order functions are a powerful,
powerful idiom for factoring out common computations and we'll see examples in
upcoming segments. One other term we'll get to later in the section is a function
closure. A function closure is a function that uses bindings from outside the
function definition. Now, how can it do that if it's not an argument or a local
variable, how can it use something? The same way we always have in ML. Things that
are already in the environment can be used by a function. Once you have first-class
functions, functions being passed around and returned, the way this environment
interacts with the functions is more sophisticated, more interesting, and much
more powerful. We're going to put that off just a bit and talk about function
closures later. So, to me, first-class functions means functions you can pass
around and put anywhere you want. Function closures means functions that can use
things in the environment, not just arguments and local variables. And these
are technically separate concepts but because functional languages always
support both and they're often used together, use both features together,
these terms are often confused with each other. And even though it's an important
conceptual distinction I'm not going to harp on the definitions and the
terminology because they're so commonly used incorrectly and it's frankly not that
big of a deal. So, that's our introduction. Hopefully you're excited
about the idea of first-class functions and we'll start learning how to use them
for actual interesting code even in the very next segment.