cppreference.com

Lambda expressions (since c++11).

Constructs a closure : an unnamed function object capable of capturing variables in scope.

[ edit ] Syntax

[ edit ] lambda expressions without an explicit template parameter list (possibly non-generic), [ edit ] lambda expressions with an explicit template parameter list (always generic) (since c++20), [ edit ] explanation.

  • If operator ( ) satisfy all constexpr function requirements, operator ( ) will be constexpr even if constexpr is not present.
  • consteval and constexpr cannot be specified at the same time.
  • static and mutable cannot be specified at the same time.
  • Cannot be used if captures is not empty, or an explicit object parameter is present.

A variable __func__ is implicitly defined at the beginning of body , with semantics as described here .

The lambda expression is a prvalue expression of unique unnamed non- union non- aggregate non- structural class type, known as closure type , which is declared (for the purposes of ADL ) in the smallest block scope, class scope, or namespace scope that contains the lambda expression. The closure type has the following members, they cannot be explicitly instantiated , explicitly specialized , or (since C++14) named in a friend declaration :

ClosureType:: operator()( params )

Executes the body of the lambda-expression, when invoked. When accessing a variable, accesses its captured copy (for the entities captured by copy), or the original object (for the entities captured by reference).

The parameter list of operator ( ) is params if it is provided, otherwise the parameter list is empty.

The return type of operator ( ) is the type specified in trailing-type .

Unless the keyword mutable was used in the lambda specifiers , or an explicit object parameter is present (since C++23) , the cv-qualifier of operator ( ) is const and the objects that were captured by copy are non-modifiable from inside this operator ( ) . Explicit const qualifier is not allowed. operator ( ) is never virtual and cannot have the volatile qualifier.

The exception specification exception on the lambda-expression applies to operator ( ) .

For the purpose of name lookup , determining the type and value of the this pointer and for accessing non-static class members, the body of the closure type's operator ( ) is considered in the context of the lambda-expression.

Dangling references

If a non-reference entity is captured by reference, implicitly or explicitly, and operator ( ) of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of objects captured by reference.

Same applies to the lifetime of the current * this object captured via this .

ClosureType:: operator ret (*)( params )()

This user-defined conversion function is only defined if the capture list of the lambda-expression is empty. It is a public, constexpr, (since C++17) non-virtual, non-explicit, const noexcept member function of the closure object.

ClosureType:: ClosureType()

The copy constructor and the move constructor are declared as defaulted and may be implicitly-defined according to the usual rules for copy constructors and move constructors .

ClosureType:: operator=(const ClosureType&)

Closuretype:: ~closuretype().

The destructor is implicitly-declared.

ClosureType:: Captures

If the lambda-expression captures anything by copy (either implicitly with capture clause [=] or explicitly with a capture that does not include the character &, e.g. [a, b, c] ), the closure type includes unnamed non-static data members, declared in unspecified order, that hold copies of all entities that were so captured.

Those data members that correspond to captures without initializers are direct-initialized when the lambda-expression is evaluated. Those that correspond to captures with initializers are initialized as the initializer requires (could be copy- or direct-initialization). If an array is captured, array elements are direct-initialized in increasing index order. The order in which the data members are initialized is the order in which they are declared (which is unspecified).

The type of each data member is the type of the corresponding captured entity, except if the entity has reference type (in that case, references to functions are captured as lvalue references to the referenced functions, and references to objects are captured as copies of the referenced objects).

For the entities that are captured by reference (with the capture-default [&] or when using the character &, e.g. [&a, &b, &c] ), it is unspecified if additional data members are declared in the closure type , but any such additional members must satisfy LiteralType (since C++17) .

[ edit ] Lambda capture

The captures is a comma-separated list of zero or more captures , optionally beginning with the capture-default . The capture list defines the outside variables that are accessible from within the lambda function body. The only capture defaults are

  • & (implicitly capture the used variables with automatic storage duration by reference) and
  • = (implicitly capture the used variables with automatic storage duration by copy).

The current object ( * this ) can be implicitly captured if either capture default is present. If implicitly captured, it is always captured by reference, even if the capture default is = . The implicit capture of * this when the capture default is = is deprecated. (since C++20)

The syntax of an individual capture in captures is

If the capture-default is & , subsequent simple captures must not begin with & .

If the capture-default is = , subsequent simple captures must begin with & or be *this (since C++17) or this (since C++20) .

Any capture may appear only once, and its name must be different from any parameter name:

Only lambda-expressions defined at block scope or in a default member initializer may have a capture-default or captures without initializers. For such lambda-expression, the reaching scope is defined as the set of enclosing scopes up to and including the innermost enclosing function (and its parameters). This includes nested block scopes and the scopes of enclosing lambdas if this lambda is nested.

The identifier in any capture without an initializer (other than the this -capture) is looked up using usual unqualified name lookup in the reaching scope of the lambda. The result of the lookup must be a variable with automatic storage duration declared in the reaching scope , or a structured binding whose corresponding variable satisfies such requirements (since C++20) . The entity is explicitly captured .

If a capture list has a capture-default and does not explicitly capture the enclosing object (as this or * this ), or an automatic variable that is odr-usable in the lambda body , or a structured binding whose corresponding variable has atomic storage duration (since C++20) , it captures the entity implicitly if the entity is named in a potentially-evaluated expression within an expression (including when the implicit this - > is added before a use of non-static class member).

For the purpose of determining implicit captures, typeid is never considered to make its operands unevaluated.

If the body of a lambda odr-uses an entity captured by copy, the member of the closure type is accessed. If it is not odr-using the entity, the access is to the original object:

If a lambda odr-uses a reference that is captured by reference, it is using the object referred-to by the original reference, not the captured reference itself:

Within the body of a lambda with capture default = , the type of any capturable entity is as if it were captured (and thus const-qualification is often added if the lambda is not mutable ), even though the entity is in an unevaluated operand and not captured (e.g. in decltype ):

Any entity captured by a lambda (implicitly or explicitly) is odr-used by the lambda-expression (therefore, implicit capture by a nested lambda triggers implicit capture in the enclosing lambda).

All implicitly-captured variables must be declared within the reaching scope of the lambda.

If a lambda captures the enclosing object (as this or * this ), either the nearest enclosing function must be a non-static member function or the lambda must be in a default member initializer :

