Tutorial - Basic Expressions in Candle

In this tutorial, we'll go through the basic expressions in Candle. But before we do that, we'll need to firstly see how literal values are expressed in Candle.

Literal Values

In the following table, you'll see examples of different literal values in Candle. The exact syntax is specified in Candle Markup Reference. When multiple instances of the literal value type are given, they are separated by comma ','. The commas are not part of the literal value.

Literal Type Type Description Literal Value Examples
empty Empty value has three equivalent syntax in Candle ()
boolean Boolean value uses reserved keywords 'true' and 'false' true, false
int integer 123, 0, -56
long 64-bit integer 123L, 0L, -56L
decimal decimal number .5, 3.14159, -0.123
double IEEE double .5e0, 3.14159e0, -0.123e2
string Only double quote character needs to be escaped in Candle string.
The escape syntax is the same as XML's character entity reference.
"some text string", "double quote &dq; needs to be escaped",
"you can also use any HTML character entity in Candle, like ©"
uri URI must always be quoted in single quote in Candle 'uri', 'http:/www.candlescript.org/'
qname Literal qualified-name qname, ns:candle:core:markup, nil:name
datetime Datetime syntax is based on XML Schema datetime. The difference is that in Candle, you need to quote it with single quote character and prefix with 't:'. t:'2011-05-13t15:01:00',
t:'2011-05-13T15:01:00',
t:'2002-10-10T12:00:00-05:00',
t:'2002-10-10+13:00', t:'2011', t:'2011-12',
t:'--12-25', t:'--12', 't:'---25'

Now we can start looking at the basic expressions in Candle.

Sequence Expressions

A sequence can be easily created with '()' and comma operator.  Sequence in Candle does not nest and never contains empty value in it.

You can also use range operator to create a sequence of consecutive integer values. And range can only be in increasing order:
<?csp1.0?>
function main() {
  "Simple sequence: " { (1, 3.5, "string", true) } <br/>
  "Empty value are ignored in sequence: " { (1, 3.5, (), "string", true) } <br/>
  "Sequence does not nest: " { (1, (3.5, (), ("string", ())), true) } <br/>
  "Range 1 to 10: " { 1 to 10 } <br/>
  "Range can only be in increasing order: " { 10 to 1 } <br/>
  "Range in sequence: " { (10, 1 to 4) }
}
Try it yourself »

Arithmetic Expressions

I don't think there's little need to explain the syntax and usage of the arithmetic expressions if you have some programming experiences. The only things you need to take note are:
<?csp1.0?>
function main() {
  "100 - 1.5 = " { 100 - 1.5 } <br/>
  "-3 div 2 = " { -3 div 2 } <br/>
  "-3 idiv 2 = " { -3 idiv 2 } <br/>
  "(1 + 100) * 100 idiv 2 = " { (1 + 100) * 100 idiv 2 } <br/>
  "Sequence cannot be used as operand, e.g. (1 to 10) + 1 = " { (1 to 10) + 1 } <br/>
}
Try it yourself »

Comparison Expressions

There two kinds of comparison expressions: value comparison and node comparison. Value comparison expressions are straightforward. Node comparison expressions compare two nodes based on their document order.

And similar to arithmetic expressions, the operands must be atomized before evaluating the expression. Sequence cannot be used as the operand.
<?csp1.0?>
function main() {
  "123 < 34.5: " { 123 < 34.5 } <br/>
  "&dq;abc&dq; <= &dq;abcdef&dq;: " { "abc" <= "abcdef" } <br/>
  "<a>5</a> == <a>5</a>: " { <a>5</a> == <a>5</a> } <br/>

  let $nodes = <nodes><n1/><n2/></nodes>;
  !! compares if n1 is same node as n2
  "nodes/n1 is nodes/n2: " { nodes/n1 is nodes/n2 } <br/>
  !! compares if n1 precedes n2
  "nodes/n1 << nodes/n2: " { nodes/n1 << nodes/n2 } <br/>
}
Try it yourself »

Logic Expressions and Unary Not

Operands of logic expressions are converted to their effective boolean value before evaluating the expression. Sequence is always considered true.

Similar to XQuery, there's no unary not operator. You need to use not() function instead.
<?csp1.0?>
function main() {
  "12 < 34.5 and 67 < 89.0: " { 12 < 34.5 and 67 < 89.0 } <br/>
  !! empty is considered false
  "() and true: " { () and true } <br/>
  !! numeric 0 is considered false
  "0 or 0.0 or 0e0: " { 0 or 0.0 or 0e0 } <br/>
  !! node is always considered true
  "not(<a>1</a>): " { not(<a>1</a>) } <br/>
  "not(<a></a>): " { not(<a></a>) } <br/>
}
Try it yourself »