What are first-class functions?

Опубликовано: 15 Май 2026
на канале: Eric Normand
1,426
36

First-class functions are functions that can be treated like any other value. You can pass them to functions as arguments, return them from functions, and save them in variables. In this episode, we talk about why they are important for functional programming and what features we require of them.

►► Audio, Video, and Transcript available: https://lispcast.com/what-are-first-c...

►► Subscribe on iTunes: https://itunes.apple.com/us/podcast/t...


Transcript

Our first-class functions. By the end of this video, you will know what they are, you will know some of the required features that we need for functional programming, and why they are important for functional programming. My name is Eric Normand, and I help people thrive with functional programming.

First-class functions are important because they're a basic requirement for writing higher-level abstractions with functions. You could do it with classes, but that's a different paradigm.

Without them, we wouldn't have tools like map, filter and reduce, and we wouldn't be able to compose functions up into new functions. This is something that is one of the main benefits of functional programming. Not the primary benefit, but I guess you could call it the main secondary benefit.

Let's go over a few points about first-class functions. What does it mean? A first-class function, first-class anything, means that the function can be, if it's first class, it means it can be treated like a value.

Anything you can do to a value such as a number or an array or vector, a list, a string, any of those values, what can you do with them? You can pass them to functions, you can store them in variables, you can return them from functions. All of those things make it first class. It means it has the same status.

Think about second-class citizens, they don't have the same status as the first-class citizens. That's the idea here, that a first-class function has the same status as other values. Functions are just values.

We can do all those things. We can put them in a variable, we can pass them as arguments to other functions, we can return them from other functions. This makes it so that we can manipulate functions like you would manipulate numbers or strings, and things like that.

This means you can start doing what is often called metaprogramming. You're programming your programs. We'll talk a little bit more about that in a minute.

You want your first-class functions to also be what are called closures. That's closure with an s. What this means is that the function can refer to variables in the scope where the function was defined.

You have some variable, let's call it x. In that scope where x is defined, the next line, you define a function, you can refer to x in the body of the function. Even if you return that function from wherever that scope is, that function somehow gets out of the scope. When you call that function, it's still referring to the same x that you had before. That's what it means.

We do this in JavaScript. We probably don't even think about it, but when you define a function inside of another function, it has access to the arguments, to the local variables that are defined there in JavaScript.

For instance, as an example, Java for the longest time did not have closures. You could define an anonymous class that had a method, but that method couldn't refer to variables in the scope where that class was defined. Now it has lambdas, those are closures, and so everything's all right.

Without them, it makes it very difficult. You have to make a lot of leaps and do a lot of gymnastics to get the same functionality. You basically have to build an object -- this is in Java -- you'd have to build an object and assign all of the variables you might need later, all the values you might need later, into that object. It's a lot of ceremony for what should be syntactically very easy.

Another thing is, when you have first-class functions, we were talking about metaprogramming, one thing you want to do is to separate out concerns so that you can reuse part of the concern in another place.

One thing I find in languages that don't allow such abstraction, or where it's not very common at least, is you're writing a lot of low-level code. People call it boilerplate. You're writing for-loops all the time, or where you're repeating yourself over and over. How can you possibly turn that into a first-class operation?