Transform a delegate to a Expression Tree - c#

I wonder if you can create and modify a Expression Tree out of a existing delegate.
Kinda like
public void Foo() {
Console.WriteLine(1000);
}
....
Expression exp = Foo.GetExpression();
//Now do something what changes 1000 to 2000...
So I would like to reverse engineer a allready excisting Method.
My problem is that I have a construction like this:
var acts = new Action[20];
for (int i = 0; i != 20; i++)
acts[i] = () => { Console.WriteLine(i); };
and by the way C# works all acts do the same (prints 20). But I want that that
acts[5]()
print 5
acts[11]()
prints 11 and so on.
So I need to compute 20 different delegates and I wonder what's a "nice" approach to do so. Of course I could just write:
acts[0] = () => Console.WriteLine(0);
acts[1] = () => Console.WriteLine(1);
acts[2] = () => Console.WriteLine(2);
acts[3] = () => Console.WriteLine(3);
....
But that's not a good approach in my eyey...

Anton's solution is nearly right, but he's copying the variable at the wrong time. You want this:
for (int i = 0; i != 20; i++)
{
int tmp = i;
acts[i] = () => Console.WriteLine(tmp);
}
This way the captured variable is tmp rather than i - and while there's only one i variable, whose value changes on each iteration, you get a "new" tmp variable for each iteration.
See Eric Lippert's blog posts on the topic (part 1, part 2) for more details.
(To answer the original question as per the title - you can't create an expression tree from a delegate in a useful way here - the only expression tree you can create is one which just calls the original delegate.)

Rewrite it like this:
for(int i = 0; i != 20; i++)
{
var x = i;
acts[i] = () => { Console.WriteLine(x); };
}

Related

c# create a .forEach() Method using actions [duplicate]

This question already has answers here:
Why does assignment to parameter not change object?
(4 answers)
Closed 8 months ago.
I'm trying to create a method that loops through an array and executes some actions I wrote with a lambda expression. Somehow I don't think I understood how to use actions correctly because my code just results in a bunch of "null" objects.
Does somebody know what I am doing wrong?
public void forEach(Action<Neuron> action)
{
for(int i = 0; i < this.Neurons.Length; i++)
{
action(this.Neurons[i]);
}
}
public void CreateNeurons(int AmountOfNeurons)
{
this.Neurons = new Neuron[AmountOfNeurons];
this.forEach(x => x = new Neuron(AmountOfNeurons));
}
In your delegate, setting x = ... only changes the value of that local parameter: it does nothing to the array itself. You would end up with the same problem if you used a for loop like this:
var a = new[] { 1, 2, 3};
for (int i = 0; i < a.Length; i++)
{
var x = a[i];
x = 5; // this does nothing to `a[i]`
}
Notably, a foreach loop would warn you if you tried to do this:
foreach (var x in a)
{
x = 5; // CS1656: Cannot assign to 'x' because it is a foreach variable.
}
This supports Dai's comment: you really shouldn't be defining your own forEach method. There are plenty of better, more idiomatic ways to do anything you'd want to do with a method like this. A foreach construct would have told you exactly what you were doing wrong, for example. And creating an array with a bunch of items is typically simpler with LINQ:
this.Neurons = Enumerable.Range(0, AmountOfNeurons)
.Select(_ => new Neuron(AmountOfNeurons))
.ToArray();

delegate and lambda expression task

could you explain me one example with delegate and lambda expression
List<Func<int>> list = new List<Func<int>>();
for (int i = 0; i < 10; i++)
{
list.Add(() => i);
}
foreach (var func in list)
{
Console.WriteLine(func());
}
I understand, that I have List of refers to methods whithout params and returns Int, but why it returns 10 times max value from loop? How it works? Thx!
It is closure when you do:
(() => i)
The lambda gets the original variable i, not a copy, so you get 10 ten times - because on calling delegate the original value of i is 10 (after loop)
If you change code and add local temp variable you will get 0 1 2 3 4 5 6 7 8 9:
for (int i = 0; i < 10; i++)
{
int j = i;
list.Add(() => j);
}
You can read about closures here:
Closures
When you pass variable inside of delegate's method it is its link, and not it's value that is used inside the delegate.
We create list of functions:
List<Func<int>> list = new List<Func<int>>();
Here we initialize list with functions and every function should use reference to memory where i variable is stored when it's fired :
for (int i = 0; i < 10; i++)
{
list.Add(() => i);
}
Now it is time to fire each function but at this time for loop is already finished executing and i variable holds its final value of 10. Remember that delegate can always find parameter because it holds reference to it. It could not be garbage collected :
foreach (var func in list)
{
// by the time we do it it has value of 10
Console.WriteLine(func());
}
The reason for that is that the lambda () => i captures the local variable i. This means that i will not be evaluated when it is added to the list but when you actually invoke the lambda with ().
At the time this happens in your code (Console.WriteLine(func());) the value of i is already 10 because the for loop has finished.
If you want to avoid this behaviour you have to copy the value of i into a local variable that will not change after the lambda has been created.
for (int i = 0; i < 10; i++)
{
int tmp = i;
list.Add(() => tmp);
}
Actually the lambda expression is a delegate, and you calling it after the loop ends and at that time i has value 10, so when the delegates are getting called, they all have i value 10 as same copy is used due to closure, you will need to write as #Roma suggested for it to work as you expect it to, otherwise it will,
this :
for (int i = 0; i < 10; i++)
{
list.Add(() => i);
}
can be looked as :
int i;
for (i=0; i < 10; i++)
{
list.Add(() => i);
}

Index out of range error when using a list as a parameter for thread start routine

I am writing a C# program that requires giving a thread parameters to a function so that the function will run properly on the separate thread. Specifically one of the parameters is a string name to a file that it is supposed to access. The problem is that I am storing the names of the files in a list and I am accessing the value from the list. However, when I do this I get an index out of range error after one or two threads are created. I think that this is list of strings is my issue, but I know that the index is not out of range.
I am not sure if I am doing something wrong with the way I am passing in the parameters or what else could be wrong.
Here is a sample of my C# code (excluding the code for the functions called):
for (int i = 0; i < 5; i++)
{
surfaceGraphDataNames.Add(String.Format(surfacePlotDataLocation+"ThreadData{0}.txt", i));
try
{
generateInputFile(masterDataLocation);
}
catch
{
MessageBox.Show("Not enough data remaining to create an input file");
masterDataLocation = masterDataSet.Count - ((graphData.NumRootsUsed + 1) * (graphData.Polynomial + 1) - 1);
this.dataSetLabel.Text = String.Format("Current Data Set: {0}", masterDataLocation + 1);
return;
}
try
{
//creates the data in a specific text file I hope
createSurfaceGraph(surfaceGraphDataNames[i]);
//start threads
threadsRunning.Add(new Thread(() => runGnuplotClicks(surfaceGraphDataNames[i], masterDataLocation)));
threadsRunning[i].Start();
}
catch
{
this.graphPictureBox1.Image = null;//makes image go away if data fails
MessageBox.Show("Gridgen failed to generate good data");
}
masterDataLocation++;
}
Looks like that you have to do something like this:
threadsRunning.Add(new Thread(() => {
var k = i;
runGnuplotClicks(surfaceGraphDataNames[k], masterDataLocation)
}
));
The reason is that when you use the variable i, it's not safe because when your i++, and the surfaceGraphDataNames has not been added with new item yet, the exception will throw because your Thread run nearly simultaneously.
Here is the context which leads to the exception:
for(int i = 0; i < 5; i++){
//Suppose i is increased to 3 at here
//Here is where your Thread running code which accesses to the surfaceGraphDataNames[i]
//That means it's out of range at this time because
//the surfaceGraphDataNames has not been added with new item by the code below
surfaceGraphDataNames.Add(String.Format(surfacePlotDataLocation+"ThreadData{0}.txt", i));
//....
}
UPDATE
Looks like that the code above even can't work possibly because the i is increased before the actual ThreadStart is called. I think you can do this to make it safer:
var j = i;
threadsRunning.Add(new Thread(() => {
var k = j;
runGnuplotClicks(surfaceGraphDataNames[k], masterDataLocation)
}
));
Synchronization Attempt:
Queue<int> q = new Queue<int>();
for(int i = 0; i < 5; i++){
//.....
q.Enqueue(i);
threadsRunning.Add(new Thread(() => {
runGnuplotClicks(surfaceGraphDataNames[q.Dequeue()], masterDataLocation)
}
));
threadsRunning[i].Start();
}
I had a problem like this then I use Thread. I was sure that the index is not out of range and this situation not happened if I tried to stop by break-point and then continued.
Try to use Task instead of Thread. It works
The most obvious problem is that you are closing over the loop variable. When you construct a lambda expression any variable references are to the variable itself and not its value. Consider the following code taken from your example.
for (int i = 0; i < 5; i++)
{
// Code omitted for brevity.
new Thread(() => runGnuplotClicks(surfaceGraphDataNames[i], masterDataLocation))
// Code omitted for brevity.
}
What this is actually doing is capturing the variable i. But, by the time the thread starts executing the i could have been incremented several times possibly (and even likely) to the point where its value is now 5. It is possible that the IndexOutOfRangeException is being thrown because surfaceGraphDataNames does not have 6 slots. Nevermind the fact that your thread is not using the value of i that you thought it was.
To fix this you need to create a special capturing variable.
for (int i = 0; i < 5; i++)
{
// Code omitted for brevity.
int capture = i;
new Thread(() => runGnuplotClicks(surfaceGraphDataNames[capture], masterDataLocation))
// Code omitted for brevity.
}

Reversing an ienumerable of lambda functions

I have created an ienumerable of lambda functions using this function
static IEnumerable<Func<int>> MakeEnumerator(int[] values)
{
for (int a = 0; a < values.Length; a++)
{
yield return () => Values[a];
}
}
I cannot then reverse this using LINQ or convert into an array without all the values becoming the last function.
Example code (note this just demonstrates the problem it is not the code in the application):
int[] start = {1,2,3};
IEnumerable<Func<int>> end = MakeEnumerator(start).Reverse<Func<int>>();
foreach (Func<int> i in end)
{
Console.WriteLine(i());
}
I think the problem is in the MakeEnumerator function. How would I modify this to make it work or go about writing a working replacement reverse function.
The problem is that you're capturing the loop variable. All of your delegates are capturing the same variable, so they'll always see the latest value of a... which will be values.Length + 1 by the time you're executing the delegates, in your use cases. You can simply copy it instead:
for (int a = 0; a < values.Length; a++)
{
int copy = a;
yield return () => Values[copy];
}
Alternatively (and preferrably IMO) use a foreach loop, which currently requires the same workaround:
foreach (int value in values)
{
int copy = value;
yield return () => copy;
}
Or better yet:
return values.Select(x => (Func<int>)(() => x));
Or:
Func<int, Func<int>> projection = x => () => x;
return values.Select(projection);
See Eric Lippert's blog post "Closing over the loop variable considered harmful" for more information. Note that the behaviour of foreach may well be changing for C# 4.5.
All of your lambda expressions are sharing the same a variable.
Since you're only calling them after the loop finishes, a is always 3.
You need to give each one its own variable:
for (int dontUse = 0; dontUse < values.Length; dontUse++)
{
int a = dontUse;
yield return () => Values[a];
}
In this code, each lambda expression gets its own a variable (since it's scoped inside the loop), and these separate variables never change.

Why does the same algorithm work in Scala much slower than in C#? And how to make it faster?

The algorithm creates all possible variants of the sequence from variants for each member of the sequence.
C# code :
static void Main(string[] args)
{
var arg = new List<List<int>>();
int i = 0;
for (int j = 0; j < 5; j++)
{
arg.Add(new List<int>());
for (int j1 = i; j1 < i + 3; j1++)
{
//if (j1 != 5)
arg[j].Add(j1);
}
i += 3;
}
List<Utils<int>.Variant<int>> b2 = new List<Utils<int>.Variant<int>>();
//int[][] bN;
var s = System.Diagnostics.Stopwatch.StartNew();
//for(int j = 0; j < 10;j++)
b2 = Utils<int>.Produce2(arg);
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
}
public class Variant<T>
{
public T element;
public Variant<T> previous;
}
public static List<Variant<T>> Produce2(List<List<T>> input)
{
var ret = new List<Variant<T>>();
foreach (var form in input)
{
var newRet = new List<Variant<T>>(ret.Count * form.Count);
foreach (var el in form)
{
if (ret.Count == 0)
{
newRet.Add(new Variant<T>{ element = el, previous = null });
}
else
{
foreach (var variant in ret)
{
var buf = new Variant<T> { previous = variant, element = el };
newRet.Add(buf);
}
}
}
ret = newRet;
}
return ret;
}
Scala code :
object test {
def main() {
var arg = new Array[Array[Int]](5)
var i = 0
var init = 0
while (i<5)
{
var buf = new Array[Int](3)
var j = 0
while (j<3)
{
buf(j) = init
init = init+1
j = j + 1
}
arg(i)=buf
i = i + 1
}
println("Hello, world!")
val start = System.currentTimeMillis
var res = Produce(arg)
val stop = System.currentTimeMillis
println(stop-start)
/*for(list <- res)
{
for(el <- list)
print(el+" ")
println
}*/
println(res.length)
}
def Produce[T](input:Array[Array[T]]):Array[Variant[T]]=
{
var ret = new Array[Variant[T]](1)
for(val forms <- input)
{
if(forms!=null)
{
var newRet = new Array[Variant[T]](forms.length*ret.length)
if(ret.length>0)
{
for(val prev <-ret)
if(prev!=null)
for(val el <-forms)
{
newRet = newRet:+new Variant[T](el,prev)
}
}
else
{
for(val el <- forms)
{
newRet = newRet:+new Variant[T](el,null)
}
}
ret = newRet
}
}
return ret
}
}
class Variant[T](var element:T, previous:Variant[T])
{
}
As others have said, the difference is in how you're using the collections. Array in Scala is the same thing as Java's primitive array, [], which is the same as C#'s primitive array []. Scala is clever enough to do what you ask (namely, copy the entire array with a new element on the end), but not so clever as to tell you that you'd be better off using a different collection. For example, if you just change Array to ArrayBuffer it should be much faster (comparable to C#).
Actually, though, you'd be better off not using for loops at all. One of the strengths of Scala's collections library is that you have a wide variety of powerful operations at your disposal. In this case, you want to take every item from forms and convert it into a Variant. That's what map does.
Also, your Scala code doesn't seem to actually work.
If you want all possible variants from each member, you really want to use recursion. This implementation does what you say you want:
object test {
def produce[T](input: Array[Array[T]], index: Int = 0): Array[List[T]] = {
if (index >= input.length) Array()
else if (index == input.length-1) input(index).map(elem => List(elem))
else {
produce(input, index+1).flatMap(variant => {
input(index).map(elem => elem :: variant)
})
}
}
def main() {
val arg = Array.tabulate(5,3)((i,j) => i*3+j)
println("Hello, world!")
val start = System.nanoTime
var res = produce(arg)
val stop = System.nanoTime
println("Time elapsed (ms): " + (stop-start)/1000000L)
println("Result length: " + res.length)
println(res.deep)
}
}
Let's unpack this a little. First, we've replaced your entire construction of the initial variants with a single tabulate instruction. tabulate takes a target size (5x3, here), and then a function that maps from the indices into that rectangle into the final value.
We've also made produce a recursive function. (Normally we'd make it tail-recursive, but let's keep things as simple as we can for now.) How do you generate all variants? Well, all variants is clearly (every possibility at this position) + (all variants from later positions). So we write that down recursively.
Note that if we build variants recursively like this, all the tails of the variants end up the same, which makes List a perfect data structure: it's a singly-linked immutable list, so instead of having to copy all those tails over and over again, we just point to them.
Now, how do we actually do the recursion? Well, if there's no data at all, we had better return an empty array (i.e. if index is past the end of the array). If we're on the last element of the array of variations, we basically want each element to turn into a list of length 1, so we use map to do exactly that (elem => List(elem)). Finally, if we are not at the end, we get the results from the rest (which is produce(input, index+1)) and make variants with each element.
Let's take the inner loop first: input(index).map(elem => elem :: variant). This takes each element from variants in position index and sticks them onto an existing variant. So this will give us a new batch of variants. Fair enough, but where do we get the new variant from? We produce it from the rest of the list: produce(input, index+1), and then the only trick is that we need to use flatMap--this takes each element, produces a collection out of it, and glues all those collections together.
I encourage you to throw printlns in various places to see what's going on.
Finally, note that with your test size, it's actually an insigificant amount of work; you can't accurately measure that, even if you switch to using the more accurate System.nanoTime as I did. You'd need something like tabulate(12,3) before it gets significant (500,000 variants produced).
The :+ method of the Array (more precisely of ArrayOps) will always create a copy of the array. So instead of a constant time operation you have one that is more or less O(n).
You do it within nested cycles => your whole stuff will be an order of magnitude slower.
This way you more or less emulate an immutable data structure with a mutable one (which was not designed for it).
To fix it you can either use Array as a mutable data structure (but then try to avoid endless copying), or you can switch to a immutable one. I did not check your code very carefully, but the first bet is usually List, check the scaladoc of the various methods to see their performance behaviour.
ret.length is not 0 all the time, right before return it is 243. The size of array should not be changed, and List in .net is an abstraction on top of array. BUT thank you for the point - problem was that I used :+ operator with array which as I understand caused implicit use of type LinkedList

Categories

Resources