Scritping Extension

Conformance

Zorba implements a subset of the XQuery Scripting Extension 1.0, with some exceptions:

Examples

Note: since XQuery is a functional language, in order to see scriping in action one needs to use some side-effecting facility, such as Zorba's input/output (see Input and Output):

import module namespace zorba =
  "http://www.zorba-xquery.com/zorba/internal-functions";

zorba:read-line () as xs:string;
zorba:print ($args as item()*) as xs:none;

The following example uses a while loop and Zorba's eval facility to implement a simple command-line calculator:

(: Simple calculator; exit with an empty line :)

import module namespace zorba =
  "http://www.zorba-xquery.com/zorba/internal-functions";

declare variable $nl := "
";

declare sequential function local:calc-one ($s as xs:string) as xs:boolean {
  if (string-length ($s) = 0) then
    exit with false ()
  else {
    zorba:print (("Result: ", eval { $s }, $nl));
    exit with true();
  };
};

while (local:calc-one (zorba:read-line ()))
{ (); }

Here's a different way to do the same thing without using an auxiliary function; we use a break statement to get out of the infinite loop when needed:

while (true ()) {
  let $s := zorba:read-line ()
  return
    if (string-length ($s) = 0) then break loop
    else zorba:print (("Result: ", eval { $s }, $nl));
}

The following is an implementation of the famous number-guessing game; since Zorba does not support mutable variables, we need to use a recursive function to implement the binary search:

import module namespace zorba =
  "http://www.zorba-xquery.com/zorba/internal-functions";

(: newline string, for easy printing :)
declare variable $nl := "
";

declare sequential function local:guess ($n) {
  zorba:print (("Was your number ", $n, "? Enter '=', '<' or '>'", $nl));
  exit with zorba:read-line();
};

(: find number $x s.t. $lo <= $x < $hi :)
declare sequential function local:solve ($lo, $hi, $iter) {
  if ($lo >= $hi) then
    zorba:print (("You have not answered truthfully.", $nl))
  else if ($lo + 1 = $hi) then
    zorba:print (("Your number was ", $lo,
                  " and I needed ", $iter, " guesses.", $nl))
  else
    let $mid := (($lo + $hi) idiv 2)
    let $ans := local:guess ($mid) return
    if ($ans = "=") then
      zorba:print (("I needed ", $iter, " guesses.", $nl))
    else if ($ans = "<") then
      local:solve ($lo, $mid, $iter + 1)
    else if ($ans = ">") then
      local:solve ($mid + 1, $hi, $iter + 1)
    else  (: invalid choice :)
      local:solve ($lo, $hi, $iter);
};

declare sequential function local:game ($nmin, $nmax) {
  zorba:print (("Think of a number between ", $nmin, " and ", $nmax,
                " then press ENTER", $nl));
  zorba:read-line();
  local:solve ($nmin, $nmax + 1, 1);
};


(::::::::::::::::::)
(:: Main program ::)
(::::::::::::::::::)

local:game (1, 11)