Tag Archives: Lambda

Lambda: simplify method calls

There is important part of good programmers skills – ability to detect duplicity. Over years I have developed it for various situations. But recently I have added new situation – duplicity in calling methods with many parameters. And especially with many parameters in local scope. Take a look on following example:

package test;

import java.awt.Graphics;

public class NaiveRenderer {
	
	public void render(Graphics g, int paramA, boolean paramB, double paramC, String paramD) {
		int calculatedA = paramA+42;
		
		if (paramA<100) {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, -1.0);
		} else if (paramA<10) {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, -0.2);
		} else if (paramA==0) {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, 0.0);
		} else if (paramA>100) {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, 1.0);
		} else if (paramA>10) {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, 0.2);
		} else {
			renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", calculatedA, 0.0);
		}
	}
	
	public void renderSubpart(Graphics g, boolean paramB, double paramC, String paramD, int calculatedA, double calculatedB) {
		//...actual code
	}
}

Obviously, there is huge duplicity in renderSubpart calls. Calculation of some parameters is repeated many times. Let’s improve it:

package test;

import java.awt.Graphics;

public class BetterRenderer {
	
	public void render(Graphics g, int paramA, boolean paramB, double paramC, String paramD) {
		int calculatedA = paramA+42;
		
		boolean newParamB = !paramB;
		double newParamC = paramC*22.3;
		String newParamD = paramD+" oh";
		
		if (paramA<100) {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, -1.0);
		} else if (paramA<10) {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, -0.2);
		} else if (paramA==0) {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, 0.0);
		} else if (paramA>100) {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, 1.0);
		} else if (paramA>10) {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, 0.2);
		} else {
			renderSubpart(g, newParamB, newParamC, newParamD, calculatedA, 0.0);
		}
	}
	
	public void renderSubpart(Graphics g, boolean paramB, double paramC, String paramD, int calculatedA, double calculatedB) {
		//...actual code
	}
}

Hm. So we have bloated scope by three new local variables. And we have to name it. Plus there is still problem with many similar calls to the renderSubpart. But only one parameter varies. Let’s improve that:

package test;

import java.awt.Graphics;

public class EvenBetterRenderer {
	
	public void render(Graphics g, int paramA, boolean paramB, double paramC, String paramD) {
		double calculatedB;
		
		if (paramA<100) {
			calculatedB = -1.0;
		} else if (paramA<10) {
			calculatedB = -0.2;
		} else if (paramA==0) {
			calculatedB = 0.0;
		} else if (paramA>100) {
			calculatedB = 1.0;
		} else if (paramA>10) {
			calculatedB = 0.2;
		} else {
			calculatedB = 0.0;
		}
		
		renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", paramA+42, calculatedB);
	}
	
	public void renderSubpart(Graphics g, boolean paramB, double paramC, String paramD, int calculatedA, double calculatedB) {
		//...actual code
	}
}

So now we reduced number of added local variables to one. Great, but I don’t like decoupling of condition and method call. Block of condition just set calculatedB which is later used for calling renderSubpart. Can’t we improve that?

I realized that I can wrap parameters into local lambda function like this:

package test;

import java.awt.Graphics;
import java.util.function.Consumer;

public class LambdaRenderer {
	
	public void render(Graphics g, int paramA, boolean paramB, double paramC, String paramD) {
		Consumer<Double> renderSubpartLambda = (calculatedB)->renderSubpart(g, !paramB, paramC*22.3, paramD+" oh", paramA+42, calculatedB);
		
		if (paramA<100) {
			renderSubpartLambda.accept(-1.0);
		} else if (paramA<10) {
			renderSubpartLambda.accept(-0.2);
		} else if (paramA==0) {
			renderSubpartLambda.accept(0.0);
		} else if (paramA>100) {
			renderSubpartLambda.accept(1.0);
		} else if (paramA>10) {
			renderSubpartLambda.accept(0.2);
		} else {
			renderSubpartLambda.accept(0.0);
		}
	}
	
	public void renderSubpart(Graphics g, boolean paramB, double paramC, String paramD, int calculatedA, double calculatedB) {
		//...actual code
	}
}

So I have defined renderSubpartLambda that receives single varying parameter and fill all other parameters that shares value over all calls. This is possible because Lambda function, unlike methods, have access to the local scope (parameters, local variables). Lambda is then executed from exact position withing condition blocks with only with single important parameter.

This technique is usable in all situations where it would be hard to define helper method because number of passed parameters would be too high. Btw. this solution is language independent – I have used it in JavaScript too.

Advertisements

Execution limiter using lambda

Execution limiter class may help in situations when something must be executed only once per specified time. Use cases:

  • Computing large data and want to print progress only every 10 seconds
  • Inputs are changing often but you do not wan’t to calculate result more often than once per second

Typical is to use variable storing time stamp of last execution and condition not allowing execution sooner than X. But that is not truly encapsulated solution, right? I use helper class, usage is following:

ExecutionsLimiter limiter = new ExecutionsLimiter(1000, false);
for (int i=0;i<10000000;++i) {
    limiter.tryExec(()->{
        //printed at most once per second
        System.out.printf("quot;Current progress is %d\n", i);
    })

    calcHeavyStuff(i);
}

Class itself looks like:

public class ExecutionsLimiter {
    private long lastRepeatTimestamp;
    private long intervalMsec;

    public ExecutionsLimiter(long intervalMsec, boolean mayExecImmediatelly) {
        this.intervalMsec = intervalMsec;
        this.timeSuplier = timeSuplier;

        reset(mayExecImmediatelly);
 }

 public void tryExec(Runnable block) {
     long currentTimestamp =System.currentTimeMillis();

     if (currentTimestamp - lastRepeatTimestamp > intervalMsec) {
         lastRepeatTimestamp = currentTimestamp;
         block.run();
     }
 }

 public void reset(boolean mayExecImmediatelly) {
      lastRepeatTimestamp = mayExecImmediatelly ? Long.MIN_VALUE : System.currentTimeMillis();
 }
}

There is also method reset(). It may be used for use case like:

  • Process files in directories and print current file every 5 seconds
  • Print at least one file per directory

In that case it may happen that second request won’t be fulfilled when processing time of some directories will be less than 5 seconds. Simple call limiter.reset(true) when entering directory will reset limiter and first tryExec will pass.

Using this tool, you can get rid of conditions in your code and make it cleaner and easier to understand.