New in 10.1 – Introduction to the Any Type

In Apama 10.1, we introduced a new type any to EPL, which can hold a value of any concrete EPL type (equivalent to Object type in Java or auto in C++). This means it is now possible to write EPL applications in much more generic ways. In this blog, we shall explore some of new possibilities, code simplifications and other benefits that the any type gives us. To get the full story on how any functions (what actions are available on it and similar) please refer to the samples or doc. For now, let’s look at some interesting code!

Generic actions

EPL’s strong typing is important for performance, but the common casting that comes with that is something of an annoyance. So how about a single library action to handle the common cases?

event Maths {
    static action add(any a, any b) returns any {
        switch(a) {
            case decimal: {
                switch(b) {
                    case decimal: {
                        return a + b;
                    }
                    case float: {
                        return a.toDecimal() + b;
                    }
                    case integer: {
                        return a + b.toDecimal();
                    }
                }
            }
            case float: {
                switch(b) {
                    case decimal: {
                        return a + b.toFloat();
                    }
                    case float: {
                        return a + b;
                    }
                    case integer: {
                        return a + b.toFloat();
                    }
                }
            }
            case integer: {
                switch(b) {
                    case decimal: {
                        return a.toDecimal() + b;
                    }
                    case float: {
                        return a.toFloat() + b;
                    }
                    case integer: {
                        return a + b;
                    }
                }
            }
            default: {
                return "Provide correct parameters to perform add operation";
            }
        }
    }

A functional approach

The any type also opens options to bring different paradigms into EPL, such as the below (featuring our add action from previous example):

action map(any values, action<any> returns any mapper) returns sequence<any> {
    sequence<any> result := new sequence<any>;
    any value;
    for value in values.getEntries() {
        result.append(mapper(value));
    }
    return result;
}
 
action reduce(any values, action<any, any> returns any reducer, any initialValue) returns any {
    any result := initialValue;
    any value;
    for value in values.getEntries() {
        result := reducer(result, value);
    }
    return result;
}
      
action multiplyBy10(any value) returns any {
    return (<integer> value) * 10;
}
      
action sum(any currentSum, any value) returns any {
    return add(currentSum, value);
}
 
...
 
log(<integer> evtA.reduce(evtA.map([1,2,3], evtA.multiplyBy10), evtA.sum, 0) = 60).toString();

Factories

The following is useful for constructing events with user provided data:

package com.apama.helloworld;
 
/** This monitor demonstrates how to construct events  */
monitor Factory {
    action onload() {
        any evt := constructEvent("com.apama.helloworld.MyEvent",[<any>1,"value"]);
         
        log "Event Field Names : " + evt.getFieldNames().toString();
        log "Event Field Types : " + evt.getFieldTypes().toString();
        log "Event Field Values : " + evt.getFieldValues().toString();
 
        // You can also send an any to a channel (if it contains an event)
        send evt to "ChannelName";
    }
     
    action constructEvent(string eventName, sequence<any> args) returns any {
        any result := any.newInstance(eventName);
        integer i := 0;
        string fieldName;
        for fieldName in result.getFieldNames() {
            result.setField(fieldName,args[i]);
            i := i + 1;
        }
        return result;
    }
}
 
/** This event wouldn't normally be constructable because it is defined after the monitor **/
event MyEvent{
    integer i;
    string s;   
}

Inheritance in EPL!?

Well, almost. Using any , we can define an interface with a reference to the inheriting object

event IAnimal {
    any animal;
    action<> makeNoise;
}
 
event Cat {
    static action animalIs(IAnimal animal) returns boolean {
        return animal.animal.getTypeName() = Cat.getName();
    }
    static action fromAnimal(IAnimal animal) returns Cat {
        return <Cat>animal.animal;
    }
    action makeNoise() {
        log "meow";
    }
    action scratchFurniture() {
        log "** There are now holes in everything **";
    }
    action asIAnimal() returns IAnimal {
        return IAnimal(self, makeNoise);
    } 
}
 
/** This monitor demonstrates how to inherit an object using any  */
monitor Inheritance {
    action onload() {
        IAnimal cat := Cat().asIAnimal();   
 
        if Cat.animalIs(cat) {
            Cat.fromAnimal(cat).scratchFurniture();
        }
    }
}

There’s a lot more we can do with any , so watch out for further EPL blog posts to help extend your knowledge. As always, please post on our forums or leave a comment below with any questions or statements you may have. Can you come up with a use for any that we haven’t? Thanks, and happy developing!

– Ashish