If a lambda expression (or a specialization of a generic lambda's function call operator) (since C++14) ODR-uses * this or any variable with automatic storage duration, it must be captured by the lambda expression.

Class members cannot be captured explicitly by a capture without initializer (as mentioned above, only variables are permitted in the capture list):

When a lambda captures a member using implicit by-copy capture, it does not make a copy of that member variable: the use of a member variable m is treated as an expression ( * this ) . m , and * this is always implicitly captured by reference:

Members of anonymous unions members cannot be captured. Bit-fields can only be captured by copy.

If a nested lambda m2 captures something that is also captured by the immediately enclosing lambda m1 , then m2 's capture is transformed as follows:

  • if the enclosing lambda m1 captures by copy, m2 is capturing the non-static member of m1 's closure type, not the original variable or * this ; if m1 is not mutable, the non-static data member is considered to be const-qualified.
  • if the enclosing lambda m1 captures by reference, m2 is capturing the original variable or * this .

[ edit ] Notes

The rule for implicit lambda capture is slightly changed by defect report P0588R1 . As of 2023-10, some major implementations have not completely implemented the DR, and thus the old rule, which detects odr-using , is still used in some cases.

  • odr-used by the body of the lambda.

[ edit ] Example

This example shows how to pass a lambda to a generic algorithm and how objects resulting from a lambda expression can be stored in std::function objects.

Possible output:

[ edit ] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

[ edit ] See also

[ edit ] external links.

  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 3 April 2024, at 15:08.
  • This page has been accessed 4,967,035 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

Lambda Expressions

A guide to programming lambda expressions in C++, C#, Java, Javascript, and Python by JoshData .

A lambda expression is a convenient syntax available in many programming languages for writing short functions. Lambda expressions do for functions what object-oriented programing does for objects: It makes a function something you can assign to a variable.

Lambda expressions are also sometimes called anonymous functions, lambda functions, and closures. The capabilities of lambda expressions differs across programming languages, and some programming languages have multiple ways of writing lambda expressions. The concept originates in philosophy.

Background Concepts

Let’s cover some general programming concepts first.

Statements versus expressions

All programming languages with lambda expressions distinguish statements from expressions :

  • A statement is typically a line of code. Statements control the flow of the program , like if statements, for loops, calling subroutines, and return statements in functions. An assignment to a variable (e.g. x = y ) is also a statement.
  • An expression is code within a statement that computes a value . Expressions are made up of constants, variables, arithmetic operators, function calls, method calls, property accesors, and so on. An expression encodes a set of instructions that results in the computation of one value.

if x > y is a statement. x > y is an expression — it computes one value, in this case either true or false. The if statement takes an action based on the value of the expression.

Statically versus dynamically typed languages

This guide covers a few common programming languages, and if you are reading it to learn about multiple languages it may be helpful to distinguish:

  • Statically typed languages, meaning all variables are defined with a type in source code that is known to the compiler. C, C++, C#, and Java are statically typed languages using types such as int , double , string , etc.
  • Dynamically typed languages, meaning any variable can hold any type of value. Variable declarations with types do not occur in these languages. Python and Javascript are dynamically typed. These languages still have types, usually the same types as in the C-family languages, but they’re only for the values computed in memory, not for variables in source code.

Lambda Syntax

A lambda expression is a function written in a shorthand syntax, and we’ll start by looking at the syntax of lambda expressions.

Here is a regular function (not a lambda function, just a normal function) that adds one to a number as it would be written in C, C++, C#, and Java (they all happen to be identical in this case) and in Javascript. We’ll look at how the same function would be written as a lambda expression.

In this example, there is a single argument x , the expression x + 1 is computed, and that expression is returned to the caller.

It can be written shorter as a lambda expression in modern versions of many languages, including C++ (starting in C++11), C# (starting in C# 9.0), Java (since Java 8), Javascript (starting in ECMAScript 6), and Python (since around Python 2.2):

C#, Java, and Javascript use an arrow symbol (made up of an equal sign or dash plus a greater than sign) to separate the arguments from the expression body. The C# and Javascript syntaxes happen to be identical in this case. (In Javascript, an “anonymous function” refers to a different but related syntactic structure — the technical name for the Javascript syntax discussed here is the “arrow function expression.”)

In the academic discipline of philosophy, the function would be written with the Greek lowercase letter lambda λ denoting the start of a lambda expression:

Here’s a function that returns the maximum value of two numbers, first written as a regular function:

and then as a lambda expression in various languages:

Lambda expressions can also have zero arguments:

Lambda expressions have most of the same components as a normal function:

  • An argument list: Zero or more variables separated with commas, usually in parentheses. C#, Java, and Javascript allow omitting parentheses if there is only one argument. C++ requires the arguments to have types, but the other statically typed languages allow it without making it required.
  • A body: Statements to execute or an expression to evaluate and return. When using statements, they are surrounded with braces, and a return statement can be used to return a value. When the body is just an expression, braces are omitted. (C++ only allows using statements and Python only allows using expressions. In C#, braces can be omitted when the body is a single statement.)

In the body of the lambda expression, some languages allow both statement blocks and expressions (C#), some only support statements (C++), and some only support expressions (Python). The add_one examples above used expressions as lambda function bodies where possible: x + 1 in C#, Python, etc. No braces are used in those languages when the body is an expression:

The max examples above used statement blocks as lambda function bodies, and when statements are used these languages require that they be surrounded in braces:

This last example could be turned into an expression-bodied lambda by using the ternary operator condition ? then : else . Expression bodies are usually easier to read because they are more compact.

The one thing missing from lambda expressions is a function name. Lambda expressions don’t have a place for a name in their syntax.

(No type is given for the return value in any of the examples above either. It is optional in C++ and not permitted in other languages. In statically typed languages, the lambda expression does have a return type but the compiler figures it out from what you return.)

Lambda Expressions are Expressions

The key difference between a regularly defined function and a lambda expression is where they occur in source code. Regular functions are normally defined either at the top-level of your source code file or in a class. All of the statements in your source code are contained within a function.

A lambda expression is exactly the opposite. It occurs not outside of statements but inside statements. It actually is an expression , which means it occurs within statements wherever an expression can be used.

Assigning a lambda expression to a variable

It can be assigned to a variable. Variable assignment normally looks like this of course:

(C++ and C# are a statically typed language so the variable must be declared first with its type, but we will omit the variable declaration for now.)

Now instead of 10 , the variable will be assigned a lambda expression:

The lambda expression is assigned to the variable f . Note that the f = at the start and the semicolon ; at the end belong to the variable assignment statement . The lambda expression appears in the middle as the expression. Since the lambda expression is multiple lines, it pushes the semicolon ; down a few lines to its end.

After the variable assignment, the variable actually holds the lambda function defined by the lambda expression.

Quick look at the type of lambda expressions in the statically typed languages

You can also make a variable declaration with an explicit type, and in C# ≤9 and Java it’s required, even though both have var keywords. The variable types to use in C++, C# and Java are:

  • C++: std::function<double(double, double)> (with #include <functional> )
  • C#: System.Func<double, double, double>
  • Java: java.util.function.BinaryOperator<Double>

For example, in Java:

We’ll come back to the type of lambda expressions later.

No type is needed in dynamically typed languages like Javascript and Python.

Few meaningful operators are defined for lambda expressions

Lambda expressions are expressions, but most operators don’t have any meaning with the value that a lambda expression computes. You can’t add two lambda functions together with + : It doesn’t make sense and that isn’t defined in any language.

The first operator that can be used with lambda expressions are grouping parentheses. Lambda expressions can always be wrapped in parentheses for clarity:

Be sure you see where the open and closing parens were added here.

Calling Lambda Expressions

The most important operator that works with lambda functions is the call operator. The next example starts with the same variable assignment as above, but it follows with a new statement that invokes the lambda function by calling it:

It is just like calling a function, but instead of f being the name of a function it is the name of a variable holding a lambda function.

When f(10, 20) is called, control flow moves to the lambda expression. The statements of the lambda expression are evaluated until the return statement is executed. Then control flow moves back the assignment of the value to z .

Assigning a lambda expression to a variable and then, some time later, using the call operator on the variable is the main thing lambda expressions do.

Java does not support the call operator — this is unusual for a language that has lambda expressions. To invoke the lambda function, in this example we use .apply(...) which is the correct method to use with BinaryOperator<Double>. (The method name depends on the runnable interface type that the expression is assigned to.)

In the next toy example, f is first set to a lambda expression that computes the maximum value of two arguments and then later it is set to a different lambda expression that computes the minimum value of two arguments. Although the same code f(10, 20) is called identically after each assignment, f returns a different value each time because it executes the two lambda functions:

Although f(10, 20) appears twice, it computes a different value each time. In the first call to f , control flow goes to the first lambda expression. In the second call to f , control flow goes to the second lambda expression.

In some languages, the call operator (10, 20) can occur after any expresson that evaluates to a lambda function. In C++, Javascript, and Python, it can be right after the lambda expression itself:

Make sure you see where the lambda expression begins and ends and where the call operator begins and ends.

This pattern is commonly seen in Javascript for reasons related to scope and not really about the lambda expression. It isn’t generally useful because you can always write an expression like this without the complex lambda expression syntax.

C# and Java do not allow this.

Passing lambda expressions as arguments to other functions

The last meaningful thing that you can do with lambda expressions is passing the lambda expresson as an argument to a function. In the next set of examples, a new function foo is defined that takes one argument. The program calls foo and passes a lambda expression as the argment.

Here are additional examples using the more complex lambda functions with statement bodies:

When passing lambda expressions with statement bodies in function calls, the triple of symbols brace-paren-semicolon } ); is a common line ending. The close brace belongs to the lambda expression: It is the close-brace that ends the lambda expression’s body. The close parenthesis belongs to the function call: It is the close parethesis at the end of the argument list. The semicolon marks the end of the statement as in all C++, C#, Java, and Javascript statements.

The most common way to use a lambda expression is passing it to another function and then calling it within that function. Here is the same function call example again, plus calling the lambda function within foo :

Finally, we look at a lambda expression with no return value. Lambda expressions without a return value are typically used with statement-block bodies to take an action.

This lambda expression has a void return type in C++, C#, and Java. (Javascript and Python do not support void return types — if there is no return value, the lambda expression returns undefined (Javascript) or None (Python).)

In C++, C#, Java, Javascript, and Python, any regular function name or class method can also be assigned to a variable and passed to a function, like lambda expressions. In the statically typed languages, the variable or function argument must have the right type. But in dynamically typed languages, that’s not an issue and passing around functions can be very natural:

Terminology

In this guide, lambda expression and lambda function mean slightly different things, although I can’t promise that anyone else makes this distinction:

A lambda expression is the code you type to define a short function. It is source code text that goes into the compiler and is recognized with a particular syntax. (In Javascript, technically they are called arrow function expressions/declarations.)

The expression evaluates at run time to a lambda function in memory. In memory during program execution, the f variable in the preceding examples holds a lambda function . It doesn’t hold the source code text that you typed in — that’s been compiled into some other more efficient representation. So it doesn’t hold an expression. Instead it probably holds a pointer to a memory location that has the compiled code.

The difference between a lambda expression and a lambda function is similar to the difference between a class and an instance of the class (an object). A class is a definition of a type of object. At run time, variables whose types are classes don’t hold classes: they hold pointers to objects. Similarly, variables that are assigned lambda expressions in code hold pointers to lambda functions at run time, not lambda expressions. (In fact, in many languages the lambda expression actually compiles to a new instance of a hidden class!)

Standard Library Routines that Use Lambda Functions

The standard library in each programming language has some methods that are convenient to use with lambda expressions.

Across programming languages, lambda functions are commonly used with the language’s standard library sort function to create sort orders for user-defined data types. In C++, a lambda expression can be passed to std::sort for this purpose.

std::sort ’s third argument is a function that compares two items in the list and returns whether the first item should come first. The arguments to the comparison function must be const references.

In this example, a user-defined class is sorted first by its name field and then, when there are any instances with the same name, by its value field.

std::sort will call the lambda function for each pair of elements in the list and will use its return value to sort the elements according to the order that the lambda function defines. The comparison function always looks something like this to achieve a sort order over multiple fields.

The standard library has a handful of functions that take comparison functions like sort does, including min_element / max_element — another common use of lambda functions across languages. This example finds the MyClass instance in a vector with the smallest value .

This is more compact than writing a for loop to iterate over the elements and track which one has the minimum value.

A comparison function can be used to create set and map containers for user-defined data types. (A hash code generator can also be used with unordered_set and unordered_map .)

You can also put lambda functions inside containers:

Across programming languages, lambda functions are commonly used with the language’s container sort functions to create sort orders for user-defined data types. In C#, a lambda expression can be passed to List.Sort(...) for this purpose.

List.Sort() ’s optional argument is a function that compares two items in the list and returns which should be first in the list. The comparison function returns -1 if the first item should come first, 1 if the second item should come first, or 0 if the items can have either order.

List.Sort will call the lambda function for each pair of elements in the list and will use its return value to sort the elements according to the order that the lambda function defines. The comparison function always looks something like this to achieve a sort order over multiple fields. String.CompareTo and Double.CompareTo have the same sematics as the function expected by Sort: They return -1, 0, or 1.

List.ForEach is another helpful method with a lambda expression — it simply runs the function on each element of the list. Here’s how you can print out each item in the list:

You could of course also write a regular foreach loop, but the lambda expression syntax might be clearer or cleaner in some cases.

You can also put lambda functions inside lists:

The extension methods in System.Linq.Enumerable ( reference ) provide other utility methods on collections that are helpful when used with lambda expressions. For example, Count can be used to count the items in a list that pass a test:

Lambda expressions are also commonly used with C# events, such as in System.Windows.Forms applications.

Rather than subscribing methods to event handlers (which are often hooked up by the Visual Studio designer automatically):

A lambda expression could be used instead:

Don’t subscribe to events directly with lambda expressions if the event handler (the lambda function) needs to be unsubscribed from the event later. To do that, you would need to assign the lambda expression to a variable first and then later use the variable to unsubscribe from the event.

System.Threading.Tasks.Task can be used to launch a background task that runs asynchronously on a thread pool and System.Threading.Tasks.Parallel can launch many tasks at once on the thread pool. Lambda expressions are convenient for both.

First, a single background task:

Next, a background task is launched for each item in an array:

The lambda expression is run multiple times, possibly simultaneously, for each item in the array, and the order in which the array elements are seen might be unpredictable. The first argument to ForEach can be any IEnumerable container. Unlike Task.Run which returns immediately, Parallel.ForEach waits until all of the loop iterations complete.

See https://ddc-java-10.github.io/2020/04/28/lambdas-key-functional-interfaces/ for some examples.

Lambda expressions and anonymous functions are used extensively in Javascript, in two ways:

  • When a lambda expression (let’s call it L) is passed as an argument to a function (let’s call it F) and the lambda L is executed by function F immediately, before the function F returns, the call to the lambda L is synchronous . All of the Javascript examples in this guide so far have been synchronous.
  • When the function F stores the lambda L to be called later, so that F can return before L is executed, the call to the lambda L is asynchronous . It often happens after other stored lambda functions are executed, creating a sort of concurrent execution of multiple tasks. An asynchronously executed lambda expression is often called a “callback.”

Asynchronous callbacks are so pervasive in Javascript that I can’t even begin here to provide key examples. The async package and the Promise design concept are the key places to look next.

Across programming languages, lambda functions are commonly used with the language’s list sorting function to create sort orders for user-defined classes for which the language doesn’t provide any built-in ordering. In Python, a lambda expression can be passed to list.sort() and sorted(...) for this purpose.

You might have seen this error when trying to sort user-defined classes:

MyClass , in this example, is not a sortable data type. You could implement the < operator on MyClass to make it sortable, but often the easier solution is to call list.sort with a lambda expression.

list.sort() ’s optional keyword argument key takes a function that takes an item of the list and returns a sortable value to use in place of the item . It can return anything sortable (a number, string, etc.). The items in the list will be sorted according to how their correponding return values from the key function would be sorted amongst each other.

Returning a tuple of sortable values is a convenient way to create a function that sorts on multiple fields. In this example, the user-defined class is sorted first by its name field and then, when there are any instances with the same name, by its value field.

Variable Capture

Besides a lambda expression’s arguments, a lambda expression can also access variables of the outer function that the lambda expression is contained within. This is called capture or closure.

For example:

In the above examples the captured variable is text . You can tell because it is a variable in the lambda expression that is not an argument (in these examples there are no arguments). The variable type is simply a string, but any data type including objects or other lambda functions can be captured:

If the variable holds an object, that object remains valid — it won’t be garbage-collected or destroyed — until the outer function exits and the lambda function is no longer referenced anywhere.

Lambda expressions are typically small, reusable, and self-contained, but capture makes lambda expressions less reusable and not self-contained, so excessive use of capture should be avoided.

How this works varies subtly across languages, and there are three types of variable capture that you need to be aware of.

Capture by Reference

Capture by reference means that the outer variable is shared with the lambda expression.

If the outer variable changes after the lambda expression is defined but before the lambda function is executed , the lambda function will get the updated value:

Conversely, the lambda expression can change the value of the outer variable so that when the lambda function finishes, the outer function sees the updated value:

Here’s a complex case. Can you figure out what will be printed?

In C#, Javascript, and Python, capture is always by reference.

In C++, there is no capture by default. To enable capture by reference, the & symbol can be put in the brackets that start the lambda expression. The brackets are for declaring capture.

When inside non-static methods of a class, the this variable is captured automatically in C#, Java, and Javascript and can be captured by value by adding this to the brackets in C++. That makes all of the current class instance’s fields, properties, methods, etc. available within the lambda expression as well.

In Python and Javascript, the capture rules apply to local function definitions the same as it does to lambda expressions. For example:

In Javascript, use the newer let keyword rather than var to declare variables to avoid for-loop scope mistakes.

Capture by Copy (C++)

Capture by copy means the lambda function gets a copy of the value in the capture variable at the time the lambda expression is defined . It cannot modify the outer variable and does not see changes to the outer variable.

In C++, capture can be either by reference or by copy. Using = in the capture brackets, capture is by copy.

Because a copy is made at the point where the lambda expression is declared, it will not see subsequent changes to the variable:

Variables captured by copy are const inside the lambda expression to prevent confusion about which variable is being edited:

Capture by copy is less prone to coding mistakes than capture by reference so it should be preferred, but it may come at a cost if the variable holds a complex data type that is expensive to copy.

Capture by copy should generally be used when capturing std::shared_ptr or other smart pointers because the copy will ensure the target object is not destroyed before the lambda function finishes. If that’s not a concern, capture by reference may be more efficient.

(In C#, Java, Javascript, and Python capture is always by reference (or by value in Java), so this section on capture by copy does not apply to those languages.)

Caveats and Capture by Value

It can become very difficult to track what captured variables will hold inside lambda expressions when the variable’s value changes, like in some of the examples in the previous section! It is especially hard in some specific cases:

  • When the variable’s value changes between the lambda expression’s definition and its invocation.
  • Capturing for -loop variables and variables within loops because their value may change on every iteration — in fact, they may be considered different variables on each iteration, which may or may not be what you expect.
  • When lambda functions are executed asynchronously, as is often the case in Javascript, because the order of execution is opposite to the source code order and may be unpredictable.

Avoid using capture by reference in these circumstances whenever possible. especially capturing for -loop variables and variables within loops.

Modifying the captured variable either inside or outside the lambda expression is not possible in Java, which requires that captured variables be final or assigned once, so that it only ever has one value. That’s nice! It prevents complex situations that are prone to error. Since the captured variable cannot be changed, capture by reference is probably not the right term: capture by value might be a more appropriate term.

To get around these issues in all of the languages, you can sometimes make the captured variable a container (e.g. a list) and modify what is inside the container. Although the variable should not (or in Java cannot) be assigned a new value, its methods can be called and its fields and properties can be modified freely.

In addition to the captured variable’s value, it is can also be very hard to track its lifetime . Objects stored in captured variables may remain in memory so long as the lambda function remains stored in a variable. The lifetime of captured variables is dependent on the lifetime of the lambda function. If the lambda function is stored in a global variable, for example, any objects in variables captured by the lambda expression may hold onto system resources indefinitely.

Or, worse, those captured objects may become invalid in some way (due to their own semantics), leading to a crash or error the next time the lambda function is called. Lambda functions must be careful that nothing intervenes between definition and execution that would violate expectations the function has about the captured variables.

Capturing loop variables

The type of lambda expressions.

If you are writing your own functions that take lambda functions as arguments in statically typed languages, or if you are using C# ≤9 or Java and want to assign a lambda expression to a variable, you will need to know the correct types to use.

The type for lambda functions in C++ is std::function<return_type(arg_type_1, arg_type_2, ...)> which is defined in the functional standard header.

The template argument return_type(arg_type_1, arg_type_2, ...) is a little unusual, but it makes sense and pretty clearly indicates what’s what.

Three types in C# are generally used with lambda expressions.

System.Action is the usual type for lambda functions that do not return anything (like a void return type function). Without any generic arguments, it is the type for lambda functions that take no arguments and have no return value.

When System.Action has generic arguments, they are the lambda function’s argument types. For example, Action<string> is the type of a lambda function that takes a string and performs an action without returning a value. Action<string,Object> is the type of a lambda function that takes a string and an object as arguments (in that order) and performs an action without returning a value.

System.Func is the usual type for lambda functions that have a return value. The first (zero or more) generic arguments are the argument types. The last generic argument is always the type of the return value of the lambda function. So, for example, Func<string> is the type of a lambda function that takes no arguments and returns a string. Func<Object,string,int> is the type of a lambda function that takes an object and a string as arguments (in that order) and returns integer.

System.Predicate is a special case of Func where the return type is bool . So, for example, Predicate<string> is the type of a lambda function that takes a string argument and returns a boolean. Predicate<Object,string,int> is the type of a lambda function that takes those three argument types and returns a bool .

These types are used throughout the built-in .NET assemblies.

Actually any delegate type can be the type of a lambda expression, but there is generally no practical reason to use any type other than the three above unless the length of the names of these types becomes too cumbersome to type or read in the source code.

The var keyword can only be used with lambda expressions starting in C# 10, and only for some lambda expressions. Otherwise, you must give a full type.

In Java, there is no fixed type that must be used with a lambda expression. The pre-defined interface classes in java.util.function ( reference ) define some commonly used types, such as Function<T,R> which can be assigned a lambda function that takes a T as an argument and returns an R -type value. The Runnable ( reference ) interface can be used for lambda expressions that take no arguments and return nothing.

Any interface with a single method (a functional interface type) can be the type of a lambda expression, so long as the method has the same return type and arguments as the lambda expression. See the language reference .

Unfortunately, to invoke the lambda function, you must know the name of the method in the particular functional interface that is being used. Consult the interface documentation for the name of the method used to invoke the lambda function.

Dynamically Typed Languages

Although dynamically typed languages like Javascript and Python still have types at runtime , the types are generally not specified in source code.

Metaprogramming

In C#, lambda expressions can be used for metaprogramming. See System.Linq.Expressions.Expression .

Language-Specific Notes

In C++, capture can also be explicit: The brackets can contain a comma-separated list of variables to capture. Variables not mentioned in the list are not captured and not available to the lambda expression. Capture is by copy by default, unless the variable name is preceded with & . The this variable can also be listed when in a non-static class member function, and it is always captured by reference. ( refreence )

Use _ as the name of lambda expression arguments to indicate they are not used, rather than dummy1, dummy2, etc. _ is a lambda discard parameter when it is the name of more than one argument.

Capture can be turned off to avoid accidental capture or if you want to have a variable the same name as a variable in the outer scope by placing the static keyword immediately before the lambda expression.

Lambda expressions can use async .

Nothing yet.

Javascript has a longer, older quasi-alternative syntax to lambda expressions (called function expressions or anonymous functions) that looks like this:

They are almost equivalent. If you don’t use this , arguments , yield , and a few other rarely used keywords, the two syntaxes are pretty much the same.

As noted previously, the capture rules apply to function expressions the same as they do with lambda expressions.

As noted earlier, the capture rules apply to local function definitions the same as they do with lambda expressions.

Because Python variable scope is determined by the nearest assignment, variables in the outer scope cannot be assigned to:

The text variable in the inner function is a different variable than the one in the outer funtion because there is an assignment to text in the inner function. A trick is to make the outer variable a contaier:

Although Python capture is always by reference, there is a trick for achieving capture by value: assigning default values to lambda expression arguments.

It’s a weird and neat trick.

  • C++: Lambda expressions
  • C#: Lambda expression
  • Java: Lambda expressions
  • Javascript: Arrow function expressions/definitions
  • Python: Lambda expressions

thisPointer

Programming Tutorials

  • C++11 Lambda: Capture Variables by Reference or Value

Lambda Functions were introduced in C++11, and it allows us to write Inline, Anonymous Functions. Lambda Functions are also called Lambda Expressions. These Lambda expressions/functions are particularly useful when you need to pass a small function as an argument to another function as callbacks, such as a sorting algorithm or a thread constructor. In this article, we’ll look how to capture local variables within a Lambda Expression / lambda Function in C++.

Table of Contents

What are lambda expressions in c++.

Before we explore variable capturing, let’s understand the basic syntax of a lambda expression:

The [] is known as the capture clause , the () holds any parameters the lambda accepts (like a regular function), and the {} contains the function code that defines the body of the lambda expression.

Capturing Local Variables into a Lambda Function in C++

When you define a lambda expression within a function, you may want to use variables from its enclosing scope, also known as the outer scope . To do this, you can capture these variables in two main ways:

  • By Reference

Capturing Variables by Value into a Lambda Function in C++

Capturing by value means the lambda will have its own copy of the captured variables. These copies are made at the point where the lambda is defined, not when it’s called. Here’s how you can capture variables by value:

The variables msg and counter are now available within the lambda, but they’re const by default – meaning you cannot modify them. To do so, you need to declare the lambda as mutable .

Here is a complete example,

Frequently Asked:

  • How to Print a vector in C++?
  • Lambda Functions in C++
  • How to Capture Member Variables in Lambda function in C++?

As you can see, changes made to msg and counter within the lambda do not affect the originals outside it.

Capturing Variables by Reference into a Lambda Function in C++

If you want your lambda to reflect changes to the captured variables back to the outer scope, you should capture them by reference:

A complete example of capturing by reference would look like this:

Notice how the changes within the lambda are reflected outside

it because msg and counter are captured by reference.

Capturing All Local Variables

You can also capture all local variables without specifying them one by one:

  • By value using [=]
  • By reference using [&]

And you can mix modes:

Capture Variables Carefully in Lambda Function in C++

Be cautious when capturing by reference, especially if the lambda might outlive the captured variables. If a lambda captures a reference to a local variable that goes out of scope, accessing that variable later will lead to undefined behavior, potentially crashing your program.

Here’s an example that demonstrates the danger:

Here, we tried to access a variable that had already been destroyed due to stack unwinding. Basically, the lambda Expression in this example outlives counter , leading to a crash when it tries to modify it.

Compiling Lambda Expressions in C++

To compile code with lambda expressions in C++, make sure to enable the C++11 (or later) standard:

Lambda expressions offer a concise and powerful way to define local functions that can access and manipulate variables in their enclosing scope. By understanding how to capture variables by value or by reference, you can write more expressive and functional code in C++. Always remember to manage the scope of your variables carefully to avoid undefined behavior.

Related posts:

  • What is shared_ptr in C++?
  • Shared_ptr & Custom Deleter in Modern C++
  • Smart Pointer vs Raw Pointer in C++
  • How not to use Smart Pointers in C++?
  • What is weak_ptr in Modern C++ & why do we need it?
  • Using std::find & std::find_if with User Defined Classes
  • C++11 Multithreading – Part 4: Data Sharing and Race Conditions
  • C++11 Multithreading – Part 5: Using mutex to fix Race Conditions
  • C++ Set example and Tutorial – Part 1
  • C++11 Multithreading – Part 7: Condition Variables Explained
  • C++11 Multithreading – Part 8: std::future , std::promise and Returning values from Thread
  • std::bind in C++ – Explained with Examples
  • The auto Keyword in C++11
  • multimap Example and Tutorial in C++
  • C++11 Multithreading – Part 9: std::async Tutorial & Example
  • What is unique_ptr in C++?
  • C++ : Check if given path is a file or directory using Boost & C++17 FileSystem Library

Share your love

4 thoughts on “c++11 lambda: capture variables by reference or value”.

' src=

Inside Lambda :: counter = -858993460 Inside Lambda :: After changing :: counter = 20 Press any key to continue . . .

It is not crashing, please find the output

' src=

Well its an undefined behaviour, some times it will crash, sometimes will give garbage values.

See the value of counter on your output, its garbage.

I tested on linux and it crashed. So, its undefined behaviour.

' src=

yes, it don’t crash on mac too, and i agree with Varun, the result this program is undefined.

' src=

Thank you ! This article was very helpful and concise.

Leave a Comment Cancel Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed .

Shahar Mike's Web Spot

Yet another geek's blog

Under the hood of lambdas and std::function

Table of Contents

In this post we’ll explore how lambdas behave in different aspects. Then we’ll look into std::function and how it works.

What’s a lambda?

Here’s a quick recap if you have yet to use one of the most powerful features of C++11 – lambdas:

Lambdas are a fancy name for anonymous functions. Essentially they are an easy way to write functions (such as callbacks) in the logical place they should be in the code.

My favorite expression in C++ is [](){}(); , which declares an empty lambda and immediately executes it. It is of course completely useless. Better examples are with STL, like:

This has the following advantages over C++98 alternatives: it is where the code would logically be (as opposed to defining a class/function somewhere outside this scope), and it does not pollute any namespace (although this could be easily be bypassed even in C++98).

Lambdas have 3 parts:

  • Capture list – these are variables that are copied inside the lambda to be used in the code;
  • Argument list – these are the arguments that are passed to the lambda at execution time;
  • Code – well.. code.

Here’s a simple example:

  • First line is simple - create 2 int s named i and j .
  • Captures i by value, j by reference,
  • Accepts 2 parameters: bool b and float f ,
  • Prints b and f when invoked
  • Third line calls this lambda with true and 1.0f

I find it useful to think of lambdas as classes :

  • The data members for f above are i and j ;
  • The lambda can access these members inside it’s code scope.
  • When a lambda is created, a constructor copies the captured variables to the data members;
  • It has an operator()(...) (for f the ... is bool, float );
  • It has a scope-lifetime and a destructor which frees members.

One last thing syntax-wise: you can also specify a default capture:

  • [&](){ i = 0; j = 0; } is a lambda that captures i and j by reference. [&] means ‘capture by-reference all variables that are in use in the function’
  • [=](){ cout << k; } is a lambda that captures k by value. Similarly, [=] means ‘capture by-value all variables that are in use in the function’
  • You can also mix and match: [&, i, j](){} captures all variables by reference except for i and j which are captures by value. And of-course the opposite is also possible: [=, &i, &j](){} .

Capture by value vs by reference

Above we mentioned capturing a lambda by value vs by reference. What’s the difference? Here’s a simple code that will illustrate:

Lambda’s type

One important thing to note is that a lambda is not a std::function . It is true that a lambda can be assigned to a std::function , but that is not its native type. We’ll talk about what that means soon.

As a matter of fact, there is no standard type for lambdas. A lambda’s type is implementation defined, and the only way to capture a lambda with no conversion is by using auto :

However, if your capture list is empty you may convert your lambda to a C-style function pointer:

Lambda’s scope

All captured variables have the scope of the lambda:

mutable lambdas

lambda’s operator() is const by-default, meaning it can’t modify the variables it captured by-value (which are analogous to class members). To change this default add mutable :

This gets even more interesting when talking about copying lambdas. Key thing to remember - they behave like classes:

Lambda’s size

Because lambdas have captures, there’s no single size for all lambdas. Example:

Output (64-bit build):

Performance

Lambdas are also awesome when it comes to performance. Because they are objects rather than pointers they can be inlined very easily by the compiler, much like functors. This means that calling a lambda many times (such as with std::sort or std::copy_if ) is much better than using a global function. This is one example of where C++ is actually faster than C.

std::function

std::function is a templated object that is used to store and call any callable type, such as functions, objects, lambdas and the result of std::bind .

Simple example

Std::function ’s size.

On clang++ the size of all std::function s (regardless of return value or parameters) is always 32 bytes. It uses what is called small size optimization , much like std::string does on many implementations. This basically means that for small objects std::function can keep them as part of its memory, but for bigger objects it defers to dynamic memory allocation. Here’s an example on a 64-bit machine:

17. That’s the threshold beyond which std::function reverts to dynamic allocation (on clang). Note that the allocation is for the size of 17 bytes as the lambda object needs to be contiguous in memory.

That’s it for my first post. I hope you enjoyed reading it as much as I enjoyed writing it. Please let me know if you have any suggestions, questions or comments!

Jeremi Mucha

Lambdas under the hood

by Jeremi | Mar 29, 2021 | C++ | 0 comments

What is a lambda

Let’s just get this out of the way – the name lambda refers to lambda-calculus . But there’s no point in me citing Wikipedia or other sources that already provide plenty of theoretical information. I think it needed to be mentioned, so there. And now I’m going to move on to information relevant to C++.

A lambda in the context of C++ can be seen as syntactic sugar for defining function objects. There’s a lot of important detail missing from this statement, but let’s start here and build on it. First things first, let’s define a simple lambda to provide some context for the discussion.

The above snippet defines an add1 variable as an instance of a lambda that takes a single integer argument, adds 1 to it and returns the result. I’m assuming that you’re already familiar with the syntax, in case you’re not, here’s a quick explanation.

The square brackets declare lambda-captures, which I’m not using in this example, but I will explain later. The parenthesis declare the parameters the lambda accepts – here it takes a single integer argument. The braces define the lambda body. The syntax may get some getting used to if you’re new, but I’m sure you’ll manage to follow along.

Well, there goes that first definition I mentioned in the introductory paragraph – I just assigned a lambda to an object, thus giving it a name, sort of. But let’s get back on track. How would a function object providing the same functionality be defined? And what is a function object in the first place?

A function object is a callable – an instance of a type, struct or class, that defines a function call operator – operator(). This means that an equivalent to the add1 lambda could be defined like so:

This code leads to the same result as the lambda example. Moreover, it likely results in equivalent machine code being generated. Notice that compared to a lambda, here, I had to do two distinct steps – first I had to define a struct (type) that specifies what the function object does, and second, I had to instantiate that type. A lambda does all this in a single expression.

Did you notice anything about the call operator declaration? That’s right – it’s const . When defining member functions we need to explicitly declare that the function does not mutate the object’s state (i.e. make them const ). Lambdas on the other hand are const by default – we’re not allowed to mutate their state, unless we specify that we’d like to be able to do so. Right now there’s no state to speak of, so let’s expand the example and see what this is about.

Lambda captures and state

Lambda-captures are declared and defined in the brackets that begin the lambda definition. Going back to the add1 example, a lambda capture could be used to define the value that should be added to the argument:

The above code would be functionally equivalent to the original example. Also note that I’m using C++14 capture syntax here – the capture y is initialized with a literal value 1 . In this context of course the capture doesn’t make much sense, but imagine it being initialized with an argument passed to some function and then passed along to an std algorithm, like so:

or some other example that calculates the captured value in an arbitrarily complex way, and then uses it. Anyway, back to the example.

A function object definition equivalent to the above lambda would look like so:

The output once again would be equivalent. The lambda-capture is simply a member data field of the function object type. Now, what about the call operator’s constness? The obvious consequence is that we’re not allowed to change the value of y . For example, if we wanted to incrementally increase the added value, we’re not allowed to do so:

The compiler complains (the example is formatted differently for readability):

The same is true of course for the function object:

If changing the object’s state is in fact our intent, we can easily make the compiler accept this code by removing the const in the function-object example.

With the lambda, we need to explicitly state that we’d like to constness removed, this is done using the mutable keyword:

After these changes, the compiler happily accepts both examples. Note that with function-objects it’s easy to simply forget to specify the call operator as const , thus allowing accidental object mutation. Since lambdas are const by default, they protect us against such accidents. The addition of the mutable keyword also brings attention of the reader to the fact that the state is being changed inside the body of this lambda. With regular function objects it might be the case that the call operator isn’t const simply because the author neglected to mark it so. This is likely the case more often then we’d like to admitt.

So you now know that a basic lambda is just a function object. As you may or may not know C++14 introduced generic lambdas. That it, the auto keyword may be used to declare lambda parameters, thus making it accept arbitrary types, like so:

With this definition the compiler will now deduce the type of x for us. How is this achieved? At least two contexts where type deduction takes place should come to mind – auto and templates. Both of these in fact use the same mechanism – template type deduction. This situation is no different – a generic lambda is a function object with a templetized function call operator:

Note that only the function call operator is templetized, not the entire function object – the capture type is known to the compiler at the time the captures are defined so there’s no need to make the function object a template.

Zero-cost abstraction

Herb Sutter defines zero-cost abstraction as “An abstraction that performs as good or better than could be reasonably written by hand”. I think lambdas are a perfect example. You can type all of this out manually, but lambdas achieve the same outcome with much less code, while also providing safer defaults (constness).

Given the information on how lambdas work under the hood it should be clear that they are an extremely lightweight abstraction. You should not be concerned about the object insantiation or call overhead – there is none for small types like this wihout a vtable. In fact as soon as the optimizer is enabled, even with the lowest settings, code like the one shown in examples is perfectly inlined and goes away entirely. That’s where the comparison of lambdas to std::function fails. Sure, the functionality is similar, however the cost of a lambda can be orders of magnitude smaller than using a std::function . For small function objects a std::function incurs a cost of at least one pointer dereference and a virtual function call. For large objects there’s an additional cost of a dynamic allocation on construction, and this depends on the standard library implementation – some may always allocate. A lambda will never implicitly allocate and most of the time (always?) is perfectly inlined. Note that the uses are not the same – you don’t get type erasure with a lambda, so they’re only a subset of the functionality std::function provides.

Once you’re accustomed to lambdas and additionally strive for const-correctness you may find yourself writing code akin to the following:

The above uses an Immediately Invoked Function Expression ( IIFE ) to conditionally initialize a variable that’s used, but unchanged throughout the rest of the code. It’s not new and is now considered an idiom. That’s only one of many lambda uses that may not be obvious at first. I’d encourage you to look for lambda-use opportunities all the time. Careful though! Once you catch on it’s quite easy to abuse them. Food for thought – could you replace most (all?) non-member function definitions with lambdas?

C++11 begun a new era in C++ – it introduced a multitude of excellent features and lambdas are arguably one of the most important ones. What’s your relationship with C++ lambdas? Do you shy away from them? Do you limit their use only to standard algorithm predicates? Or are you already one of the lambda aficionados that gets excited whenever an opportunity for an unorthodox yet reasonable lambda use presents itself?

  • Lambda calculus
  • Sutter’s Mill

Submit a Comment Cancel reply

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

Submit Comment

Recent Posts

  • Pythonic overload sets with singledispatch
  • CMake Fundamentals Part 9
  • CMake Managing Resources
  • CMake Fundamentals Part 8
  • CMake FetchContent
  • Metaprogramming (1)
  • Musings (1)

Using Lambda environment variables

You can use environment variables to adjust your function's behavior without updating code. An environment variable is a pair of strings that is stored in a function's version-specific configuration. The Lambda runtime makes environment variables available to your code and sets additional environment variables that contain information about the function and invocation request.

To increase security, we recommend that you use AWS Secrets Manager instead of environment variables to store database credentials and other sensitive information like API keys or authorization tokens. For more information, see Create and manage secrets with AWS Secrets Manager .

Environment variables are not evaluated before the function invocation. Any value you define is considered a literal string and not expanded. Perform the variable evaluation in your function code.

Configuring environment variables (console)

Configuring environment variables (api), configuring environment variables (aws cli), configuring environment variables (aws sam), example scenario for environment variables, retrieve environment variables, defined runtime environment variables, securing environment variables.

You define environment variables on the unpublished version of your function. When you publish a version, the environment variables are locked for that version along with other version-specific configuration settings .

You create an environment variable for your function by defining a key and a value. Your function uses the name of the key to retrieve the value of the environment variable.

To set environment variables in the Lambda console

Open the Functions page of the Lambda console.

Choose a function.

Choose Configuration , then choose Environment variables .

Under Environment variables , choose Edit .

Choose Add environment variable .

Enter a key and value.

Requirements

Keys start with a letter and are at least two characters.

Keys only contain letters, numbers, and the underscore character ( _ ).

Keys aren't reserved by Lambda .

The total size of all environment variables doesn't exceed 4 KB.

Choose Save .

To generate a list of environment variables in the console code editor

You can generate a list of environment variables in the Lambda code editor. This is a quick way to reference your environment variables while you code.

Choose the Code tab.

Choose the Environment Variables tab.

Choose Tools , Show Environment Variables .

Environment variables remain encrypted when listed in the console code editor. If you enabled encryption helpers for encryption in transit, then those settings remain unchanged. For more information, see Securing environment variables .

The environment variables list is read-only and is available only on the Lambda console. This file is not included when you download the function's .zip file archive, and you can't add environment variables by uploading this file.

To manage environment variables with the AWS CLI or AWS SDK, use the following API operations.

UpdateFunctionConfiguration

GetFunctionConfiguration

CreateFunction

The following example sets two environment variables on a function named my-function .

When you apply environment variables with the update-function-configuration command, the entire contents of the Variables structure is replaced. To retain existing environment variables when you add a new one, include all existing values in your request.

To get the current configuration, use the get-function-configuration command.

You should see the following output:

You can pass the revision ID from the output of get-function-configuration as a parameter to update-function-configuration . This ensures that the values don't change between when you read the configuration and when you update it.

To configure a function's encryption key, set the KMSKeyARN option.

You can use the AWS Serverless Application Model to configure environment variables for your function. Update the Environment and Variables properties in your template.yaml file and then run sam deploy .

Example template.yaml

You can use environment variables to customize function behavior in your test environment and production environment. For example, you can create two functions with the same code but different configurations. One function connects to a test database, and the other connects to a production database. In this situation, you use environment variables to pass the hostname and other connection details for the database to the function.

The following example shows how to define the database host and database name as environment variables.

Environment variables in the Lambda console.

If you want your test environment to generate more debug information than the production environment, you could set an environment variable to configure your test environment to use more verbose logging or more detailed tracing.

To retrieve environment variables in your function code, use the standard method for your programming language.

In some cases, you may need to use the following format:

Lambda stores environment variables securely by encrypting them at rest. You can configure Lambda to use a different encryption key , encrypt environment variable values on the client side, or set environment variables in an AWS CloudFormation template with AWS Secrets Manager.

Lambda runtimes set several environment variables during initialization. Most of the environment variables provide information about the function or runtime. The keys for these environment variables are reserved and cannot be set in your function configuration.

Reserved environment variables

_HANDLER – The handler location configured on the function.

_X_AMZN_TRACE_ID – The X-Ray tracing header . This environment variable changes with each invocation.

This environment variable is not defined for OS-only runtimes (the provided runtime family). You can set _X_AMZN_TRACE_ID for custom runtimes using the Lambda-Runtime-Trace-Id response header from the Next invocation .

For Java runtime versions 17 and later, this environment variable is not used. Instead, Lambda stores tracing information in the com.amazonaws.xray.traceHeader system property.

AWS_DEFAULT_REGION – The default AWS Region where the Lambda function is executed.

AWS_REGION – The AWS Region where the Lambda function is executed. If defined, this value overrides the AWS_DEFAULT_REGION .

For more information about using the AWS Region environment variables with AWS SDKs, see AWS Region in the AWS SDKs and Tools Reference Guide .

AWS_EXECUTION_ENV – The runtime identifier , prefixed by AWS_Lambda_ (for example, AWS_Lambda_java8 ). This environment variable is not defined for OS-only runtimes (the provided runtime family).

AWS_LAMBDA_FUNCTION_NAME – The name of the function.

AWS_LAMBDA_FUNCTION_MEMORY_SIZE – The amount of memory available to the function in MB.

AWS_LAMBDA_FUNCTION_VERSION – The version of the function being executed.

AWS_LAMBDA_INITIALIZATION_TYPE – The initialization type of the function, which is on-demand , provisioned-concurrency , or snap-start . For information, see Configuring provisioned concurrency or Improving startup performance with Lambda SnapStart .

AWS_LAMBDA_LOG_GROUP_NAME , AWS_LAMBDA_LOG_STREAM_NAME – The name of the Amazon CloudWatch Logs group and stream for the function. The AWS_LAMBDA_LOG_GROUP_NAME and AWS_LAMBDA_LOG_STREAM_NAME environment variables are not available in Lambda SnapStart functions.

AWS_ACCESS_KEY , AWS_ACCESS_KEY_ID , AWS_SECRET_ACCESS_KEY , AWS_SESSION_TOKEN – The access keys obtained from the function's execution role .

AWS_LAMBDA_RUNTIME_API – ( Custom runtime ) The host and port of the runtime API .

LAMBDA_TASK_ROOT – The path to your Lambda function code.

LAMBDA_RUNTIME_DIR – The path to runtime libraries.

The following additional environment variables aren't reserved and can be extended in your function configuration.

Unreserved environment variables

LANG – The locale of the runtime ( en_US.UTF-8 ).

PATH – The execution path ( /usr/local/bin:/usr/bin/:/bin:/opt/bin ).

LD_LIBRARY_PATH – The system library path ( /var/lang/lib:/lib64:/usr/lib64:$LAMBDA_RUNTIME_DIR:$LAMBDA_RUNTIME_DIR/lib:$LAMBDA_TASK_ROOT:$LAMBDA_TASK_ROOT/lib:/opt/lib ).

NODE_PATH – ( Node.js ) The Node.js library path ( /opt/nodejs/node12/node_modules/:/opt/nodejs/node_modules:$LAMBDA_RUNTIME_DIR/node_modules ).

PYTHONPATH – ( Python 2.7, 3.6, 3.8 ) The Python library path ( $LAMBDA_RUNTIME_DIR ).

GEM_PATH – ( Ruby ) The Ruby library path ( $LAMBDA_TASK_ROOT/vendor/bundle/ruby/2.5.0:/opt/ruby/gems/2.5.0 ).

AWS_XRAY_CONTEXT_MISSING – For X-Ray tracing, Lambda sets this to LOG_ERROR to avoid throwing runtime errors from the X-Ray SDK.

AWS_XRAY_DAEMON_ADDRESS – For X-Ray tracing, the IP address and port of the X-Ray daemon.

AWS_LAMBDA_DOTNET_PREJIT – For the .NET 6 and .NET 7 runtimes, set this variable to enable or disable .NET specific runtime optimizations. Values include always , never , and provisioned-concurrency . For more information, see Configuring provisioned concurrency .

TZ – The environment's time zone ( UTC ). The execution environment uses NTP to synchronize the system clock.

The sample values shown reflect the latest runtimes. The presence of specific variables or their values can vary on earlier runtimes.

For securing your environment variables, you can use server-side encryption to protect your data at rest and client-side encryption to protect your data in transit.

To increase database security, we recommend that you use AWS Secrets Manager instead of environment variables to store database credentials. For more information, see Using AWS Lambda with Amazon RDS .

Security at rest

Lambda always provides server-side encryption at rest with an AWS KMS key. By default, Lambda uses an AWS managed key. If this default behavior suits your workflow, you don't need to set up anything else. Lambda creates the AWS managed key in your account and manages permissions to it for you. AWS doesn't charge you to use this key.

If you prefer, you can provide an AWS KMS customer managed key instead. You might do this to have control over rotation of the KMS key or to meet the requirements of your organization for managing KMS keys. When you use a customer managed key, only users in your account with access to the KMS key can view or manage environment variables on the function.

Customer managed keys incur standard AWS KMS charges. For more information, see AWS Key Management Service pricing .

Security in transit

For additional security, you can enable helpers for encryption in transit, which ensures that your environment variables are encrypted client-side for protection in transit.

To configure encryption for your environment variables

Use the AWS Key Management Service (AWS KMS) to create any customer managed keys for Lambda to use for server-side and client-side encryption. For more information, see Creating keys in the AWS Key Management Service Developer Guide .

Using the Lambda console, navigate to the Edit environment variables page.

Choose Configuration , then choose Environment variables from the left navigation bar.

In the Environment variables section, choose Edit .

Expand Encryption configuration .

(Optional) Enable console encryption helpers to use client-side encryption to protect your data in transit.

Under Encryption in transit , choose Enable helpers for encryption in transit .

For each environment variable that you want to enable console encryption helpers for, choose Encrypt next to the environment variable.

Under AWS KMS key to encrypt in transit, choose a customer managed key that you created at the beginning of this procedure.

Choose Execution role policy and copy the policy. This policy grants permission to your function's execution role to decrypt the environment variables.

Save this policy to use in the last step of this procedure.

Add code to your function that decrypts the environment variables. To see an example, choose Decrypt secrets snippet .

(Optional) Specify your customer managed key for encryption at rest.

Choose Use a customer master key .

Choose a customer managed key that you created at the beginning of this procedure.

Set up permissions.

If you're using a customer managed key with server-side encryption, grant permissions to any users or roles that you want to be able to view or manage environment variables on the function. For more information, see Managing permissions to your server-side encryption KMS key .

If you're enabling client-side encryption for security in transit, your function needs permission to call the kms:Decrypt API operation. Add the policy that you saved previously in this procedure to the function's execution role .

Managing permissions to your server-side encryption KMS key

No AWS KMS permissions are required for your user or the function's execution role to use the default encryption key. To use a customer managed key, you need permission to use the key. Lambda uses your permissions to create a grant on the key. This allows Lambda to use it for encryption.

kms:ListAliases – To view keys in the Lambda console.

kms:CreateGrant , kms:Encrypt – To configure a customer managed key on a function.

kms:Decrypt – To view and manage environment variables that are encrypted with a customer managed key.

You can get these permissions from your AWS account or from a key's resource-based permissions policy. ListAliases is provided by the managed policies for Lambda . Key policies grant the remaining permissions to users in the Key users group.

Users without Decrypt permissions can still manage functions, but they can't view environment variables or manage them in the Lambda console. To prevent a user from viewing environment variables, add a statement to the user's permissions that denies access to the default key, a customer managed key, or all keys.

Example IAM policy – Deny access by key ARN

Error message for user without decrypt permissions in the Lambda console.

For details on managing key permissions, see Key policies in AWS KMS in the AWS Key Management Service Developer Guide .

Warning

To use the Amazon Web Services Documentation, Javascript must be enabled. Please refer to your browser's Help pages for instructions.

Thanks for letting us know we're doing a good job!

If you've got a moment, please tell us what we did right so we can do more of it.

Thanks for letting us know this page needs work. We're sorry we let you down.

If you've got a moment, please tell us how we can make the documentation better.

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

'ReadOnly' variable cannot be the target of an assignment in a lambda expression inside a constructor

  • 11 contributors

You have referred to a ReadOnly variable from within a lambda expression, which is not permitted. The following code causes this error by sending the ReadOnly variable m as the argument to a ByRef parameter.

Error ID: BC36602

To correct this error

If possible, change parameter n in function Test to a ByVal parameter, as shown in the following code.

Assign the ReadOnly variable m to a local variable in the constructor, and use the local variable in place of m , as shown in the following code.

  • Lambda Expressions
  • Constructors

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

  • Documentation »
  • Correctness »
  • Assigning a lambda expression to a variable
  • View page source

Assigning a lambda expression to a variable ¶

The sole advantage that a lambda expression has over a def is that the lambda can be anonymously embedded within a larger expression. If you are going to assign a name to a lambda , you are better off just defining it as a def .

From the PEP 8 Style Guide:

The first form means that the name of the resulting function object is specifically ‘f’ instead of the generic ‘<lambda>’. This is more useful for tracebacks and string representations in general. The use of the assignment statement eliminates the sole benefit a lambda expression can offer over an explicit def statement (i.e. that it can be embedded inside a larger expression)

Anti-pattern ¶

The following code assigns a lambda function which returns the double of its input to a variable. This is functionally identical to creating a def .

Best practice ¶

Use a def for named expressions ¶.

Refactor the lambda expression into a named def expression.

References ¶

  • PEP 8 Style Guide - Programming Recommendations
  • Stack Overflow - Do not assign a lambda expression

Navigation Menu

Search code, repositories, users, issues, pull requests..., provide feedback.

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly.

To see all available qualifiers, see our documentation .

  • Notifications

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make throws error: assignment of read-only variable ‘L’ #107

@firun

firun commented Dec 30, 2018

  • 👍 1 reaction

Sorry, something went wrong.

@vineelpratap

vineelpratap commented Dec 30, 2018 • edited

@vineelpratap

No branches or pull requests

@vineelpratap

IMAGES

  1. C++ : Is it possible to access (read only) the variables captured by a

    lambda assignment of read only variable

  2. Best practices when you use Lambda expressions in Java

    lambda assignment of read only variable

  3. Lambda Functions with Example and Error Handling

    lambda assignment of read only variable

  4. What is a lambda expression in Java? Where did the term 'lambda' come from?

    lambda assignment of read only variable

  5. How to Effectively Use Lambda Functions in Python as a Data Scientist

    lambda assignment of read only variable

  6. Introduction a unique Insider: Python Lambda Function

    lambda assignment of read only variable

VIDEO

  1. C++ From Scratch: Lambdas

  2. Read only variable

  3. variable and assignment #learnngrow #coding #coder

  4. How To Read AWS S3 File Using Lambda Function (4 Min)

  5. How to Write AWS Lambda Function

  6. error: assignment of read-only variable

COMMENTS

  1. Why are lambda arguments passed by value read-only in C++11?

    When a function takes an argument by value, it can usually modify it. However, this does not seem to be the case with lambdas. Why? int x = 0; auto lambda = [x] { x = 1; }; // error: assignment of read-only variable 'x'. return 0; By default, the closure's apply-operator is const.

  2. Assignment inside lambda expression in Python

    The assignment expression operator := added in Python 3.8 supports assignment inside of lambda expressions. This operator can only appear within a parenthesized (...), bracketed [...], or braced {...} expression for syntactic reasons. For example, we will be able to write the following: import sys. say_hello = lambda: (.

  3. Lambda expressions (since C++11)

    A lambda expression can read the value of a variable without capturing it if the variable ... The copy assignment operator is defined as deleted (and the move assignment operator is not declared). ... Only lambda-expressions defined at block scope or in a default member initializer may have a capture-default or captures without initializers.

  4. 20.7

    When a lambda definition is executed, for each variable that the lambda captures, a clone of that variable is made (with an identical name) inside the lambda. These cloned variables are initialized from the outer scope variables of the same name at this point. Thus, in the above example, when the lambda object is created, the lambda gets its ...

  5. Lambda Expressions: A Guide

    Assigning a lambda expression to a variable. It can be assigned to a variable. Variable assignment normally looks like this of course: A variable assignment statement in C-family languages f = 10; (C++ and C# are a statically typed language so the variable must be declared first with its type, but we will omit the variable declaration for now.)

  6. Modern C++ In-Depth

    Here's a simple example of what it might look like to assign a lambda expression to a variable: ... string_view makes it easier to write generic code that can accept read-only references to ...

  7. C++11 Lambda: Capture Variables by Reference or Value

    These copies are made at the point where the lambda is defined, not when it's called. Here's how you can capture variables by value: Copy to clipboard. // Local Variables. std::string msg = "Hello"; int counter = 10; // Defining Lambda function and Capturing Local variables by Value. auto func = [msg, counter] () {.

  8. How to Use Python Lambda Functions

    Consider a two-argument anonymous function defined with lambda but not bound to a variable. The lambda is not given a name: Python >>> lambda x, y: x + y. ... and a traceback shows only <lambda>: Python >>> div_zero = lambda x: ... you can assign a lambda to the named argument key, such that the sorting will use the number associated with the ID:

  9. Python workarounds for assignment in lambda

    r=range;r(a)+r(b) print s[1:],s[1:]*2. r=s[1:];print r,r*2. Other languages have workarounds, Octave for example. There are known tricks for Python, but they are long, clunky, and/or limited-use. A short, general-purpose method to simulate assignment in a lambda would revolutionize Python golfing. What are ways for a Python golfer to overcome ...

  10. Tutorial: Lambda Functions in Python

    Even though the function above spans more lines than the corresponding lambda function, it's much easier to read. We can assign a lambda function to a variable and then call that variable as a normal function: increment = lambda x: x + 1 increment(2) 3. However, it's a bad practice, according the PEP 8 style guide for Python code:

  11. c++

    you also have mistakes, you have another TIME variable declared in the scope static const bool TIME = true;, you need to either change the type (do you want it to be a bool?) and remove the const modifier from that one OR you have to fully qualify the path to the other TIME variable (the one in the other file) - shafeen

  12. Under the hood of lambdas and std::function

    A lambda's type is implementation defined, and the only way to capture a lambda with no conversion is by using auto: auto f2 = [](){}; However, if your capture list is empty you may convert your lambda to a C-style function pointer: void (*foo)(bool, int); foo = [](bool, int){}; Lambda's scope. All captured variables have the scope of the ...

  13. Lambdas under the hood

    First things first, let's define a simple lambda to provide some context for the discussion. auto add1 = [](int x) { return x + 1; }; std::cout << add1(41) << "\n"; The above snippet defines an add1 variable as an instance of a lambda that takes a single integer argument, adds 1 to it and returns the result.

  14. Using Lambda environment variables

    To generate a list of environment variables in the console code editor. You can generate a list of environment variables in the Lambda code editor. This is a quick way to reference your environment variables while you code. Choose Tools, Show Environment Variables. Environment variables remain encrypted when listed in the console code editor.

  15. 20.6

    Although we only wrote the lambda once, two lambdas were generated -- and each has its own version of callCount. To have a shared counter between the two generated lambdas, we'd have to define a global variable or a static local variable outside of the lambda. As you know from previous lessons, both global- and static local variables can ...

  16. 'ReadOnly' variable cannot be the target of an assignment in a lambda

    Assign the ReadOnly variable m to a local variable in the constructor, and use the local variable in place of m, as shown in the following code. Class Class1Fix2 ReadOnly m As Integer Sub New() Dim temp = m Dim f = Function() Test(temp) End Sub Function Test(ByRef n As Integer) As String End Function End Class

  17. Assigning value to readonly variable during declaration

    Generally though, you'd want to use. readonly c="$(( a + b ))" i.e. quoting the expansion. If the variable IFS has a value that includes the digit 2, it could otherwise lead to an empty value in c. The value would be empty as the shell would have split the arguments to readonly on the 2, resulting in the command. readonly c=.

  18. Assigning a lambda expression to a variable

    If you are going to assign a name to a lambda, you are better off just defining it as a def. From the PEP 8 Style Guide: Yes: def f(x): return 2*x. No: f = lambda x: 2*x. The first form means that the name of the resulting function object is specifically 'f' instead of the generic '<lambda>'. This is more useful for tracebacks and ...

  19. Read only reference variable in a lambda expression

    That way the caller can create a Completion and pass it to the Play() method which casts it as ICompletionNotification. var completion = new Completion(); Play(player, completion); The caller can call Complete() to indicate that it's done, but the receiver can't set that property. It can only read it.

  20. make throws error: assignment of read-only variable 'L' #107

    You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window.

  21. c++

    9. Well, your array's fields are read-only variables, so you can't assign values to them. Remove the const qualifier, and it should work fine. I'm unsure whether array[num_elements] = num_elements++ does something useful, though. Maybe you wanted to do array[num_elements++] = i instead? answered Apr 1, 2014 at 14:34.