Showing posts with label closures. Show all posts
Showing posts with label closures. Show all posts

Saturday, January 05, 2019

Go Gotchas

As I wrote my first non trivial project in Go, I had a few head-scratching moments. Nothing that a quick search could clear up, but worth keeping in mind...

Nil is not nil. 

You may run into that one quickly enough in tests. An instance of an interface can have a nil value but since it carries the interface type information, it does not equal to nil!! A lot has been written about it so make sure to read about it!

Redeclarations

The fact that you can use := to declare variables easily is a double edged sword, as declaring a variable with the same name as a previously declared one is allowed if it's in a different scope, and it shadows the original variable. So:



This code will only print True at the end. The "err" variable inside the if block has been redefined so even though it's not nil inside the if block, it IS nil once you exit it! So if you want to chain several operations that may return errors and then at the end handle whatever error occurred in a consistent way, you have to be careful.

Closures

This one gave more some Javascript PTSD:



This prints :
4
4
4

Which was not what I expected! One easy fix is to add a line saying i:=i before creating the func in the first loop, which by virtue of the previous gotcha redeclares a variable in the scope of the for loop body.


Errors

I'm not convinced in the end by the standard error reporting in Go. A lot has been written on that topic too. I feel that the code is peppered with error handling that gets in the way of readability and implementing cleanly the business logic. I'm sure there are some design tricks you can use, but you shouldn't have to resort to tricks to do clean error handling in a language, because at the end of the day it's how you handle errors that make up the quality of your software, not only how you handle the happy path.

These things you can watch out for and probably code around pretty easily, but they do impact a bit the ease of use of Go, even though I still think it's quite a simple elegant language to quickly be productive in.

Happy Go Hacking!

Friday, March 23, 2007

Dynamic class behaviour in Java

In a previous post, I was using annotations to generate method pointers in Java. The functions objects were generated in a separate class file. However, if you suppose that a modern IDE would be able to generate all that code for you when you create a method, you could have the function object in the same class file as the method code itself. Since Java allows you to have a field and a method with the same name, everything works fine.
In that previous post the function object referenced the actual method in the original class file. What if we did the opposite, that is to say, the actual code is in the function object, and the method merely delegates? Here is a trivial example:

public class StringHelperDynamic {

public String toUpper(String a){
return toUpper.run(a);
}

public Function1 toUpper = new Function1 (this){
public java.lang.String run(java.lang.String a) {
return a.toUpperCase();
}
};

}

Here, we have a toUpper method that takes a String and return a String, and a toUpper function object that we can pass around, perform currying on, etc... the interesting twist of this architecture is that the toUpper field can be final or not. If not, we can then change it at runtime, and hence change the behaviour of the class at runtime, while still calling the same methods. Who needs a dynamic scripting language (-: ? To the silly example:

StringHelperDynamic me=new StringHelperDynamic();
me.toUpper=new Function1(me){
public java.lang.String run(java.lang.String a) {
return a.toLowerCase();
}
};

assertEquals("hello",me.toUpper("HELLO"));

OK, breaking the contract of the method is NOT what this is about, but you get the gist of it. The code for the Function1 class can be found here.

Friday, November 24, 2006

Higher order functions in Java with an annotation processor factory

I’m continuing my explorations of both Java 5 features like generics and annotations and of functional programming constructs. A lot of Java discussions on the web these days are about closures: writing quick anonymous methods without having to wrap them in a abstract class (think Runnable, Comparator, …). Now, closures can also be related to higher order functions, that is to say functions considered as objects in their own right. If you can reference a precise method inside an instance instead of just having to deal with interface, you can have a type of closures. For example, instead of passing a Comparator object you could pass a Function object, meaning a function that takes two T arguments and returns an integer.
To illustrate this point, let’s take an example.
You have a simple Sale class:

public class Sale {
private String customer;
private Date dateOfSale;
private float amount;

public Sale(String customer, Date dateOfSale, float amount) {
…constructor, getters and setters…

And you have a SaleManager class that encapsulates a list of sales (think retrieved from a database, etc…) and gives you a method to retrieve all sales sorted by what you want:

public class SalesManagerClassic {
private List sales;

public SalesManagerClassic(List sales){
this.sales=sales;
}

public Sale[] listSales(Comparator comp){
Sale[] ret=new Sale[sales.size()];
sales.toArray(ret);
Arrays.sort(ret,comp);
return ret;
}


}

So far so good. Now you define a SaleComparator that will provide you all kinds of comparators:
public class SaleComparatorClassic {

public Comparator compareByCustomer(){
return new Comparator(){
public int compare(Sale o1, Sale o2) {
return o1.getCustomer().compareToIgnoreCase(o2.getCustomer());
}
};
}

public Comparator compareByAmount(){
return new Comparator(){
public int compare(Sale o1, Sale o2) {
return (int) (o2.getAmount()-o1.getAmount());
}
};
}

}

As you can see, creating a comparator each time is tedious. Closure and higher order functions aim at simplifying the important code bits so that the actual strategy (how do we sort the sales) is not buried in all the boilerplate code. This is how we could use that class:

List l=new ArrayList();
…
SalesManagerClassic smc=new SalesManagerClassic(l);
SaleComparatorClassic scc=new SaleComparatorClassic();
Sale[] s=smc.listSales(scc.compareByCustomer());

A Function object in Java is something like that, roughly:

public abstract class Function {
private Object instance;

public Function(Object instance){
this.instance=instance;
}

public Object getInstance() {
return instance;
}
}

So it encapsulates the instance on which the function will be run. We’re not going out of the OO world right now.
Then generics in Java do not (if they do, drop me a line) allow you to specify that a class can take any number of generic type in its definition, so we’ll have to define a concrete class for all possible numbers of parameters:

public abstract class Function0 extends Function {
public Function0(Object instance){
super(instance);
}

public abstract R run();

}

The code above represents an object method that takes no argument and its return type is the generic type R (which could be Void if the method return nothing). Subclasses need to provide the actual implementation of the run method. And a function taking one parameter will be:

public abstract class Function1 extends Function {

public Function1(Object instance){
super(instance);
}

public abstract R run(P param);

public Function0 curry(final P param){
Function0 f=new Function0(getInstance()){
@Override
public R run() {
return Function1.this.run(param);
}
};
return f;
}

}

Here P is the type of the first parameter. For fun I added the curry function: if you know the first parameter but you don’t want to run the function right now, you can create a Function object with no argument that can be run later.

So what would that mean for our sales manager? This is what the code can look like:

public Sale[] listSales(final Function2 func){
Sale[] ret=new Sale[sales.size()];
sales.toArray(ret);
Arrays.sort(ret,new Comparator(){
public int compare(Sale o1, Sale o2) {
return func.run(o1, o2);
}
});
return ret;
}

The boiler plate for the comparator has been moved in one place (of course we still need it, we’re not writing our own version of Java where standard API calls takes our Function objects right now…). The Sale comparator is where the gain is made:

@FunctionAnnotation
public int compareByCustomer(Sale o1,Sale o2){
return o1.getCustomer().compareToIgnoreCase(o2.getCustomer());
}

@FunctionAnnotation
public int compareByAmount(Sale o1,Sale o2){
return (int) (o2.getAmount()-o1.getAmount());
}

The FunctionAnnotation is a simple method level annotation. This tells us: I want to be able to refer to these methods as Function objects. Note that my code for the moment does NOT deal with methods with the same name and different argument list. We’ll worry about that later… Notice for now how the methods are much simpler and how what they do is clear.

Now, what we need to do, is to do automatically the translation between simple methods with the FunctionAnnotation and Function<…> objects that we can pass to our SalesManager. For this we’ll use an annotation process factory. This factory will run on the source code for SaleComparator, and will generate a SaleComparatorFunctions class that will have methods giving you the Function<…> objects:

public static Function2 compareByAmount(final fr.moresmau.jp.func.samples.SaleComparatorFunctional instance){
return new Function2 (instance){
public Integer run(fr.moresmau.jp.func.samples.Sale param0, fr.moresmau.jp.func.samples.Sale param1) {
return instance.compareByAmount( param0, param1);
}
};
}

public static Function2 compareByCustomer(final fr.moresmau.jp.func.samples.SaleComparatorFunctional instance){
return new Function2 (instance){
public Integer run(fr.moresmau.jp.func.samples.Sale param0, fr.moresmau.jp.func.samples.Sale param1) {
return instance.compareByCustomer( param0, param1);
}
};
}

Aren’t we happy this is generated for us ? Then we can just code our calls like that:
List l=new ArrayList();
…
SalesManagerFunctional smf=new SalesManagerFunctional(l);
SaleComparatorFunctional h=new SaleComparatorFunctional();
Sale[] s=smf.listSales(SaleComparatorFunctions.compareByCustomer(h));

That code is about the same complexity as before. Of course using another class for the function wrapping make the code not as clear as it should be. In a later post I’ll look at alternatives, so for the moment bear with me.

So we have obtained higher order functions from a standard Java class, and we can use these functions instead of comparator objects.

Now of course I haven’t talked about the annotation process factory yet. There’s nothing magic there. We need to implement an AnnotationProcessFactory and to say we want to do something when we encounter our annotation:

public Collection supportedAnnotationTypes() {
return Arrays.asList("fr.moresmau.jp.func.FunctionAnnotation");
}

And we need to implement a AnnotationProcessor that will generate a Functions class for every class that as at least one method with the FunctionAnnotation. For that we need to use the createSourceFile method of the Filer object provided by the environment to create the function file.
Running the factory is done through the JDK apt tool:

apt -s src -factory fr.moresmau.jp.func.FunctionProcessorFactory -d bin -cp bin src/fr/moresmau/jp/func/samples/SaleComparator.java

The code for the Function objects and the AnnotationProcessFactory can be found here, the Sale example here, with unit tests.