Skip to content

Revisions to lambda expressions topic. #1285

New issue

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

Merged
merged 4 commits into from
Nov 29, 2016
Merged

Conversation

rpetrusha
Copy link
Contributor

Revisions to lambda expressions topic

Summary

Extensively revised with new examples and a section on tuples and lambda expressions.

Suggested Reviewers

@BillWagner @stevehoag @mairaw

@dotnet-bot
Copy link
Contributor

❌ Validation status: errors

File Status Preview URL Details
docs/csharp/lambda-expressions.md ❌Error Details
samples/snippets/csharp/concepts/lambda-expressions/async1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/expression3.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/infer1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/lambda1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/lambda2.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/query1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/scope.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/statement1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/tuples1.cs ✅Succeeded
samples/snippets/csharp/concepts/lambda-expressions/tuples2.cs ✅Succeeded

docs/csharp/lambda-expressions.md

  • Line unspecified: [Error] Tag Snippet1 is not paired or occurred just more than once, details: (2 start lines, 0 end lines)
  • Line unspecified: [Error] Tag name 2 is not found
  • Line unspecified: [Error] Tag Snippet1 is not paired or occurred just more than once, details: (0 start lines, 2 end lines)
  • Line unspecified: [Error] Tag name 1 is not found
  • Line unspecified: [Error] Tag Snippet3 is not paired or occurred just more than once, details: (2 start lines, 0 end lines)

For more details, please refer to the build report.

Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.

@mairaw
Copy link
Contributor

mairaw commented Nov 23, 2016

There are some build errors. It would be good to fix those first, otherwise we can't even see it on staging.

@rpetrusha
Copy link
Contributor Author

@mairaw I think I've fixed all the build errors. A new build should run shortly.

@dotnet-bot
Copy link
Contributor

✅ Validation status: passed

File Status Preview URL Details
docs/csharp/lambda-expressions.md ✅Succeeded View

For more details, please refer to the build report.

Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.

Copy link
Contributor

@stevehoag stevehoag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - add a few minor comments.

keywords: .NET, .NET Core
author: dotnet-bot
manager: wpickett
ms.date: 06/20/2016
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the date; also needs a ms.author.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevehoag Thanks. I completely forgot to copy the header from the original topic.


## Lambda expressions and tuples ##

Starting with C# 7.0, the C# language provides built-in support for tuples. You can provide a tuple as an argument to a lambda expression, and your lambda expression can also return a tuple. In some cases, the C# compiler uses type inference to determine the types of tuple components.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to the Tuples topic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevehoag I've added it. Thanks for thinking of it; I'd intended to do it, and forgot


[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/query1.cs#3)]

You can also supply a lambda expression when the argument type is an @System.Linq.Expressions.Expression%601, for example in the standard query operators that are defined in the @System.Linq.Queryable type. When you specify an @System.Linq.Expressions.Expression%601 argument, the lambda is compiled to an expression tree. The following example uses the @System.Linq.Enumerable.Count%60%601(System.Collections.Generic.IEnumerable{t%60%600})) standard query operator.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last link (@System.Linq.Enumerable.Count) isn't resolving.


## See Also ##

[LINQ (Language-Integrated Query)](../standard/using-linq.md)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These three links are all showing up on a single line - was that intentional?


- A lambda expression cannot contain a `goto` statement, `break` statement, or `continue` statement that is inside the lambda function if the jump statement’s target is outside the block. It is also an error to have a jump statement outside the lambda function block if the target is inside the block.

## Featured Book Chapter ##
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still be linking to this? The book was published in 2007.

@dotnet-bot
Copy link
Contributor

✅ Validation status: passed

File Status Preview URL Details
docs/csharp/lambda-expressions.md ✅Succeeded View

For more details, please refer to the build report.

Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.


