Powerful concept: FunctionMap

This idea comes from JavaScript when there were no classes yet as there are now in ES6. You would write something like this:

var greetings = {
 hello: function() { console.info("Hello"); }
};
greetings.hello();
greetings["hello"]();

This is how functions could be shipped around. So the idea is simple, especially the second one. I started to wonder if we can have a Map of String -> Function in other languages like Java, Python, PHP and more?

Java

We sure can. I was working on a JSON-RPC project where you don't send entity bodies but you send what method to invoke and with what arguments. In the backend we made it so internally a consistent object was shipped around (RPCServiceResult) and we had Enum for the methods that were allowed. So I set up an EnumMap of Enum -> Function. This made it so the entrypoint of each service was the same. See if the method key exists, if so execute the corresponding function with the given input otherwise throw a MethodNotFound error. This meant we could extend the Enum and EnumMap and the Function mapping but never had to change how the services called each other.

Python

In Python I was working on a silly hacking simulation game in the Console. I wanted to have a list of commands and execute the corresponding function that was that command in game terms. At this point I just came from PHP and there it is completely normal to execute the string itself. I will come back to this in a bit. This is more difficult to do in Python and so I came up with a dict where command name was the key and function references were the values. This made it super simple to maintain.

PHP

So in PHP this is normal:

function a(){ echo "A"; };
$a = "a";
$a();

However it is really difficult to maintain and see what is going on, let alone insecure to do this if the input to $a is user input. The following makes more sense and is easier to maintain.

function a() { echo "A"; };
$commands = ["a" => function() { call_user_func("a"); }];
if ( array_key_exists("a", $commands) ) { $commands["a"](); }

Granted this is a contrived example but I hope it gets the point across.

Scala

I was working on the Advent of Code 2020 and one of the puzzles had a lot of validation rules. Immediately the structure came to mind of having a Map of Functions, for each field to validate the corresponding function. This worked like a charm and it is very easy to see what each rule does.

Java

Another example was that in a particular flow there was a need to either create a User of type A or type B and then continue the flow. It was first like the following:

if ( type == "UserA" ) {
    return new UserA();
} else {
    return new UserB();
}

Now never mind the bug of always returning type B, I suggested the following:

Map<String, Supplier<User>> userSupplier = new HashMap<>(){{ put("UserA", UserA::new); put("UserB", UserB::new); }};

Now you could replace it with one entrypoint:

return userSupplier.getOrDefault(type, UserB::new).get();

You still have the bug, but it became a feature. So we leave it in. The colleague immediately said, this happens in way more places in the code and I can change all of them.

The nice thing again is, we can extend the map to support more types but it does not change the logic of calling the service.

Conclusion

I hope this concept proves useful to you, I find it quite powerful and easy to construct and it gives lots of nice patterns.

#code #javascript #java #python