Instantly share code, notes, and snippets.

Embed
What would you like to do?
The distinction between anonymous functions and lambdas in JavaScript.

TL;DR - Lambda means "function used as data".

Anonymous function means "function without a name".

This is one of the relatively few cases where the Wikipedia definition of a word, while not entirely wrong, is misleading. Lambdas and anonymous functions are distinct ideas.

These ideas are commonly confused because in many programming languages (and lambda calculus) all lambdas are anonymous or vise verse.

In JavaScript, not all lambdas are anonymous, and not all anonymous functions are lambdas, so the distinction has some practical meaning.

(function () {
  console.log(`
  Some people mistakenly think that "lambda" and "anonymous function" have
  the same meaning. Let's clear that up.

  In computer science, the most important, defining characteristic of a lambda
  expression is that it is used as data. That is, the function is passed as
  an argument to another function, returned as a value from a function, or
  assigned to variables or data structures.

  This is basically the definition of a first class function. In JavaScript, you
  can use any function as a lambda expression because functions are first class.

  However, that does not mean that all JavaScript functions are therefore lambda
  expressions. For instance, this expression defines a function which gets
  immediately invoked and then dropped on the floor rather than passed,
  exported, or assigned. In other words, the function is not used as data.
  Instead, it's used for a side-effect (logging this text to the console).

  Conceptually, this is more akin to imperative programming than functional
  programming, and thinking of this function as a lambda would add zero useful
  meaning to your understanding of it.

  This distinction is not essential, but is a useful concept when you're
  learning functional programming. In other words, if you understand this
  distinction, you have a deeper understanding of what the word "lambda" means
  in both functional programming and lambda calculus (which are closely
  related).

  It is possible to use functional language features like first-class functions
  in an imperative style, but that adds nothing interesting to your grasp of the
  language, or your grasp of why lambda expressions exist in the first place.
  `)
})();

$('#el').on('click', function clickHandler () {
  console.log(`
  This is an example of a lambda expression that is not anonymous. As you can
  see, it clearly has a name, clickHandler, which can be used inside the
  function for the purpose of recursion (also an important concept in functional
  programming).

  It is a lambda expression because of the semantic use -- it's being passed
  to another function as data. The .on() function is using the function as
  an argument -- in other words, communicated as a message (i.e. functions as
  data).
  `);
});

Looks like some people are still confused, because you've accepted "lambda = anonymous" as gospel. While it is a somewhat useful concept to understand that anonymous functions have interesting uses, such as points-free-style (tacit programming), that is not the salient point of lambdas. It's mostly syntactical sugar.

I am aware that hundreds of references refer to lambdas and anonymous functions interchangeably, and that lots of references list "anonymous function" as the definition of "lambda".

I'm saying they're wrong, and the distinction matters in JavaScript in order to avoid confusion when you learn functional programming concepts.

It is functions used as data which is the true salient, defining feature of lambdas, not anonymity.

For example, you can have all the same benefits of anonymous functions even when those functions have names, simply by ignoring the names.

However, there are benefits to named lambdas that you can't enjoy without the names, such as enhanced debugging visibility.

The point here is that whether a function has a name or not is not particularly important compared to whether or not the function is used as data. JavaScript supports named and unnamed lambdas, and it's useful to understand that a named function can be anonymous. If you don't consider a named function to be a lambda, you're missing the point of lambdas.

bar is a lambda, but not anonymous:

const foo = [1,2,3];
const baz = foo.map(function bar (n) { return n + 1; });

This anonymous function is not a lambda:

// Just evaluated and dropped on the floor. Not used as data.

// Not a lambda.

(msg) => {

  const formattedMsg = JSON.stringify({
    time: Date.now(),
    msg
  });
  console.log(formattedMsg)
  
}('foo');

