Extract Action<> and Func<>
After reading about Functional Programming, I've come to realize that I often enter this situation.
FindXinYAndDoZ(A)
-->Y.FindXAndDoZTo(A)
-->Iterate something in Y based on A
-->If X
--->Do Z to X
Now, When I want to implement FindXinYAndDoWTo(A)
Then, I suddenly realize that my code above mixes the action of finding something and what to do with it once I have found it.
I should have passed Z as an Action<X> instead.
If I have this c# code:
private void FindAndDeletePersonByName(data d, string name ) // Yeah, I know linq. This is for example.
{
foreach(person p in data.persons)
{
if (p.Name==name)
p.Delete();
}
}
As Time progresses, there are two things I may want to change while reusing the rest: Either the comparison predicate or the action of deleting.
If I select the p.Name==name and choose "Introduce variable", I am given a bool type because that is the return type of the selected expression.
But what I really want to do, is to get a Func<Bool> expressed as a lambda expression:
Func<bool> predicate = ()=>p.Name==name;
and I wish to extract "name" turning the declaration into
Func<string,bool> predicate = (theName)=> p.Name==theName;
...so that I will be able to either extract the whole Func as a parameter, implement it as a strategy pattern or hardcode it differently in subclasses.
A prime objective of object orientation is to separate what changes from what stays the same. By making lambdas a first class citizen, I think resharper could do wonders.
Please sign in to leave a comment.
Hello Tormod,
Did you try selecting expression you'd like to "functionalize" and trying
to introduce parameter? It has option to create func/action.
Sincerely,
Ilya Ryzhenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
TS> After reading about Functional Programming, I've come to realize
TS> that I often enter this situation.
TS>
TS> FindXinYAndDoZ(A)
TS> -->Y.FindXAndDoZTo(A)
TS> -->Iterate something in Y based on A
TS> -->If X
TS> --->Do Z to X
TS> Now, When I want to implement FindXinYAndDoWTo(A)
TS>
TS> Then, I suddenly realize that my code above mixes the action of
TS> finding something and what to do with it once I have found it.
TS>
TS> I should have passed Z as an Action Func<string,bool> predicate = (theName)=> p.Name==theName;
TS>
TS> ..so that I will be able to either extract the whole Func as a
TS> parameter, implement it as a strategy pattern or hardcode it
TS> differently in subclasses.
TS>
TS> A prime objective of object orientation is to separate what changes
TS> from what stays the same. By making lambdas a first class citizen, I
TS> think resharper could do wonders.
TS>
TS> ---
TS> Original message URL:
TS> http://devnet.jetbrains.net/message/5271988#5271988
At least I think I did.
public void Refactoring_Test()
{
System.Environment.SetEnvironmentVariable("TestVariable", "TestValue");
}
I've tried to mark the whole line and just the expression (leaving out the semicolon).
It says "return type is void".
If I use "Refactor this", then the options are introduce variable and extract method.
Can you refactor the above to a method that accepts Action as a parameter?
public void Refactoring_Test(Action<string,string> theAction)
{
theAction("TestVariable", "TestValue");
}
or even just
public void Refactoring_Test(Action theAction)
{
theAction();
}
If so, how?
I believe for void methods, no. I'll check it tomorrow.
Sincerely,
Ilya Ryzhenkov
JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"
IR> At least I think I did.
IR>
IR> public void Refactoring_Test()
IR> {
IR>
IR> System.Environment.SetEnvironmentVariable("TestVariable",
IR> "TestValue");
IR> }
IR> I've tried to mark the whole line and just the expression (leaving
IR> out the semicolon).
IR>
IR> It says "return type is void".
IR>
IR> If I use "Refactor this", then the options are introduce variable
IR> and extract method.
IR>
IR> Can you refactor the above to a method that accepts Action as a
IR> parameter?
IR>
IR> public void Refactoring_Test(Action<string,string>
IR> theAction)
IR> {
IR> theAction("TestVariable", "TestValue");
IR> }
IR> or even just
IR>
IR> public void Refactoring_Test(Action theAction)
IR> {
IR> theAction();
IR> }
IR> If so, how?
IR>
IR> ---
IR> Original message URL:
IR> http://devnet.jetbrains.net/message/5271995#5271995
Sound good. Looking forward to your answer.
Naturally this works:
public void test()
{
int p = returnSomething();
}
private int returnSomething()
{
int n;
if (Environment.GetEnvironmentVariable("SomeTest").Length > 0)
n = 1;
else
n = 2;
return n;
}
Here I can extract the predicate like this
public void test()
{
int p = returnSomething(Environment.GetEnvironmentVariable("SomeTest").Length > 0);
}
private int returnSomething(bool b)
{
int n;
if (b)
n = 1;
else
n = 2;
return n;
}
.....or I can choose to not include " > 0" in the selection, which will give an int as parameter type.
but given this:
public void test()
{
int p = returnSomething();
}
private int returnSomething()
{
int n=3;
if (Environment.GetEnvironmentVariable("SomeTest").Length + n > 0) // NOTE that I am including n in the expression
n = 1;
else
n = 2;
return n;
}
...then I am actually looking to extract a parameter of type Func<int,bool>