GPO now includes the ability to define spreadsheet type formulas as property values.
The values are recalculated as their dependent values are modified.
There are only a few computational models in common use today. The majority of "professional" programmers will use some programming language like Java or C++. But, probably the most widely used computational tool is the spreadsheet.
For a discussion on the unification of the spreadsheet model with GPO please take
a look at this whitepaper.
Within GPO you can define a formula that is calculated within the context of the
GPO, take a look at this example:
IGPOMap gpm = new GPOMap(om);
gpm.set("value", 10.0);
gpm.define("vat", "(* 0.175 (-> value))");
The define method compiles the expression to a computational object, and sets it
to the property "vat". Now, the following line:
System.out.println("The vat value is " + gpm.get("vat"));
Will display the string "The vat value is 1.75" to standard out.
The most important thing to understand is the (-> value) which will return
the value of gpm.get("value"). In general a lookup can navigate a complex structure :
(-> parent parent name)
Might return the value of the "name" property of an objects "grandparent".
A note on "Strings": Since the formula is defined as a java string itself, it is not possible to simply follow scheme conventions on quoting a string. Instead, after considerable thought, it is decided to use the single quote "'" character to delimit a string containing spaces.
For example 'This is a string'. If you need to include the "'" character in the string
it is simply repeated: 'and ''this'' is quoted content in a string'.
If you need to include the double-quote '"' then that is escaped as for normal java, so
"(str 'and \"this\" is quoted')" should do what you want.
| In Formula | Evaluates as |
hello |
Java string hello |
'hello world' |
Java string hello world |
'hello ''world''' |
Java string hello 'world' |
'hello \"world\"' |
Java string hello "world" |
#t |
Java boolean Boolean.TRUE |
#f |
Java boolean Boolean.FALSE |
10 |
Java Double new Double(10) |
10.5 |
Java Double new Double(10.5) |
Mechanisms are provided to extend the formula primitives available, but here are the currently available built-in primitives.
| Lookups | Example |
(-> prop1 ...) |
(-> name) |
(#-> gprop ...) |
(#-> root name)
uses IObjectManager.recall to access the first value |
| Strings | Example |
(str val ...) |
(str 'My name is ' (-> name))
Simple concatenation of all the string values passed as arguments |
(substr val begin [end]) |
(substr 'Mr Brown' 3)
Returns the substring from the begin index to either the end of
the string, or the end index if supplied |
(str-upcase val ...) |
(str-upcase (-> name) ' ' (-> surname))
Returns the uppercase representation of a concatenation of all the string arguments provided. |
(str-downcase val ...) |
(str-downcase (-> name) ' ' (-> surname))
Returns the lowercase representation of a concatenation of all the string arguments provided. |
| Debug | Example |
(watch val ...) |
(watch '''Name'' property is now ' (-> name))
Specializes the str primitive to echo the string value to stdout
whenever it is modified. |
| Set Oriented | Example |
(sum link property) |
(sum parent value)
will sum the value of the "value" property for all objects that defined by the set gpm.getLinkSet("parent") |
(avg link property) |
(avg parent value) |
(count link) |
(count parent) |
(stddev link property) |
(stddev parent value)
incrementally computes the standard deviation of the values in the set |
| Maths | Example |
(+ v1 ...) |
(+ (-> vat) (-> net))
(+ 2 3 4 5 6) evaluates to 20 |
(* v1 ...) |
(* 0.175 (-> net)) |
(- v1 ...) |
(- (-> value) 10)
(- 10) as a single argument returns the negative: -10 |
(/ v1 ...) |
(/ (sum linkset value) (count linkset))
- same value as (avg linkset value)
(/ 3) as a single argument returns the inverse: 1/3 |
(sqr v1) |
(sqr (-> value) 2)
computes the square of the value |
(sqrt v1) |
(sqrt 2)
computes the square root of the value |
(expt v1 v2)(^ v1 v2)
| (expt (-> value) 2) or (^ (-> value) 2)
- same value as (sqr (-> value)) |
| Comparison | Example |
(= v1 v2 ...) |
(= (-> value1) (-> other value1))
short circuit equality test for first argument against all others |
(!= v1 v2 ...) |
(!= (-> value1) (-> other value1))
short circuit test for first argument being not equal to all others |
(> v1 v2 ...) |
(> (-> value) 10.0) |
(>= v1 v2 ...) |
(>= (-> value) 10.0) |
(< v1 v2 ...) |
(< (-> value) 10.0) |
(<= v1 v2 ...) |
(<= (-> value) 10.0) |
(and v1 v2 ...) |
(and (> (-> value) 10.0) (< (-> value) 20.0))
Short circuit test returning true if all arguments evaluate to true |
(or v1 v2 ...) |
(or (> (-> value) 10.0) (< (-> value) 20.0))
Short circuit test returning true if any arguments evaluate to true |
(not v1) |
(not (> (-> value) 10.0))
is equivalent to (<= (-> value) 10.0) |
| Security | Example |
(md5 v1 ...) |
(md5 (-> name))
Concatanates a list of string values and returns a base 64 string representing the message digest computed using the MD5 algorithm |
| Conditionals | Example |
(cond (t1 v1) ...) |
(cond ((< 10 (-> value)) 'lessThan') (#t 'greaterOrEqual')))
general conditional expression, returning value of last expression of the first successfully tested block |
(case val (t1 v1) ...) |
(case (-> name) ('tony' 'PM') ('cherie' 'QC')))
variation that tests single test value for equality against other expressions, returning the last expression of the block that matches |
| Java Callback | Example |
(call [target] meth a1 ...) |
(call doMethod (-> name))
will invoke the method doMethod on the local object with
the value of the name lookup passed as first parameter.
(call (-> assoc) doMethod (-> name))
will do something similar but invoke the method on the object returned by the lookup on the assoc property. |
| Code Blocks | Example |
(let ([(n v)...]) ...) |
(let ((n (-> name))) (str 'hi there ' n))
binds the result of the lookup (-> name) to the symbol n
which is then used in any following formula - in the case above equivalent to:
(str 'hi there ' (-> name)) |