`

@dfkaye

This comment has been minimized.

Show comment
Hide comment
@dfkaye

dfkaye May 19, 2015

I was running this by copy+paste in the console to see the template string output, but w/o including jQuery.

To do that successfully, here's a quick-and-dirty $ shim:

var $ = function $() { return { on: $} };

And this line

$('#el').on(click, function clickHandler () {

Should be changed to

$('#el').on('click', function clickHandler () { // add quotes around 'click'

Then it works 😄

dfkaye commented May 19, 2015

I was running this by copy+paste in the console to see the template string output, but w/o including jQuery.

To do that successfully, here's a quick-and-dirty $ shim:

var $ = function $() { return { on: $} };

And this line

$('#el').on(click, function clickHandler () {

Should be changed to

$('#el').on('click', function clickHandler () { // add quotes around 'click'

Then it works 😄

@ericelliott

This comment has been minimized.

Show comment
Hide comment
@ericelliott
Owner

ericelliott commented May 19, 2015

Fixed.

@kbariotis

This comment has been minimized.

Show comment
Hide comment
@kbariotis

kbariotis Aug 14, 2015

And if we had omitted the clickHandler function's name and instead left it anonymous. What would that be? (As bad practice as that is)

kbariotis commented Aug 14, 2015

And if we had omitted the clickHandler function's name and instead left it anonymous. What would that be? (As bad practice as that is)

@oieduardorabelo

This comment has been minimized.

Show comment
Hide comment
@oieduardorabelo

oieduardorabelo Aug 15, 2015

@kbariotis still be an lambda

Lambda means "function used as data".

if the function is named or not, "doesn't matter" (we can explain why named function is good, debugging and recursion, but, you know what I mean)

oieduardorabelo commented Aug 15, 2015

@kbariotis still be an lambda

Lambda means "function used as data".

if the function is named or not, "doesn't matter" (we can explain why named function is good, debugging and recursion, but, you know what I mean)

@fiskr

This comment has been minimized.

Show comment
Hide comment
@fiskr

fiskr Aug 18, 2015

I'm uncertain of what you mean by "lambda" here.
When you posted this on twitter, you received a comment like:

Brutallo: @_ericelliott Strictly speaking, in lambda calculus functions are always anonymous.

To which you replied:

Eric Elliott: @Brutallo JavaScript isn't lambda calculus. ;)

So then what do you mean by lambda?
I know Python has a special keyword for lambda, as does Scheme.
But I'm not familiar with anything like that for Javascript, the closest might be the function keyword.
Essentially, what could you mean by lamdba here other than in the context of lambda calculus?

If you really are making a distinction between anonymous functions in javascript and lambdas like Scheme might use, then I'm further confused by your distinction.

If you read 1.3.2, when lambda is introduced in SICP, it sure seems that lambda is being used to make anonymous functions.

In fact, if your read about anonymous functions, you find quotes like:

In several programming languages, anonymous functions are introduced using the keyword lambda, and anonymous functions are often referred to as lambdas or lambda abstractions.

Is the distinction you are making really something more along the lines of "lambda is a functional programming paradigm, and when you use a lambda in an imperative way, it's not useful to think of it as a lambda anymore"?

Unfortunately, just because it's not useful to think of an anonymous function as a lambda doesn't make it not a lambda. This leaves me in knots trying to understand your distinction.

Back to SICP, would the following be an example of "imperative" use of a lambda?
(lambda (x) (/ 1.0 (* x (+ x 2))))
The above code is also "immediately invoked and then dropped on the floor rather than passed,
exported, or assigned" - but it is still a lambda no?

So what distinction are you really making?

What specifically can I read to understand this distinction, and what are your sources?

Don't confuse my challenge as an attack - I think this is fun stuff, and you more than likely know what you're talking about - that just means I need some help to catch up. Help me out. 😃

fiskr commented Aug 18, 2015

I'm uncertain of what you mean by "lambda" here.
When you posted this on twitter, you received a comment like:

Brutallo: @_ericelliott Strictly speaking, in lambda calculus functions are always anonymous.

To which you replied:

Eric Elliott: @Brutallo JavaScript isn't lambda calculus. ;)

So then what do you mean by lambda?
I know Python has a special keyword for lambda, as does Scheme.
But I'm not familiar with anything like that for Javascript, the closest might be the function keyword.
Essentially, what could you mean by lamdba here other than in the context of lambda calculus?

If you really are making a distinction between anonymous functions in javascript and lambdas like Scheme might use, then I'm further confused by your distinction.

If you read 1.3.2, when lambda is introduced in SICP, it sure seems that lambda is being used to make anonymous functions.

In fact, if your read about anonymous functions, you find quotes like:

In several programming languages, anonymous functions are introduced using the keyword lambda, and anonymous functions are often referred to as lambdas or lambda abstractions.

Is the distinction you are making really something more along the lines of "lambda is a functional programming paradigm, and when you use a lambda in an imperative way, it's not useful to think of it as a lambda anymore"?

Unfortunately, just because it's not useful to think of an anonymous function as a lambda doesn't make it not a lambda. This leaves me in knots trying to understand your distinction.

Back to SICP, would the following be an example of "imperative" use of a lambda?
(lambda (x) (/ 1.0 (* x (+ x 2))))
The above code is also "immediately invoked and then dropped on the floor rather than passed,
exported, or assigned" - but it is still a lambda no?

So what distinction are you really making?

What specifically can I read to understand this distinction, and what are your sources?

Don't confuse my challenge as an attack - I think this is fun stuff, and you more than likely know what you're talking about - that just means I need some help to catch up. Help me out. 😃

@Apromixately

This comment has been minimized.

Show comment
Hide comment
@Apromixately

Apromixately Aug 12, 2016

If you hit somebody with a broom it doesn't suddenly become a bat.

Apromixately commented Aug 12, 2016

If you hit somebody with a broom it doesn't suddenly become a bat.

@battlmonstr

This comment has been minimized.

Show comment
Hide comment
@battlmonstr

battlmonstr Aug 21, 2016

Interesting point, but it is biased to JavaScript. JavaScript can't be a model language for that Wikipedia article. When lambda functions are available in most languages you can find diverse examples of what is called a lambda function and deduce the meaning.
Consider this:

  1. In most programming languages if a function is anonymous it can't be called, unless it's assigned or passed as an argument (used as data). The JavaScript idiom of defining a function to be called once and dropped is an esoteric way to deal with scopes. It started mainly as a hack to cope with problems of not having block-scope local variables, and not having safe isolated namespaces (defining a named function XYZ in the global scope accidentally overrides window.XYZ).
  2. "Function used as data" is a required attribute, but not sufficient to qualify as a lambda function. With that definition function pointers and callbacks are also lambdas, but they aren't. Other important attributes are:
    • a function that is defined in place where it's used
    • a function that is defined using a shorthand arrow notation. Most languages have arrow notations these days, but those which didn't (like PHP 5 or JS ES 5) could call their anonymous function syntax "lambda functions" with a stretch.

Examples:

    function next(n) { return n + 1 }
    [1,2,3].map(next)
        // not a lambda function, although used as data

    [1,2,3].map(function (n) { return n + 1 })
        // anonymous function, but not a lambda function
        // (can call it a lambda function in loosely terms)

    [1,2,3].map(n => n + 1)
         // true lambda function expression

battlmonstr commented Aug 21, 2016

Interesting point, but it is biased to JavaScript. JavaScript can't be a model language for that Wikipedia article. When lambda functions are available in most languages you can find diverse examples of what is called a lambda function and deduce the meaning.
Consider this:

  1. In most programming languages if a function is anonymous it can't be called, unless it's assigned or passed as an argument (used as data). The JavaScript idiom of defining a function to be called once and dropped is an esoteric way to deal with scopes. It started mainly as a hack to cope with problems of not having block-scope local variables, and not having safe isolated namespaces (defining a named function XYZ in the global scope accidentally overrides window.XYZ).
  2. "Function used as data" is a required attribute, but not sufficient to qualify as a lambda function. With that definition function pointers and callbacks are also lambdas, but they aren't. Other important attributes are:
    • a function that is defined in place where it's used
    • a function that is defined using a shorthand arrow notation. Most languages have arrow notations these days, but those which didn't (like PHP 5 or JS ES 5) could call their anonymous function syntax "lambda functions" with a stretch.

Examples:

    function next(n) { return n + 1 }
    [1,2,3].map(next)
        // not a lambda function, although used as data

    [1,2,3].map(function (n) { return n + 1 })
        // anonymous function, but not a lambda function
        // (can call it a lambda function in loosely terms)

    [1,2,3].map(n => n + 1)
         // true lambda function expression
@ergose

This comment has been minimized.

Show comment
Hide comment
@ergose

ergose Sep 5, 2016

I am in disagreement that a function is still a lambda once one names the function.

It sounds like, in lamda calculus, the functions are all anonymous and, I'm assuming, are called lambdas in discussion.
At some point in time the term pollinated into JavaScript discussions to describe functions that were anonymous.
Ultimately, I'm of the stance that the term lambda, is merely a synonymous term for an anonymous function.

Where that description is misleading, however, is when practically applied, anonymous functions tend to be passed as data in JavaScript.
When learning about lambdas in the context of lambda calculus there is no conflict. It sounds like it is strictly a term for the functions.
When learning in the context of JavaScript, to say that a lambda is strictly an anonymous function is still technically correct,
but it looses real world meaning when one considers how it's actually used, the majority of the time, in a JS discussion...
Usually it is assumed that one is using the term lambda to not, literally mean just an anonymous function, but one that is being
used as data (since that's often how the lambda/anonymous function is used in an applied JavaScript context.)

If I were describing a lambda to someone in a JS discussion that was new to the concept then I would describe it as,
"an anonymous function, often used as data, and to return data, for an invoking function." I feel it would convey the clearest meaning
without diving into examples or being too general.

Borrowing from battlmonstr and the author, here's what I do and don't consider lambdas:

const foo = [1,2,3];
const baz = foo.map(function bar (n) { return n + 1; });
    // I would not call this a lambda function because it is named.
    // The term I would use in discussion would be a Named Function.
    // ex: "We are passing the Named Function bar into foo.map"

function next(n) { return n + 1 }
[1,2,3].map(next)
    // I would not call this a lambda function because it is named.
    // The term I would use is a Callback in discussion.

[1,2,3].map(function (n) { return n + 1});
    // I would call this a lambda function because it is an anonymous function, 
    // used as data, and returns data, for an invoking function.
    // I would say that I was "passing a lambda to dot map."

[1,2,3].map( n => n + 1 );
    // I would also call this a lambda for the same reason.
    // I would say the same as above.

I consider the last two functions as completely equal, neither being more true, because:
"[1,2,3].map( n => n + 1 );" transpiles directly to "[1,2,3].map(function (n) { return n + 1});" with TypeScript (I'm pretty sure it's
the same with Babel.)

I've really enjoyed reading and thinking about this. :) Kudos.

ergose commented Sep 5, 2016

I am in disagreement that a function is still a lambda once one names the function.

It sounds like, in lamda calculus, the functions are all anonymous and, I'm assuming, are called lambdas in discussion.
At some point in time the term pollinated into JavaScript discussions to describe functions that were anonymous.
Ultimately, I'm of the stance that the term lambda, is merely a synonymous term for an anonymous function.

Where that description is misleading, however, is when practically applied, anonymous functions tend to be passed as data in JavaScript.
When learning about lambdas in the context of lambda calculus there is no conflict. It sounds like it is strictly a term for the functions.
When learning in the context of JavaScript, to say that a lambda is strictly an anonymous function is still technically correct,
but it looses real world meaning when one considers how it's actually used, the majority of the time, in a JS discussion...
Usually it is assumed that one is using the term lambda to not, literally mean just an anonymous function, but one that is being
used as data (since that's often how the lambda/anonymous function is used in an applied JavaScript context.)

If I were describing a lambda to someone in a JS discussion that was new to the concept then I would describe it as,
"an anonymous function, often used as data, and to return data, for an invoking function." I feel it would convey the clearest meaning
without diving into examples or being too general.

Borrowing from battlmonstr and the author, here's what I do and don't consider lambdas:

const foo = [1,2,3];
const baz = foo.map(function bar (n) { return n + 1; });
    // I would not call this a lambda function because it is named.
    // The term I would use in discussion would be a Named Function.
    // ex: "We are passing the Named Function bar into foo.map"

function next(n) { return n + 1 }
[1,2,3].map(next)
    // I would not call this a lambda function because it is named.
    // The term I would use is a Callback in discussion.

[1,2,3].map(function (n) { return n + 1});
    // I would call this a lambda function because it is an anonymous function, 
    // used as data, and returns data, for an invoking function.
    // I would say that I was "passing a lambda to dot map."

[1,2,3].map( n => n + 1 );
    // I would also call this a lambda for the same reason.
    // I would say the same as above.

I consider the last two functions as completely equal, neither being more true, because:
"[1,2,3].map( n => n + 1 );" transpiles directly to "[1,2,3].map(function (n) { return n + 1});" with TypeScript (I'm pretty sure it's
the same with Babel.)

I've really enjoyed reading and thinking about this. :) Kudos.

@amandeepmittal

This comment has been minimized.

Show comment
Hide comment
@amandeepmittal

amandeepmittal Nov 12, 2016

Is this an example of Lambda function or anonymous function?

var functionName = function(a,b,c){};

In the above example a function is created and assigned a name: functionName

amandeepmittal commented Nov 12, 2016

Is this an example of Lambda function or anonymous function?

var functionName = function(a,b,c){};

In the above example a function is created and assigned a name: functionName

@Madeyedexter

This comment has been minimized.

Show comment
Hide comment
@Madeyedexter

Madeyedexter Nov 22, 2016

This article definitely clears the mist around lambdas and anonymous functions. Thank you.

Madeyedexter commented Nov 22, 2016

This article definitely clears the mist around lambdas and anonymous functions. Thank you.

@fromSpace

This comment has been minimized.

Show comment
Hide comment
@fromSpace

fromSpace Jan 20, 2017

The function "Passed as data" is still anonymous to the receiving function, it will be evaluated regardless of it's name. Keeping a reference to that function via the lexical scope makes it more difficult to troubleshoot / test unless you knew something about the function before it was passed to you. If I start passing functions that take advantage of the "private" closure around it to access itself, there is magic behind the scenes that may cause hard to track errors. It is best to reference the function by the argument name in the recieving function, you will be able to do recursion there if required. I do not believe passing as anonymous without a name limits the ability to unit test the function, the function you have access to from within the closure and the recieving function would not share the same execution thread, and though you can use it for recursion, there is a performance cost with that type of recursion because you never return from the previous function when it calls itself. This type of recursion absolutely does cause multiple execution threads to be opened simultaniously, but provides the added benefit of asynchronicity. I recommend registering your evented action type as a string in queue somewhere, then processing your que item from the event handler, if required, you could pass a string query to the event. The reason I pass the definition and register as a string is because a reference will not be maintained within the closure of the function that you want to completely die at next GC, and you will be able maintain the same asynchronous recursion, without the overhead. Essentially, you can have an asynchrounous method called consistently over 5 hours and the memory peak when watching the profiler in chrome will always be the same height. If you are using the type of recursion you had mentioned in this post, you essentially have a memory leak.

fromSpace commented Jan 20, 2017

The function "Passed as data" is still anonymous to the receiving function, it will be evaluated regardless of it's name. Keeping a reference to that function via the lexical scope makes it more difficult to troubleshoot / test unless you knew something about the function before it was passed to you. If I start passing functions that take advantage of the "private" closure around it to access itself, there is magic behind the scenes that may cause hard to track errors. It is best to reference the function by the argument name in the recieving function, you will be able to do recursion there if required. I do not believe passing as anonymous without a name limits the ability to unit test the function, the function you have access to from within the closure and the recieving function would not share the same execution thread, and though you can use it for recursion, there is a performance cost with that type of recursion because you never return from the previous function when it calls itself. This type of recursion absolutely does cause multiple execution threads to be opened simultaniously, but provides the added benefit of asynchronicity. I recommend registering your evented action type as a string in queue somewhere, then processing your que item from the event handler, if required, you could pass a string query to the event. The reason I pass the definition and register as a string is because a reference will not be maintained within the closure of the function that you want to completely die at next GC, and you will be able maintain the same asynchronous recursion, without the overhead. Essentially, you can have an asynchrounous method called consistently over 5 hours and the memory peak when watching the profiler in chrome will always be the same height. If you are using the type of recursion you had mentioned in this post, you essentially have a memory leak.

@absorr

This comment has been minimized.

Show comment
Hide comment
@absorr

absorr Apr 21, 2017

"Gospel" means "good news" which doesn't make sense in the context you've used it in

absorr commented Apr 21, 2017

"Gospel" means "good news" which doesn't make sense in the context you've used it in

@steveknoblock

This comment has been minimized.

Show comment
Hide comment
@steveknoblock

steveknoblock May 3, 2017

In some places a bicycle turns into a motorcycle above a certain speed, if it has a motor, even when powered by pedaling

steveknoblock commented May 3, 2017

In some places a bicycle turns into a motorcycle above a certain speed, if it has a motor, even when powered by pedaling

@scamden

This comment has been minimized.

Show comment
Hide comment
@scamden

scamden Jun 7, 2017

in foo.map(function bar (n) { return n + 1; });, i believe bar is actually referred to in javascript as a named anonymous function. it's still anonymous, and no one can call the function by name (including itself recursively). the name is as you said purely for debugging and profiling.

i can see the point that an anonymous function evaluated and "dropped" without being passed as data might not fit the definition of a lambda you're providing, but i do think that all lambdas are still technically "anonymous" in the important sense even if given a name.

scamden commented Jun 7, 2017

in foo.map(function bar (n) { return n + 1; });, i believe bar is actually referred to in javascript as a named anonymous function. it's still anonymous, and no one can call the function by name (including itself recursively). the name is as you said purely for debugging and profiling.

i can see the point that an anonymous function evaluated and "dropped" without being passed as data might not fit the definition of a lambda you're providing, but i do think that all lambdas are still technically "anonymous" in the important sense even if given a name.

@xgqfrms-GitHub

This comment has been minimized.

Show comment
Hide comment
@xgqfrms-GitHub

xgqfrms-GitHub Nov 16, 2017

ES6 Arrow Function === Java 8 Lambda Expression ???

xgqfrms-GitHub commented Nov 16, 2017

ES6 Arrow Function === Java 8 Lambda Expression ???

@zLinz

This comment has been minimized.

Show comment
Hide comment
@zLinz

zLinz Feb 26, 2018

C# the definition of lambda: A lambda expression is an anonymous function that you can use to create delegates or expression tree types. What is the distinction between so many program language?

zLinz commented Feb 26, 2018

C# the definition of lambda: A lambda expression is an anonymous function that you can use to create delegates or expression tree types. What is the distinction between so many program language?

@zfortier

This comment has been minimized.

Show comment
Hide comment
@zfortier

zfortier Apr 29, 2018

@fiskr You beat me by about 2.5 years. SICP 1.3.2:


[...] introducing the special form lambda which can be thought of as "define anonymous"
[...] In general, lambda is used to define procedures in the same way as define, except that no name is specified for the procedure being defined:

(lambda (<formal parameters>)<body>)

The resulting procedure is just as much a procedure as one that is created using define. The only difference is that it has not been associated with any name in the environment.


@ericelliott I don't know. Maybe you are right, and all these other highly credible sources are wrong. I am inclined to believe that when there is broad consensus on the technical definition of some term, then it automatically becomes the correct definition, if only for the sake of uniformity and common understanding (and sanity) in how we communicate ideas. I am going to stick with the definition of "lambda == anonymous function" because that is what I have been lead to believe for a long time. At the same time, I can also accept that JavaScript breaks with that definition in a way that provides some interesting expressive capabilities (but does not appear to provide anything that is unachievable in other languages using more common constructs).

zfortier commented Apr 29, 2018

@fiskr You beat me by about 2.5 years. SICP 1.3.2:


[...] introducing the special form lambda which can be thought of as "define anonymous"
[...] In general, lambda is used to define procedures in the same way as define, except that no name is specified for the procedure being defined:

(lambda (<formal parameters>)<body>)

The resulting procedure is just as much a procedure as one that is created using define. The only difference is that it has not been associated with any name in the environment.


@ericelliott I don't know. Maybe you are right, and all these other highly credible sources are wrong. I am inclined to believe that when there is broad consensus on the technical definition of some term, then it automatically becomes the correct definition, if only for the sake of uniformity and common understanding (and sanity) in how we communicate ideas. I am going to stick with the definition of "lambda == anonymous function" because that is what I have been lead to believe for a long time. At the same time, I can also accept that JavaScript breaks with that definition in a way that provides some interesting expressive capabilities (but does not appear to provide anything that is unachievable in other languages using more common constructs).

@LvChengbin

This comment has been minimized.

Show comment
Hide comment
@LvChengbin

LvChengbin Jul 5, 2018

ES6 arrow function is just syntactic sugar.

LvChengbin commented Jul 5, 2018

ES6 arrow function is just syntactic sugar.

@samsonmaconi

This comment has been minimized.

Show comment
Hide comment
@samsonmaconi

samsonmaconi Aug 6, 2018

Thank you for the article.

samsonmaconi commented Aug 6, 2018

Thank you for the article.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment