c# lambda expression with for loop - c#

I'm using this code to build my 3d surface plot in each point, but I have a problem that I need to parametrize my function so t variable will be looped from 0 to T value, but I can't figure it out how can I do it inside the delegate?
edited the first block for more clarity:
/*this is code for building 3d surface plot, parameter delegate is counting Z
value in each (x, y) point.
x, y are axis variables. t is constant here*/
new ILPlotCube()
{
new ILSurface((x, y) => (float) (1/(x+y+t))
}
Resulting pseudocode is something like:
float functionValue = 0;
for (double t = 0; t < T; t + deltaT)
{
/*t is loop parameter here*/
functionValue += (float) (1/(x+y+t));
}
return functionValue;

If you don't need an Expression Tree, then it should be:
Func<float, float, float> func = (x, y) =>
{
float functionValue = 0;
for (double t = 0; t < T; t += deltaT)
{
/*t is loop parameter here*/
functionValue += (float)(1 / (x + y + t));
}
return functionValue;
};
Note that I had to change the t + deltaT adder of the for
From there you can
new ILSurface(func);
This is a statement lambda, because it uses { ... } code after the =>. See https://msdn.microsoft.com/library/bb397687.aspx statement lambdas

Related

Value Tuple initialization is counter-intuitive

In the Sunday evening I have been watching some conferences this time I get hands on this one Conference Link
Where I found out pretty interesting think there is simple code example:
struct Point
{
private double x;
public double X { get => x; set => x = value; }
private double y;
public double Y { get => y; set => y = value; }
public Point(double x, double y) => (this.x, this.y) = (x, y);
public void SwapCode() => (X, Y) = (Y, X);
}
In Main:
var point = new Point(10.0, 11.0);
Console.WriteLine($"x: {point.X}, y: {point.Y}");
point.SwapCode();
Console.WriteLine($"x: {point.X}, y: {point.Y}");
And there is output of this :
x: 10, y: 11
x: 11, y: 10
So there is some questions:
How does it works ?
What I mean by that is Tuples should be translate into Tuple<T, K> which should be initialize with copy of the values but there it assign values to the variables at least for me it's kind of counter intuitive.
And i wonder if it's just sugar syntax think or there is happen some magic under this what make perfect sense but I can't spot it out?
Firstly structs should be immutable. Even though you can do this, you probably shouldn't.
Secondly, your SwapCode is actually doing this, as seen here.
public void SwapCode()
{
double num = Y;
double num2 = X;
double num4 = X = num;
num4 = (Y = num2);
}
Yeah, it's a little strange. However, it's just a little syntactic magic introduced in C#7. What it is actually doing is using a deconstruct method (the terminology .Net uses) to provide a set of out arguments for each of the params you want to extract. In this case, it's the properties/field you supplied!
To see it a little clearer, consider these two functionally equivalent code blocks
(int x, int y) asd = (1, 2); // create a Value Tuple
(int x, int y) = asd; // deconstruct it
(x, y) = (x, y); // assign to the deconstructed type
// All the above now has the swapped values
// they are all pointing to the same variables/memory
// You could even take this further by
x = 10;
y = 11;
// Once again, x and y, asd, and (x, y) all have the same values
// Because they are the same
// ----------------------------------------------------
int x = 1;
int y = 2;
(x, y) = (y, x); // we are just deconstructing our original variables
// All the above now has the swapped values
// they are all pointing to the same variables/memory
Note : As you can see, this is also a slightly more succinct way of swapping 2 variables as you don't have to use a temp variables, your friendly CLR does it for you
Anyway, you shouldn't be doing this with a struct anyway, they really should be immutable for various reasons

How to make a struct component a variable?

Not sure I am asking this right or this even possible.
I feel to explain my question it is best to ask right in the code at the relevant places so please see my comments in the snippet below.
I wonder how to achieve this without building a new list of values for each I iteration. I feel this should not be necessary.
The bigger picture of this loop is to plot individual dimensions of 3D points to three new 2D plots of these. Hope that makes sense.
for (int i = 0; i < 3; i++) // 3 iterations (X,Y;Z)
{
// what here? how to make the data component of Vector3D a variable
for (int k = 0; k <= Points.Count - 1; k++)
{
Vector2D TL = new Vector2D();
TL.x = ((1 / (float)FrameCount.Sum()) * k);
TL.y = Points[k].x; // on i = 0 want Points[k].x
// on i = 1 want Points[k].y
// on i = 2 want Points[k].z
TimelinePoints.Add(TL); // just collect to a flat list for now
}
}
One option would be to have an array of extraction functions that you could apply to points. You can then use the LINQ Select overload that accepts a Func<TInput, int, TOutput> to generate a sequence of the values you want to add, and add it to TimeLinePoints that way.
// Possibly store this in a static variable somewhere
var extractors = new Func<Point, float>[] { p => p.x, p => p.y, p => p.z };
// Just do this once; store the result as a float for simplicity when dividing later.
float frameSum = FrameCount.Sum();
foreach (var extractor in extractors)
{
TimeLinePoints.AddRange(Points.Select((point, index) =>
new Vector2D(index / frameSum, extractor(point));
}
(You could go even further using SelectMany potentially, but that's where I'd start...)
A considerably more pedestrian approach compared to Jon Skeet's answer would be to modify the Point struct to include an indexer, assuming that is an option:
public struct Point
{
float x;
float y;
float z;
public float this[int index]
{
get
{
switch (index)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
}
}
Then you could assign the proper field according to the value of your loop counter, like so:
for (int k = 0; k < Points.Count; k++)
{
Vector2D TL = new Vector2D();
TL.x = ((1 / (float)FrameCount.Sum()) * k);
TL.y = Points[k][i];
TimelinePoints.Add(TL); // just collect to a flat list for now
}
The alternate way is to use Linq to archive this:
Points
//foreach point create 3 Vector2D with X, Y and Z coordinate
.SelectMany((p, index) => new []
{
new Vector2D(index / frameSum, p.X),
new Vector2D(index / frameSum, p.Y),
new Vector2D(index / frameSum, p.Z)
})
//unfurl IEnumerable<IEnumerable<Vector2D>> to IEnumerable<Vector2D>
.Select(v => v)
.ToList();

Get name of delegate method

Out of curiosity I've been looking into delegate methods and am interested in getting the name of the current delegate method that is being used (just for fun, really).
The code I have is as follows (with the current/desired outputs):
private delegate int mathDelegate(int x, int y);
public static void Main()
{
mathDelegate add = (x,y) => x + y;
mathDelegate subtract = (x,y) => x - y;
mathDelegate multiply = (x,y) => x * y;
var functions = new mathDelegate[]{add, subtract, multiply};
foreach (var function in functions){
var x = 6;
var y = 3;
Console.WriteLine(String.Format("{0}({1},{2}) = {3}", function.Method.Name, x, y, function(x, y)));
}
}
/// Output is:
// <Main>b__0(6,3) = 9
// <Main>b__1(6,3) = 3
// <Main>b__2(6,3) = 18
/// Desired output
// add(6,3) = 9
// subtract(6,3) = 3
// multiply(6,3) = 18
Does anyone know of any way(s) I could achieve this? Thanks.
Your methods are anonymous delegates, so the the compiler gives each of them a name that doesn't have any meaningful connection back to the variable name. If you want them to have better names then make them actual methods:
public int Add(int x, int y)
{
return x + y ;
}
etc. Then reference them by name:
var functions = new mathDelegate[]{this.Add, this.Subtract, this.Multiply};
Note that the this. is optional but illustrates that they are class members rather than local variables.

Return expression instead result

If I have function like this
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
is it possible to modify it somehow, to not return result immediately only some object which is expression and then evaluate it this way:
var expression = GetExpression(1,2,3);
double result = expression.Execute() or expression.Evaluate()
other words just return function
?
Yes!
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
use as:
var expression = GetExpression(1,2,3);
double result = expression();
Well, you could use delegates, and return a Func<double>:
Func<double> GetExpression(int x, int y, int z)
{
return () => x * y + z;
}
var expression = GetExpression(1,2,3);
double result = expression(); // Or expression.Invoke()
Is that what you were looking for?
Now each time you call expression() it will execute the code in the lambda expression. You can observe that if you use code which doesn't just return the same value each time. For example:
Func<int> GetExpression()
{
Random rng = new Random();
return () => rng.Next(10);
}
var expression = GetExpression();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(expression());
}
That will print 10 random numbers in the range [0, 10). Note that this will only create one instance of Random (avoiding a common problem) - each time you call expression() it will call the Next() method on the same instance. The constructor for Random is called in the "normal" part of the method - it's not in the lambda expression. So that gets executed when you first call the GetExpression method (even if you never call expression() afterwards).
Note however that the arguments to your GetExpression were still passed by value though, and are captured by the lambda express. So consider this:
Func<int> GetExpression(int a, List<int> b)
{
return () => a + b.Count;
}
int x = 10;
List<int> list = new List<int> { 1, 2, 3 };
var expression = GetExpression(x, list);
Console.WriteLine(expression()); // 13
x = 20;
list.Add(100);
Console.WriteLine(expression()); // 14
Here the value of the list variable has been captured, so changes the the object that the value refers to are visible in the lambda expression, but changes to the x variable itself are not visible in the lambda expression. (Likewise if you had list = new List<int>(); that change wouldn't be visible...
To expand on Jon Skeet's answer, about capturing variables, if you didn't want to, you could do something like this:
double GetExpression(int x, int y, int z)
{
return x * y + z;
}
Func<int, int, int, double> expression = GetExpression;
for (int i = 0; i < 10; i++)
Console.WriteLine("{0}", expression(i, i+1, i+2));
Which avoids modifying the existing code (in case you wanted to point to a function you didn't have control over), and avoids capturing values outside of the lamda.

'List<T>.ForEach()' and mutability

I want to translate all points in a List<T>. This works:
for (int i = 0; i <PolygonBase.Count; ++i)
{
PolygonBase[i] = PolygonBase[i] + MousePos;
}
But using List<T>.ForEach doesn't:
PolygonBase.ForEach(v => v += MousePos);
Ideas?
Your current code is simply re-assigning the local variable v to a new value - it doesn't refer back to the original value in the list. It's the equivalent of writing:
foreach(int v in PolygonBase)
{
v += MousePos;
}
To write back to the original value, use ConvertAll:
PolygonBase.ConvertAll(v => v += MousePos);

Categories

Resources