Just remember the saying about programming in the springtime:
March comes in like a Linq and out like a Lambda
Just remember the saying about programming in the springtime:
March comes in like a Linq and out like a Lambda
The point of a lamba in this case is to pass a function instead of piece of data or a field name. You could implement it the other ways you suggest, but they would not be as flexible. Actually, this works just fine:
List<float> numbers = new List<float> { 43.68F, 1.25F, 583.7F, 6.5F };
float sum = numbers.Sum();
Console.WriteLine("The sum of the numbers is {0}.", sum);
/*
This code produces the following output:
The sum of the numbers is 635.13.
*/
Because the lambda is shorthand for a function, you can easily add complexity
OrderHead.OrderDtl.Sum(x => x.OrderLineQty * x.UnitPrice)
(Pardon the incorrect names writing on the fly)
You might ask why can’t you still just write:
OrderHead.OrderDtl.Sum(OrderLineQty*UnitPrice)
And I think that mostly comes back to what @Banderson is talking about with ambiguous items, particularly because lambdas capture outer variables
@Banderson’s point is definitely valid
RcvDtl is a collection of something. Count() is an extension method,
and while it may be considered by some to be LINQ, it’s not really.
While dsReceipts.RcvDtl.Sum(ThisTranQty) could technically be written as an extension method, it would not logically fit with how you select other things in LINQ.
C# is strongly-typed language: it won’t even try to sum RcvDtl objects, unless you tell it how to do that. The Lambda describes what you want to happen by returning a summable value (e.i., TranQty)
You could define a Func to do that:
Func<Erp.Tablesets.RcvDtlRow, decimal> ThisTranQty = (rcvDtl) => rcvDtl.TranQty;
Then that statement becomes valid and does what you expect.
Otherwise, it looks (to the compiler) like you’re sending a variable that has not been defined.
The commands are read linearly … so when it gets to RcvDtl.ThisTranQty, the compiler says “Hey! RcvDtlTable doesn’t have a property or extension method by that name … I don’t know what to do with this!” … so it won’t even try.
Started a tools section:
According to Wikipedia:
In computer programming, a type system is a logical system comprising a set of rules that assigns a property called a type (for example, integer, floating point, string) to every term (a word, phrase, or other set of symbols). Usually the terms are various language constructs of a computer program, such as variables, expressions, functions, or modules.[1] A type system dictates the operations that can be performed on a term. For variables, the type system determines the allowed values of that term
That’s about as clear as mud isn’t it?
Ok, English time, with examples.
Assuming you’ve read the section on variables, let’s proceed.
//[Type] [Variable Name] [Operator] [Value]
//The value of this variable is of Type "string" (text)
string donnaSummer = "She works hard for the money.";
//[Type] [Variable Name] [Operator] [Value]
//The value of this variable is of Type "int" (Integer)
int hitchhiker = 42;
//Here is a function
//[Access Modifier] [Return Type] [Function(Method) Name] [ Input Parameters ([Type] [Variable Name]) ]
//You'll see two types in the signature, Return Type is bool (Boolean {true/false}), and the Input Parameters takes a string (text)
private bool AreYouRidiculous(string message)
{
//Variable
//[Type] [Variable Name] [Operator] [Value]
bool output = true;
//Something we do
//Console WriteLine is a method that takes a TYPE of string (There are exceptions, they are not relevant here.)
//[Method]( Input Parameters [Type -> string])
Console.WriteLine(message);
//This is a function, so we must have a return
//This function must return a bool (Boolean)
//We defined the "output" variable earlier as Type "bool", so we are good.
//Return [Type]
return output;
}
Types are not only simple types, like strings or numbers. They can also be objects, and depending on language, other constructs.
//[Type] [Variable Name] [Operator] [Keyword] [Type]( [Constructor Values] )
//This Type is an "object", specifically, an object of Type "DataTable".
DataTable dt = new DataTable("MyCollectionOfPeopleToAnnoy");
//This is a class object. It is an object. It is also a Type, called "Groot"!
//[Access Modifier] [objectType: class][Name & Type]
public class Groot
{
// [Type] [Special Keyword] [Variable Name] [Operator] [Value]
// The "Special Keyword" here, "const", just makes this value immutable,
// which means it cannot be changed... it is a "constant" by definition. This is set at compile time.
private const string speech = "I am Groot.";
//[Access Modifier] [Return Type] [Function(Method) Name] [Input Parameters]
public void Speak()
{
//[Method]( Input Parameters [Type -> string])
Console.WriteLine(speech);
}
}
Different languages have differing Type “Systems”, but as for C#, here is a table that explains some of the “Base” Types.
Type | Description | Value |
---|---|---|
byte | 8-bit unsigned integer | 0 to 255 |
sbyte | 8-bit signed integer | -128 to 127 |
short | 16-bit signed integer | -32,768 to 32,767 |
ushort | 16-bit unsigned integer | 0 to 65,535 |
int | 32-bit signed integer | -2,147,483,648 to 2,147,483,647 |
uint | 32-bit unsigned integer | 0 to 4,294,967,295 |
long | 64-bit signed integer | -9,223,372,036,854,770,000 to 9,223,372,036,854,770,000 |
ulong | 64-bit unsigned integer | 0 to 18,446,744,073,709,551,615 |
float | 32-bit Single-precision floating point type | -3.402823e38 to 3.402823e38 |
double | 64-bit double-precision floating point type | -1.79769313486232e308 to 1.79769313486232e308 |
decimal | 128-bit decimal type for financial and monetary calculations | (+ or -)1.0 x 10e-28 to 7.9 x 10e28 |
char | 16-bit single Unicode character | Any valid character, e.g. a,*, \x0058 (hex), or\u0058 (Unicode) |
bool | 8-bit logical true/false value | True or False |
object | Base type of all other types. | |
string | A sequence of Unicode characters | |
DateTime | Represents date and time | 0:00:00am 1/1/01 to 11:59:59pm 12/31/9999 |
I hope this helps, I’m sure it can be expanded… (by someone )
Back on the subject of lambdas…
We’ve already covered Expression lambdas here, and the posts above and below, so let’s move on to Statement lambdas.
You use statement lambdas, when you need to do more than one statement, or do some more complex logic than an expression statement.
For example:
//using LINQ here (I just make this crap up, who knows if this is remotely correct.)
string someString = Db.PerCon.Where(p => p.PerConID == "ROCK").FirstOrDefault()
.Select(str =>
{
string t1 = p.Name.ToUpper();
string t2 = p.FirstName.ToLower();
string t3 = p.LastName.ToUpper();
if(t3.Length() > t2.Length())
{
return "Yo";
}
else return "Bollocks";
}); //I said it was gibberish, but it's logic.
//or an Event, in a form: (try not to do this)
UD01Form.Shown += (sender, eventArgs) =>
{
someClassLevelVariable = ((Control)sender).Name;
MessageBox.Show(JsonConvert.SerializeObject(eventArgs, Formatting.Indented));
};
And that’s pretty much it. It’s a method, where you can do what you want in it.
If y’all want more on this one, please ask a specific question, and I’ll see if I can answer it, or prod me with a needed example.
Aha! Got one:
//Returning a list of new object from LINQ AND manipulating the output with a filter.
//This is bs code, don't do this lol
var listOfPeople = Db.PerCon.Where(p => p.LastName.StartsWith("Q"))
.Select(p =>
{
var person = new
{
name = p.FirstName + " " + p.LastName,
hasMiddle = !String.IsNullOrWhiteSpace(p.MiddleName)
};
if(person.HasMiddle) return new
{
name = p.FirstName + " " + p.MiddleName + " " + p.LastName,
hasMiddle = !String.IsNullOrWhiteSpace(p.MiddleName)
}
else return person;
}).ToList();
My examples suck today, but I hope it’s clear.
I’m back. Sorry in advance.
I’m still lost on the lambdas, but I am trying to figure out how to contribute here while not being too much of “that guy.”
So, you can skip this paragraph, but for context, I’m the widget guy. I’m low-code or die. Now, that still means some code, of course, and that’s why I am here infecting this thread. When I need code, it’s almost always going to be a one-line snippet that I can just hurl into a Set Variable widget, or worst-case, a few lines in a code block. I’m not looking to create my own classes or delegates or what have you; I can go as far as a Func<>
and that’s about it.
With that, I have read the replies here several times and googled about lambdas, but nothing is connecting for me.
Am I beneath the intelligence of this thread? Probably. But then there’s “What is a variable,” and like the Jeopardy viewer who gets one question right and thinks, “I could totally be on that show,” I too feel like I can hang with the crew here.
So, all of that is to preface the simple point of: I simply don’t get it with lambdas.
Here’s what I am piecing together:
return
in there. But it’s essentially an expanded version of #1.I think it’s
Db.PerCon.Where((p => p.PerConID) == "ROCK")
I don’t even know if that would work or not, but my point is, is that what is logically happening?
But my most fundamental question is: What kind of thing is a lambda returning? Is it a list? Is it more like a representation of a field in a table?
I have to run, but that’s what I have so far. Thanks to anyone that might still be bearing with me.
I keep telling you…
Low-Code / Widgets / Bobbins → It’s Code
Low-Code / Widgets / Bobbins → It’s Code
Low-Code / Widgets / Bobbins → It’s Code
Post away, fill it up, teach us O’ wise one, just don’t ask me to touch your widgets…
You’ll get no hate from me, just me silently (openly) judging your choices.
This thread, is more about mindset and problem solving, than technique, even though technique is the way it’s being presented.
I don’t believe you can access items outside your scope. In the following case:
ds.table.Where(x => x.field1 == value).Sum(y => y.field2)
“y” cannot be any row (not really a row, but whatever) that was already excluded in the Where call.
SIdenote: I didn’t have to use “y” in the second lambda. I could have used “x” in both, since the x variable is contained within the scope of the call. However, I always switch up the names because x & y represent two different things. YMMV.
Every good fantasy or scifi story has one character that’s a proxy for the audience, who doesn’t know the backstory and has to be there so everyone can slow down and explain things in plain English.
Those characters are vital and so are you.
You got it. (mostly) Sometimes you need return, sometimes not, depending on what you are doing.
Been working my whole life on getting one, and I don’t either. Cope.
No, you can always see items in your scope, and any enclosing scopes (scopes you are inside of)
Ok no, it’s
Db.PerCon.Where(p => p.PerConID == "ROCK")
That says Using the Db context, and from the PerCon table (object),
select objects Where match some criteria.
That criteria being defined by a lambda.
The lambda itself says: Define variable p, where p is being fed from the Db.PerCon rows (it is the rows (Maybe we need to define what extension methods are, that would make some of this clearer.)), and then creates an anonymous function that returns true or false → p.PerConID == "ROCK"
p => p.PerConID == "ROCK"
//is equivalent to
if(PerConID == "ROCK") return my row
It depends on the context.
In a where clause in linq, it’s true or false.
In a select statements, it’s fields or new objects.
In other contexts, you may return nothing at all.
Lambdas are not LINQ, but LINQ uses a lot of lambdas, don’t confuse the two.
Remember, a lambda is just a function. Another name for them is Anonymous functions. Its just a more compact, short hand way of creating a function that you are only using in one place. If you understand a regular function, the only things to get hung up on are the syntax and the fact that the variable scope is a little different than a full fledged function.
I think a more relevant example is calls multiple methods in one service in ERP.
CallService<Erp.Contracts.EngWorkBenchSvcContract>(ewb =>
{
foreach (var method in methods)
{
ewb.ClearAll(...);
ewb.GetDetailsFromMethods(...);
//Parameters removed from methods for brevity.
}
});
You can write this exactly the same as two lambda expressions and it will do what you want. It’s just more verbose and maybe has an overhead cost for repeatedly connecting/disconnecting from the service. Not sure about that part.
The LINQ methods all call an internal (invisible) method called MoveNext after every iteration.
So you have a list (essentially) of PerCon objects, it starts with the first one and runs the anonymous function:
p = PerCon #1, if p.PerConID == “ROCK” add it to the results of Where, now MoveNext
p = PerCon #2, if p.PerConID == “ROCK” add it to the results of Where, now MoveNext
until you reach the end of the content of the DB.PerCon table and you have a new set of data populated by essentially moving through the list and applying the same rules against each line
I think the next topic is “Extension Methods”.
Ok, imagine this little function (Func<T>) is a real one, and is much longer, and this will make more sense to you.
Anyway…
I had a function (really a Func<T>) that was very long and hard to read. So I used a Tuple so it would be clearer. Yes one can argue that to some this would be less clear, but just sharing the technique in case someone needs it.
//Snippet (Tuples & Func<T>...)
//Kinda funky
Func<string, string, string, string, string, string, string, bool> SomeConfusingFunction = (a, b, c, d, e, f, g) =>
{
if(a == e)
{
return false;
}
else
{
return true;
}
};
//Call like so...
bool myBool1 = SomeConfusingFunction("I", "am", "a", "man", "of", "constant", "sorrow");
//Slightly better... Notice parenthesis in Func< ( [inType1][inName1], [inType2][inName2] ... ) , [outType]>
//This is a Tuple, so we are actually only passing one object, the "tuple" named "input"
Func<(string a, string b, string c, string d, string e, string f, string g), bool> SomeSlightlyLessConfusingFunction = (input) =>
{
if(input.a == input.e)
{
return false;
}
else
{
return true;
}
};
//Call like so... (Notice double parenthesis - You are actually passing a Tuple)
bool myBool2 = SomeSlightlyLessConfusingFunction(("I", "am", "a", "man", "of", "constant", "sorrow"));
that would be
const bool bandersonIsCranky = true;
I’d like to hope you aren’t cranky all the time, and if that’s the case then you would be variably cranky
He is cranky all the time, but it’s usually the good cranky.