GPO now includes the ability to define spreadsheet type formulas as property values.

The values are recalculated as their dependent values are modified.

Spreadsheet Processing

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.

GPO Formulas

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.

Formula Constants

In FormulaEvaluates 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)

Builtin Formula Primitives

Mechanisms are provided to extend the formula primitives available, but here are the currently available built-in primitives.

LookupsExample
(-> prop1 ...) (-> name)
(#-> gprop ...) (#-> root name)
uses IObjectManager.recall to access the first value
StringsExample
(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.
DebugExample
(watch val ...) (watch '''Name'' property is now ' (-> name))
Specializes the str primitive to echo the string value to stdout whenever it is modified.
Set OrientedExample
(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
MathsExample
(+ 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))
ComparisonExample
(= 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)
SecurityExample
(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
ConditionalsExample
(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 CallbackExample
(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 BlocksExample
(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))