Fabl uses "dot" syntax for accessing and setting properties. The fact that RDF allows multiple values per property makes it convenient to distinguish two kinds of property access: single-valued access, represtented by one dot, and multi-valued access, represented by two dots. Here are the details:
One dot
If R is a resource, and P a property, R.P is one of the values of P on R (ie one of the values V of triples of the form <R,P,V>). If P is a functional property, then there can only be one value, and R.P is that value. Otherwise, the value of the most recently added triple <R,P,V> is selected. If R.P has no value, then the Fabl construct representing an undefined result, nil, is returned.
Similarly, R.P=V sets the unique value of P on R to be V; that is, it replaces any values P may previously have had on R by V.
Two dots
R..P evaluates to a sequence containing all of the values of P on R (see the section on sequences). If there is one value, a sequence is still returned - a sequence of length one in this case.
R..P=V adds V to the current set of values of P on R; that is, it adds the triple <R,P,V>.
If P is known to have only one value, either because P is a functional property, or because the type C of R restricts P to have only one value on members of C, then R..P takes this into account, and replaces the value rather than adding to the current value set.
Examples
allocate("ex:R0");
allocate("ex:P0",Property);
ex:R0.ex:P0 = "abc";
adds the following triple to the Fabl triple store:
<http://example.org/R0,http://example.org/P0, "abc" >after removing any existing triples of the form
<http://example.org/R0,http://example.org/P0,X>
And then,
ex:R0.ex:P0; -->abc
continuing the example:
ex:R0.ex:P0 = "def"; ex:R0.ex:P0 -->def
Note that the existing value was replaced. However,
ex:R0..ex:P0 = "hij"; ex:R0..ex:P0 -->[def,hij]
Typed properties
rdfs:range is a property of properties that asserts the type of values that a property can take on.
For example:
allocate('ex:intP0',owl:FunctionalProperty);
ex:intP0.rdfs:range = int;
This asserts that the functional property ex:intP0 can only assume ints as value. Then expressions of the form
R.ex:intP0
are assigned the type int by Fabl.
An attempt to assign a value of the wrong type generates an error:
ex:R0.ex:intP0 = 'example'; --> ERROR --> Could not coerce example to xsd:int
but
ex:R0.ex:intP0 = 5; ex:R0.ex:intP0 = ex:R0.ex:intP0 + 3; ex:R0.ex:intP0; --> 8
Bitfield properties
For compact storage Fabl (like most programming languages) supports the representation of a boolean property as a single bit within a word. The function,
void defineBitField(Class cls,Property booleanprop,Property intprop,int n)
asserts that for objects of class cls, the value of the boolean property booleanprop is represented by the value of the nth bit within the value of the integer property intprop. Here is an example:
allocate('ex:intP0',owl:FunctionalProperty);
ex:intP0.rdfs:range = int;
allocate('ex:booleanP0',owl:FunctionalProperty);
ex:booleanP0.rdfs:range = boolean;
defineBitField(Resource,ex:booleanP0,ex:intP0,3);
var uu = new(Resource);
uu.ex:booleanP0 = true;
uu.ex:intP0;
-->8
uu.ex:booleanP0;
-->true
Low level triple manipulation
As explained just above, use of the dot syntax invokes Fabl's type analysis machinery; an expression of the form x.P or x..P will be assigned a type based on what is known about the type of x and the restrictions on P. The following lower level operations are also available - operations which ignore such type information as may be available. set and assert should be used with care, since they can create triples that are inconsistent with assertions made elsewhere. The function
Resource fget(Resource R,Property P)
resembles R.P in effect: it returns the most recently added value of P on R, or nil if there is no such value.
SeqOf(Resource) mget(Resource R,Property P)
resembles R..P in effect: it returns the sequence of all values of P on R.
Binding set(Resource R,Property P,Resource V)
resembles R.P=V in effect: it replaces whatever values P may have had on R by V. set has variants for int and double values:
Binding set(Resource R,Property P,int V)
Binding set(Resource R,Property P,double V)
The function
Binding assert(Resource R,Property P,Resource V)
resembles R..P=V in effect: it adds V to the set of values possessed by P on R. assert has variants for int and double values:
Binding assert(Resource R,Property P,int V)
Binding assert(Resource R,Property P,double V)