[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/infer1.cs#1)]

The general rules for type inteference for lambdas are:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: inteference

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mairaw And I didn't even spell the wrong word (interference) correctly. Fixed.


## Variable Scope in Lambda Expressions ##

Lambdas can refer to *outer variables* (see [Anonymous methods](programming-guide/statements-expressions-operators/anonymous-methods.md)) that are in scope in the method that defines the lambda function, or in scope in the type that contains the lambda expression. Variables that are captured in this manner are stored for use in the lambda expression even if the variables would otherwise go out of scope and be garbage collected. An outer variable must be definitely assigned before it can be consumed in a lambda expression. The following example demonstrates these rules.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must be definitely -> must be (I think the must is enough)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this should stay "definitely assigned". That's the phrase the spec always uses for the analysis of assignment to a variable before it is used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know @BillWagner 😄


## Type inference in lambda expressions ##

When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: missing comma after So

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just remove "So".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should delete "delegate" in the phrase "the parameter's delegate type". Or am I misunderstanding this sentence?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mairaw @BillWagner I've removed the "So". And changed "the parameter's delegate type" to "the parameter types".

Copy link
Member

@BillWagner BillWagner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ron, I like the way you've explained all the concepts here.

I had a few locations where the language is technically incorrect based on the terms used in the spec. once those are handled, this looks great.

ms.assetid: b6a0539a-8ce5-4da7-adcf-44be345a2714
-title: Lambda Expressions
-description: Lean to use lambda expressions, which are executable code blocks that can be passed as arguments.
-keywords: .NET, .NET Core, lambda epxressions, lambdas, delegates
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: epxressions


- Creating [expression trees](expression-trees-building.md).

Lambda expressions are delegates. The specific delegate type of a lambda expressions depends on its parameters and return value. Lambda expressions that don't return a value correspond to a specific `Action` delegate, depending on its number of parameters. Lambda expressions that return a value correspond to a specific `Func` delegate, depending on its number of parameters. For example, a lambda expression that has two parameters but returns no value corresponds to an @System.Action%602 delegate. A lambda expression that has one parameter and returns a value corresponds to @System.Func%602 delegate.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lambda expressions are delegates, except when they are expression trees.

Maybe "Lambda expressions are code that can be represented either as a delegate, or an expression tree that would compile to a delegate". (I'm not sure I like that wording, improve at will.)


[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/expression3.cs#3)]

Note in the previous example that the body of an expression lambda can consist of a method call. However, if you are creating expression trees that are evaluated outside of the .NET Framework, such as in SQL Server, you should not use method calls in lambda expressions. The methods will have no meaning outside the context of the .NET runtime.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add some weasel words here. Entity Framework does translate some known methods (especially on the string class. The guidance is correct in the general case.


[!CODE [csSnippets.Lambdas](../../samples/snippets/csharp/concepts/lambda-expressions/statement1.cs#1)]

Statement lambdas, like anonymous methods, cannot be used to create expression trees.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend deleting "like anonymous methods". The C# spec defines lambda expressions as a syntax for anonymous methods, so in that sense all lambda expressions are anonymous methods.


## Lambdas with the standard query operators ##

Many standard query operators have an input parameter whose type is one of the @System.Func%601 family of generic delegates. These delegates use type parameters to define the number and type of input parameters, and the return type of the delegate. `Func` delegates are very useful for encapsulating user-defined expressions that are applied to each element in a set of source data. For example, consider the @System.Func%601 delegate, whose syntax is:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would start this by saying "LINQ to Objects, among other implementations" have an input parameter..

That way this is distinguished from the IQueryable discussion later.


## Type inference in lambda expressions ##

When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just remove "So".


## Type inference in lambda expressions ##

When writing lambdas, you often do not have to specify a type for the input parameters because the compiler can infer the type based on the lambda body, the parameter’s delegate type, and other factors, as described in the C# Language Specification. For most of the standard query operators, the first input is the type of the elements in the source sequence. So if you are querying an `IEnumerable<Customer>`, then the input variable is inferred to be a `Customer` object, which means you have access to its methods and properties:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should delete "delegate" in the phrase "the parameter's delegate type". Or am I misunderstanding this sentence?


## Variable Scope in Lambda Expressions ##

Lambdas can refer to *outer variables* (see [Anonymous methods](programming-guide/statements-expressions-operators/anonymous-methods.md)) that are in scope in the method that defines the lambda function, or in scope in the type that contains the lambda expression. Variables that are captured in this manner are stored for use in the lambda expression even if the variables would otherwise go out of scope and be garbage collected. An outer variable must be definitely assigned before it can be consumed in a lambda expression. The following example demonstrates these rules.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this should stay "definitely assigned". That's the phrase the spec always uses for the analysis of assignment to a variable before it is used.

@rpetrusha
Copy link
Contributor Author

@BillWagner I've addressed all of your comments and will update the topic.

@dotnet-bot
Copy link
Contributor

✅ Validation status: passed

File Status Preview URL Details
docs/csharp/lambda-expressions.md ✅Succeeded View

For more details, please refer to the build report.

Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.

@BillWagner
Copy link
Member

@rpetrusha LGTM. :shipit:

@rpetrusha rpetrusha merged commit 09d36c8 into dotnet:master Nov 29, 2016
@rpetrusha rpetrusha deleted the lambdas branch January 18, 2017 22:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants