Friday, November 12, 2010

Pattern: How to start a thread of execution in Fantom

In Fantom, how do you start a new thread of execution? The pattern below is very simple and nice.

    const class Main {
        Void main() {
            svc := Actor(ActorPool()) { doSomething }.send(null)
        }

        Obj? doSomething() {
            // Do something like binding to a port and listening for requests.
            // Or you can call another method that does that.

            return null
        }
    }

The code above might seem a little odd at first. All that it does is to create an Actor with a code block that will execute the doSomething method. By sending a dummy message (".send(null)"), the Actor instance is started.

The key here is that sending a dummy message to an Actor starts the Actor. This same trick may be applicable to other Actor based languages as well.

Wednesday, November 03, 2010

Funny error message in YouTube

Today I got this funny error message in YouTube.

Tuesday, November 02, 2010

Lazy initializing default values

One of the tasks you will come across often is to look up a value in a map, while providing a default value for the looked up value. For e.g.

Properties prop = ...
Object value = prop.get("key", "defaultValue")

The issue with this pattern is that, what if arriving at default value is a costly operation. Even worse, there may be no need to compute the default value at all, may be because the get operation will always find a value in the properties.

During such times "lazy evaluation" comes to the rescue. This is not a new pattern, it has been around for long time. Just that some APIs are written with lazy evaluation in mind, and some not. In the example above, instead of taking the value itself, if the get method takes an argument that is callable or a lambda function, then it can use that function only under the situation that the value is not present.

The example below is from Fantom language when you attempt to get a value from a map.
    class Main {
        Void main() {
            myMap := [Str:Str]["k1":"v1", "k2":"v2"]
            echo(myMap.getOrAdd("k3", |Str k->Str| {return "v3"}))
        }
    }

What the piece of code above does is to compute the value of the key only when it is not present in the map. In the example above when you look up "k3" which is not found in the map, the lambda function is invoked to compute the value once.