Libretto Language: Symbol Reference
- anglequote ( « (^") , » ("^) )
- arithop ( + , - , · (*) , == , ≠ (!=) , < , ≤ , > , ≥ , mod , div )
- as
- assign ( = , .= , += )
- atsym ( @ )
- bracket ( [ , ] )
- break
- class
- colon ( : )
- comment ( # )
- curly ( { , } )
- def
- dollar ( $ )
- dot ( . )
- exclaim ( ! )
- gen
- if ( if , else )
- inverse ( ~ )
- logicop ( ∧ (and) , ∨ (or) , ¬ (not) )
- ontology
- parentheses ( ( , ) )
- persent ( % )
- prefix
- question ( ? )
- quote ( " , ' )
- remove ( -- )
- require
- return
- semicolon ( ; )
- slash ( / )
- sorter ( << , >> )
- xmlsym ( <> )
- yield
anglequote
- description: The angle quotes « and » (the ASCII versions are ^" and "^) are used to define angle strings. An angle string does NOT have its own escaping sequences. Its interpretation depends on further processing (e.g. as a normal string, an XML code etc.) Since opening and closing quotes are different, angle strings can be nested in each other (like parentheses). The combination of angle strings and ! (eval) provides the presentation of nested expressions in parametrized strings.
- symbol: « (^")
- crib:
- linked: string
» ("^)
«abc» # = abc ^"abc"^ # = abc «{«{1+2}»}» # = {«{1+2}»} «{«{1+2}»}»! # = {1+2} «{«{1+2}»}»!! # = 3 «"normal string1" 'normal string2'» "\x3F" # = ? «\x3F»; # = \x3F «<address type="email">a@ontobox.org</address>»/x:readXml()/x:ee("address")/x:a("type") # = "email"
parametrized string
arithop
- description: The next symbols is used as arithmetic operators:
- symbol: +
- crib:
-
1 + 2; # 3 6 - 21; # -15 5 * 6 · 2; # 60 7 div 4; # 1 7.0 div 4; # 1.75 9 div 4.5; # 2.0 10 mod 3; # 1 10.0 mod 3; # error 1 >= 1; # true 1 > 6; # () - empty set means false 5.0 == 5; # true 3 != 23 ; # true 1 < 1; # ()
- linked: expression
"+" means addition;
"-" means subtraction;
"*" or "·" means multiplication;
"div" means exact division for whole numbers and division with remainder for decimal numbers (fractions);
"mod" means division with remainder for any kind of numbers. This operator may be used only for whole numbers
"==" means equality of two entities;
"≠" or "!=" means non-equality of two entities;
"<" ("≤") means that one number is less (less or equal) than another one;
">" ( "≥") means that one number is greater (greater or equal) than another one.
-
· (*)
==
≠ (!=)
<
≤
>
≥
mod
div
as
- description: “as” is used as an operator which allows user to assign variables. This may be useful in order to save data which appear along the query path.
- symbol: as
- crib:
-
(1,2,3) as x/(1,2,3) as y/ (x * y); # (1,2,3,2,4,6,3,6,9) class Person {name v:string; lastname v:string}; class Father extends Person {child Person}; Father &john {name = 'John'; lastname = 'Smith}; Person &ray {name = 'Ray'; lastname = 'Charles'}; &john {child = &ray}; Father as f/ child [lastname ≠ f/lastname] / '{name} has changed his last name'! #Ray has changed his last name
- linked: variable
sequence
iteration
assign
- description: These operators are used in the operations of assignment:
- symbol: =
- crib:
-
class Message {text v:string[1,1]} #the property must have only one value class Thread {messages Message[0, ]}#the property can have any amount of values Message &m1, &m2, &m3, &m4; Thread &t {messages = &m1}/messages; # (&m1) &t {messages .= &m2}/messages; # (&m2, &m1) &t {messages += (&m3, &m4)}/messages; # (&m2, &m1, &m3, &m4) &t {messages = &m3}/messages; # &m3 Thread &_{messages = Message[text/v:contains('ontology')]} # the object has not been created, because there are no messages containing word 'ontology' # But we may use either += or .= to ?surely? create the object Thread &_{messages += ()]} # &_4c5aec32-c07c-49fc-86fa-0ddbf6e78bc1
- linked: property
“=” means destructive assignment variables (data are replaced by new values);
“.=” means adding data to the beginning of a value sequence;
“+=” means adding to the end of a value sequence.
In case of using the destructive assignment ("="), creating of a new object with empty properties is impossible. But new object still can be created if ".=" or "+=" is used to assignment new values, even though one of the property values is empty.
.=
+=
variable
atsym
- description: “@” is used as a key to a schemeless declaration of objects and their values at the same time. Also symbol “@” can be used as an annotation to classes, properties or ontologies.
- symbol: @
- crib:
-
creating an object and properties on the fly &_ {@fileName = 'test.jsp'; @fileSize = '234'}; class Titled {title v:string}; %Titled {@comment = 'Class with t-property title'} # class Title now has an annotation %title {@comment = 'title value'}/@comment # title value
- linked: key
bracket
- description: The brackets “[]” are used to distinguish a predicate from the rest of an expression.
- symbol: [
- crib:
-
#brackets for condition class Employee {salary v:int}; Employee &_ {salary = 200}; Employee &_ {salary = 300}; Employee [salary > 200 ] # get all employees with salary higher than 200 #brackets for accessing an element of the sequence (1,2,3) [2] # 3 #brackets for declaring limits on the amount of values class Mother { name v:string[1, 1]; #one and only one name children Person[1, ]; #not less than one child passport v:int[, 1]; #not more than one passport }
- linked: predicate
Another application of brackets is when in the brackets “[]” indices of a sequence are enclosed. Through using the brackets “[]” an access to elements of a sequence may be done.
Also the brackets "[]" allow user to limit number of property values on the model level.
]
sequence (index)
break
- description: Breaks the innermost iteration. For deep breaks/returns use funcitons
- symbol: break
- crib:
- linked: sequence
label/3 and rollback/1. Breaks can influence through the functions but not generators.
(1,2,3,0,4,5,6)/(if (. = 0) break else .); # = (1,2,3) def g() {case . = 0 => break; case => .}; (1,2,3,0,4,5,6)/g(); # = (1,2,3) gen gg() {if (. = 0) break else .}; (1,2,3,0,4,5,6)/g(); # Error: Misplaced break...
iteration
class
- symbol: class
- linked: class
colon
- symbol: :
- linked: name
namespace
ontology
comment
- symbol: #
- linked: program
curly
- symbol: {
- linked: modifier
}
function
anonymuous function
block
def
- description: A keyword for defining a named function with the element-wise behavior.
- symbol: def
- crib:
- linked: function
def fact($x) {
case $x = 0 => 1;
case => $x * fact($x - 1)};
fact(7); # = 5040
(1,2,3,4,5) / fact(.); # = (1,2,6,24,120)
def untilZero() {
case . = 0 => break;
case => .
};
(1,2,3,0,4,5,6) / untilZero(); # = (1,2,3)
dollar
- description: Determines a variable, e,g,
- symbol: $
- crib:
- linked: variable
$x, $counter. Operation := is used to destructively assign values to variables. Libretto has global and local variables (in function and generator definitions). Variable names are unqualified (can not have prefixes). Global variables are not accessible within function bodies. Variables and their values are not saved in ontologies and valid only within the Libretto code that contains them. The combination of variables with operation as is convenient for organizing iterations over sequences in paths.
#$x is global $x := 115; # $y is local def f($y) {$y + 1}; # locals are valid only within function bodies $x; # = 115 $y; # Error: Global variable $y is not instantiated f(5) # = 6 # no access to globals within the function bodies def ff() {$x}; ff(); # Error: Local variable $x is not instantiated # variables as fields in paths $numbers := (1,2); ("a", "b") as $s / $numbers as $n / ($s + $n); # = ("a1", "a2", "b1", "b2")
dot
- description: The dot . is an analogue of 'this' and 'self' in object-oriented languages. It equals the current context. If the context is element-wise (e.g. in the call of a function) then . iteratively takes the value of each element of the context sequence. In the collection-wise context (e.g. in a call of a generator) . equals the whole sequence.
- symbol: .
- crib:
- linked: sequence
# in the element-wise context the dot . iteratively takes the value of each element of the context sequence (1,2,3,4,5) / (. + 3) # = (4,5,6,7,8) # in the collection-wise context of the built-in generator intersection/2 the dot . takes as the value the whole sequence at once (1,2,3) / v:intersection(. , (2,3,4)); # = (2,3) # functions are evaluated in the element-wise style, so the dot iteratively enumerates each value of the context sequence # break is used to stop the iteration over the context sequence def f() {case . = 0 => break; case => .}; (1,2,3,0,4,5,6)/f(); # = (1,2,3) # . = 0 is checked here number by number: 1 = 0, 2 = 0, 3 = 0, 0 = 0 # generators are evaluated in the collection-wise style, so in them the dot takes the whole sequence as value # break could be senseless here, because there is no iteration to stop: the sequence is taken as a whole gen g() {case . = 0 => return; case => yield .}; (1,2,3,0,4,5,6)/g(); # = () # . = 0 is checked for the whole sequence at once: (1,2,3,0,4,5,6) = 0, and since it is true, the computation immediately returns # the first dot takes the whole sequence, the second dot iteratively takes the value of each number: gen sum() {$s := 0; . / {$s := . + $s}; yield $s}; (1,2,3,4,5)/sum(); # = 15
iteration
exclaim
- description: The exclamation mark ! evaluates the expression. There are three types of such expressions: parametrized strings, blocks and functions (anonymuous functions or function entities):
-
A string (e.g.
«1+2 = {1+2}») is interpreted as a parametrized string, in which expressions in curly brackets are evaluated. The optional second argument of ! determines the escaping function transforming the results of evalutation. It is recommended to use angle quotes to provide nested evaluations. -
A block (e.g.
_{1+$x}): the expression(s) of the block is evaluated. In case of blocks ! does not have the second argument. -
An anonymuous function or a function entity (e.g.
_($x) {$x + 1}and%v:intersection^2: the function is evaluated; the mandatory second argument contains the arguments of the evaluated function. - symbol: !
- crib:
- linked: block
# in case of parametrized strings ! evaluates expressions in curly brackets: «1 + 2 = {1 + 2}»! # = 1 + 2 = 3 # use angle quotes « and » to organize nested evaluations: «{«{1+2}»}» # = {«{1+2}»} «{«{1+2}»}»! # = {1+2} «{«{1+2}»}»!! # = 3 # the first argument of ! can be an arbitrary expression: $x1 := "{1"; $x2 := "2}"; ($x1 + "+" + $x2)!; # = 3 # the evaluated expression can depend on the context values: (2,3) / «{.} + 2 = {. + 2}»! # = ("2 + 2 = 4", "3 + 2 = 5") # the optional 2nd argument of ! determines the escaping function, which acts on the evaluated expressions: «<a>{«<b>ccc</b>»}</a>»! # = <a><b>ccc</b></a> «<a>{«<b>ccc</b>»}</a>»!x:esc # = <a>&lt;b>ccc&lt;/b></a> # any unary function can be used as the escaper: def f($x) {$x + " is escaped"}; «the expression {«exp1»} and {«exp2»}»!f # = the expression exp1 is escaped and exp2 is escaped # ! can also evaluate blocks: _{1+2}!; # = 3 # a block saves the values of variables, which they have at the moment of block's creation (so-called closure semantics): $x := 5; $block := _{$x + .}; $x := 1000; (2,5)/$block!; # = (7,10) # in case of functions the 2nd argument of ! is mandatory (it transfers parameters to functions): %v:intersection^2 ! ((1,2,3),(2,3,4)) # = (2,3) $z := 5; $fun := _($x, $y) {($x + $y) * $z}; $z := 0; $fun ! (2,3); # = 25 # note that the body of an anonymuous function can contaion global variables, which also follow the closure semantics # actually ! is a syntactic sugar for built-in functions v:eval/1 and v:eval/2 "{1+2}" !; # = 3 v:eval/1("{1+2}"); # = 3 2 / _($x) {. * $x} ! (3); # = 6 2 / v:eval(_($x) {. * $x}, _{(3)}); # = 6
anonymuous function
function
parametrized string
gen
- symbol: gen
- linked: generator
if
- symbol: if
- linked: expression
else
inverse
- symbol: ~
- linked: property
logicop
- symbol: ∧ (and)
- linked: expression
∨ (or)
¬ (not)
predicate
ontology
- symbol: ontology
- linked: program
parentheses
- symbol: (
- linked: sequence
)
function
anonymuous function
persent
- symbol: %
- linked: entity
prefix
- symbol: prefix
- linked: ontology
namespace
name
question
- description: Variables
- symbol: ?
- crib:
- linked: variable
$_0..$_9 are used in combination with the question mark: ith occurrence of the question mark corresponds to the value of the ith variable. This construct is used in a number of web-programming techniques.
$_0 := 10; $_1 := 20; $_2 := 30; ? + ? + ?; # = 60
query
quote
- symbol: "
- linked: string
'
parametrized string
remove
- symbol: --
- linked: property
object
require
- symbol: require
- linked: repository
ontology
community
return
- description: Returns from functions and generators
- symbol: return
- linked: function
generator
semicolon
- symbol: ;
- linked: program
query
modifier
predicate
slash
- description: Connects the steps of a path.
- symbol: /
- linked: path
path step
sorter
- description: Sorts the context collection using a comparator (any expression which produces linearly ordered values).
- symbol: <<
- crib:
- linked: path
>>
# example 1 (3,2,1,6,4,5)<<.>> # = (1,2,3,4,5,6) # example 2 def titleNumber() { v:match("(\\d*).*", "")/$_m1/v:to-int() }; "10 Asterisks"/titleNumber(); # = 10 $titles := ("9 Data Types", "8 Modifiers, Predicates and Sequences", "10 Asterisks"); $titles<<.>>; # = ("10 Asterisks", "8 Modifiers, Predicates and Sequences", "9 Data Types") $titles<<title-number()>> # = ("8 Modifiers, Predicates and Sequences", "9 Data Types", "10 Asterisks")
path step
xmlsym
- description:
- symbol: <>
- crib:
- linked: XML
XML and XHTML elements are the normal expressions of Libretto. Actually they are translated into expressions, which combine builtin functions x:add/1, x:elem/1, x:attr/2. The evaluation of this expression produces a number of objects, which together represent the XML document. To work with XML documents it is necessary to load the XML ontology from the repository:
require x "http://xml.ontobox.org/";
# An XML element is translated into the set of objects; the root object of the XML-expression is returned:
$xml := <address type="postal"><street>Main</street><building>15</building></address>
# = &_bb9fb4ad-8077-40ad-bf5b-2a94368f454e
# The structure of XML objects is determined in the ontology http://xml.ontobox.org/,
# including such classes as x:Element, x:Text, etc. and properties x:name, x:attributes, x:text ets.
$xml/x:name; # = "address"
$xml/x:attributes[x:name = "type"]/x:value; # = "postal"
# Built-ins x:e/1, x:ee/1, x:a/1, x:t/0, x:tt/0 are convenient for handling data in the XML document
$xml/x:e("street")/x:t(); # = "Main"
$xml/x:a("type"); # = "postal"
$xml/x:tt()/v:join(", "); # = "Main, 15"
$xml/x:ee()/x:name; # = ("address", "street", "building")
# The functions x:write-xml/0 and x:write-xml/2 reconstruct the XML document from the XML objects.
$xml / x:write-xml();
# = «<address type="postal"><street>Main</street><building>15</building></address>»
# The functions x:read-xml/0 and x:read-xml/1, x:read-html/1 and x:read-html/3 load XML documents
$ontobox := x:read-html("http://ontobox.org/", "utf-8");
# = &_78c5f90c-2e81-43eb-88cd-e6a1a022173f
$ontobox/x:ee()/x:name/v:distinct();
# = ("html", "head", "meta", "link", "title", "body", ...)
($ontobox/x:ee("h2")/x:t())[0]; # = "Overview"
$ontobox/x:ee("div")/x:a("class"); # = ("mm_left", "mm_right", ... )
# XML expressions can contain parameters in curly brackets {..}
$street := <street>Main</street>;
$num := 15;
$tp := "postal";
<address type={$tp}>{x:elem("street")/x:add(x:text("Main"))}{"<building>{$num}</building>"! / x:read-xml()}</address> / x:write-xml()
# = "<address><street>Main</street><building>15</building></address>"
# Actually XML expressions are translated into combinations of built-in functions, which are further evaluated:
$xmlblock := _{<address type="postal"><street>Main</street><building>15</building></address>};
# = {x:elem("address") / x:add(x:attr("type", "postal")) /
# x:add(x:elem("street") / x:add(x:text("Main"))) / x:add(x:elem("building") /
# x:add(x:text("15")))}
$xmlblock! / x:name; # = "address"
# XML objects are always created in a special 'heap' ontology, which is determined by its prefix xheap:
xheap:*/x:name/v:distinct()<<.>>; # = ("address", "building", "street", "type")
expression
yield
- description: Places its argument into the output sequence of the generator in which it occurs.
- symbol: yield
- crib:
- linked: generator
yield is a keyword of Libretto. It works only in generators, not in functions.
# The class of a tree with named nodes is defined by two constructors:
class Tree(name v:string, subnodes Tree);
class Tree(name v:string);
# collect/1 collects nodes with a certain name:
gen collect($name v:string) {
yield .[name = $name];
yield subnodes/collect($name)
};
# example: create the tree with 3 nodes two of which named 'b'
$tree := Tree(":n1", "a",
(Tree(":n2", "b", ()),
Tree(":n3", "b", ()))); # = &n1
$tree / collect("b"); # = &n2, &n3
