They are one of those language features that, having learned them, it's a little hard to flip my brain around into the world I knew before I learned them.
If I think hard, I can sort of remember how I used to do things before I worked almost exclusively in languages that natively support closures ("Let's see... I create a state object, and it copies or retains reference to all the relevant variables... and for convenience I put my function pointer in there too usually... But I still need rules for disposing the state when I'm done with it..." It's so much nicer when the language handles all of that bookkeeping for you and auto-generates those state constructs).
Curiously, higher-order functions, and the concept of something like a closure, dates back to the earliest days of PL design - and I'm not even talking about Lisp! Algol-60, the granddaddy of pretty much every modern mainstream programming language, already had the notion of nested functions (which closed over variables from the surrounding scopes) and the ability to pass those functions to other functions.
They weren't fully first-class because there were no function-typed variables, nor could you return a function. Even so, this already lets you do stuff like map and filter. And Algol-60 programs from that era did use those capabilities, e.g.:
PROCEDURE EULER (FCT, SUM, EPS, TIM)
VALUE EPS, TIM;
INTEGER TIM;
REAL PROCEDURE FCT;
REAL SUM, EPS;
BEGIN
INTEGER I, K, N, T;
ARRAY M [0 .. 15];
REAL MN, MP, DS;
I := N := T := 0;
M[0] := FCT(0);
SUM := M[0] / 2;
NEXTTERM:
I := I+1;
MN := FCT(1);
FOR K := 0 STEP 1 UNTIL N DO
BEGIN
MP := (MN + M[K]) / 2;
M[K] := MN;
MN := MP
END;
IF (ABS(MN) < ABS(M[N]) AND N < 15) THEN
BEGIN
DS := MN/2;
N := N+1;
M[N] := MN
END
ELSE
DS := MN;
SUM := SUM + DS;
IF ABS(DS) < EPS THEN
T := T + 1
ELSE
T := 0;
IF T < TIM THEN
GOTO NEXTTERM
END;
If I think hard, I can sort of remember how I used to do things before I worked almost exclusively in languages that natively support closures ("Let's see... I create a state object, and it copies or retains reference to all the relevant variables... and for convenience I put my function pointer in there too usually... But I still need rules for disposing the state when I'm done with it..." It's so much nicer when the language handles all of that bookkeeping for you and auto-generates those state constructs).