Next

Prev

Prev-tail

Tail

Up

Chapter 20
urbiscript Standard Library

20.1 Barrier

Barrier is used to wait until another job raises a signal. This can be used to implement blocking calls waiting until a resource is available.

  20.1 Barrier
  20.1.1 Prototypes
  20.1.2 Construction
  20.1.3 Slots
  20.2 Binary
  20.2.1 Prototypes
  20.2.2 Construction
  20.2.3 Slots
  20.3 Boolean
  20.3.1 Prototypes
  20.3.2 Construction
  20.3.3 Truth Values
  20.3.4 Slots
  20.4 CallMessage
  20.4.1 Examples
  20.4.2 Slots
  20.5 Channel
  20.5.1 Prototypes
  20.5.2 Construction
  20.5.3 Slots
  20.6 Code
  20.6.1 Prototypes
  20.6.2 Construction
  20.6.3 Slots
  20.7 Comparable
  20.7.1 Slots
  20.8 Container
  20.8.1 Prototypes
  20.8.2 Slots
  20.9 Control
  20.9.1 Prototypes
  20.9.2 Slots
  20.10 Date
  20.10.1 Prototypes
  20.10.2 Construction
  20.10.3 Slots
  20.11 Dictionary
  20.11.1 Example
  20.11.2 Prototypes
  20.11.3 Construction
  20.11.4 Slots
  20.12 Directory
  20.12.1 Prototypes
  20.12.2 Construction
  20.12.3 Slots
  20.13 Duration
  20.13.1 Prototypes
  20.13.2 Construction
  20.13.3 Slots
  20.14 Event
  20.14.1 Prototypes
  20.14.2 Examples
  20.14.3 Construction
  20.14.4 Slots
  20.15 Exception
  20.15.1 Prototypes
  20.15.2 Construction
  20.15.3 Slots
  20.15.4 Specific Exceptions
  20.16 Executable
  20.16.1 Prototypes
  20.16.2 Construction
  20.16.3 Slots
  20.17 File
  20.17.1 Prototypes
  20.17.2 Construction
  20.17.3 Slots
  20.18 Finalizable
  20.18.1 Example
  20.18.2 Prototypes
  20.18.3 Construction
  20.18.4 Slots
  20.19 Float
  20.19.1 Prototypes
  20.19.2 Construction
  20.19.3 Slots
  20.20 Float.limits
  20.20.1 Slots
  20.21 FormatInfo
  20.21.1 Prototypes
  20.21.2 Construction
  20.21.3 Slots
  20.22 Formatter
  20.22.1 Prototypes
  20.22.2 Construction
  20.22.3 Slots
  20.23 Global
  20.23.1 Prototypes
  20.23.2 Slots
  20.24 Group
  20.24.1 Example
  20.24.2 Prototypes
  20.24.3 Construction
  20.24.4 Slots
  20.25 InputStream
  20.25.1 Prototypes
  20.25.2 Construction
  20.25.3 Slots
  20.26 IoService
  20.26.1 Example
  20.26.2 Prototypes
  20.26.3 Construction
  20.26.4 Slots
  20.27 Job
  20.27.1 Prototypes
  20.27.2 Construction
  20.27.3 Slots
  20.28 Kernel1
  20.28.1 Prototypes
  20.28.2 Construction
  20.28.3 Slots
  20.29 Lazy
  20.29.1 Examples
  20.29.2 Caching
  20.29.3 Prototypes
  20.29.4 Construction
  20.29.5 Slots
  20.30 List
  20.30.1 Prototypes
  20.30.2 Construction
  20.30.3 Slots
  20.31 Loadable
  20.31.1 Prototypes
  20.31.2 Example
  20.31.3 Construction
  20.31.4 Slots
  20.32 Lobby
  20.32.1 Prototypes
  20.32.2 Construction
  20.32.3 Examples
  20.32.4 Slots
  20.33 Location
  20.33.1 Prototypes
  20.33.2 Construction
  20.33.3 Slots
  20.34 Math
  20.34.1 Prototypes
  20.34.2 Construction
  20.34.3 Slots
  20.35 Mutex
  20.35.1 Prototypes
  20.35.2 Construction
  20.35.3 Slots
  20.36 nil
  20.36.1 Prototypes
  20.36.2 Construction
  20.36.3 Slots
  20.37 Object
  20.37.1 Prototypes
  20.37.2 Construction
  20.37.3 Slots
  20.38 Orderable
  20.39 OutputStream
  20.39.1 Prototypes
  20.39.2 Construction
  20.39.3 Slots
  20.40 Pair
  20.40.1 Prototype
  20.40.2 Construction
  20.40.3 Slots
  20.41 Path
  20.41.1 Prototypes
  20.41.2 Construction
  20.41.3 Slots
  20.42 Pattern
  20.42.1 Prototypes
  20.42.2 Construction
  20.42.3 Slots
  20.43 Position
  20.43.1 Prototypes
  20.43.2 Construction
  20.43.3 Slots
  20.44 Primitive
  20.44.1 Prototypes
  20.44.2 Construction
  20.44.3 Slots
  20.45 Process
  20.45.1 Prototypes
  20.45.2 Example
  20.45.3 Construction
  20.45.4 Slots
  20.46 Profiling
  20.46.1 Prototypes
  20.46.2 Construction
  20.47 PseudoLazy
  20.48 PubSub
  20.48.1 Prototypes
  20.48.2 Construction
  20.48.3 Slots
  20.49 PubSub.Subscriber
  20.49.1 Prototypes
  20.49.2 Construction
  20.49.3 Slots
  20.50 RangeIterable
  20.50.1 Prototypes
  20.50.2 Slots
  20.51 Regexp
  20.51.1 Prototypes
  20.51.2 Construction
  20.51.3 Slots
  20.52 StackFrame
  20.52.1 Construction
  20.52.2 Slots
  20.53 Semaphore
  20.53.1 Prototypes
  20.53.2 Construction
  20.53.3 Slots
  20.54 Server
  20.54.1 Prototypes
  20.54.2 Construction
  20.54.3 Slots
  20.55 Singleton
  20.55.1 Prototypes
  20.55.2 Construction
  20.55.3 Slots
  20.56 Socket
  20.56.1 Example
  20.56.2 Prototypes
  20.56.3 Construction
  20.56.4 Slots
  20.57 String
  20.57.1 Prototypes
  20.57.2 Construction
  20.57.3 Slots
  20.58 System
  20.58.1 Prototypes
  20.58.2 Slots
  20.59 System.PackageInfo
  20.60 System.Platform
  20.61 Tag
  20.61.1 Examples
  20.61.2 Construction
  20.61.3 Slots
  20.61.4 Hierarchical tags
  20.62 Timeout
  20.62.1 Prototypes
  20.62.2 Construction
  20.62.3 Examples
  20.62.4 Slots
  20.63 TrajectoryGenerator
  20.63.1 Prototypes
  20.63.2 Examples
  20.63.3 Construction
  20.63.4 Slots
  20.64 Triplet
  20.64.1 Prototype
  20.64.2 Construction
  20.64.3 Slots
  20.65 Tuple
  20.65.1 Prototype
  20.65.2 Construction
  20.65.3 Slots
  20.66 UObject
  20.66.1 Prototypes
  20.66.2 Slots
  20.67 UValue
  20.68 UVar
  20.68.1 Construction
  20.68.2 Prototypes
  20.68.3 Slots
  20.69 void
  20.69.1 Prototypes
  20.69.2 Construction
  20.69.3 Slots

20.1.1 Prototypes

20.1.2 Construction

A Barrier can be created with no argument. Signals and wait calls done on this instance are restricted to this instance.

 
Barrier.new; 
[00000000] Barrier_0x25d2280

20.1.3 Slots

20.2 Binary

A Binary object, sometimes called a blob, is raw memory, decorated with a user defined header.

20.2.1 Prototypes

20.2.2 Construction

Binaries are usually not made by users, but they are heavily used by the internal machinery when exchanging Binary UValues. A binary features some content and some keywords, both simple Strings (??sec:std-String).

 
Binary.new(
"my header"
, 
"my content"
); 
[00000001] BIN 10 my header
 
my content

Beware that the third line above (‘my content’), was output by the system, although not preceded by a timestamp.

20.2.3 Slots

20.3 Boolean

There is no object Boolean in urbiscript, but two specific objects true and false. They are the result of all the comparison statements.

20.3.1 Prototypes

The objects true and false have the following prototype.

20.3.2 Construction

There are no constructors, use true and false. Since they are singletons, clone will return themselves, not new copies.

 
true; 
!false; 
2 < 6 === true; 
true.new === true; 
6 < 2 === false;

20.3.3 Truth Values

As in many programming languages, conditions may be more than only true and false. Whether some value is considered as true depends on the type of this. Actually, by default objects as considered “true”, objects evaluating to “false” are the exception:

The method Object.asBool is in charge of converting some arbitrary value into a Boolean.

 
assert(Global.asBool == true); 
assert(nil.asBool ==    false); 
void.asBool; 
[00000421:error] !!! unexpected void

20.3.4 Slots

20.4 CallMessage

Capturing a method invocation: its target and arguments.

20.4.1 Examples

20.4.1.1 Evaluating an argument several times

The following example implements a lazy function which takes an integer n, then arguments. The n-th argument is evaluated twice using evalArgAt.

 
function callTwice 
{ 
  var n = call.evalArgAt(0); 
  call.evalArgAt(n); 
  call.evalArgAt(n) 
} |; 
 
// Call twice echo("foo").
 
callTwice(1, echo(
"foo"
), echo(
"bar"
)); 
[00000001] *** foo
 
[00000002] *** foo
 
 
// Call twice echo("bar").
 
callTwice(2, echo(
"foo"
), echo(
"bar"
)); 
[00000003] *** bar
 
[00000004] *** bar

20.4.1.2 Strict Functions

Strict functions do support call.

 
function strict(x) 
{ 
  echo(
"Entering"
); 
  echo(
"Strict: "
 + x); 
  echo(
"Lazy:   "
 + call.evalArgAt(0)); 
} |; 
 
strict({echo(
"1"
); 1}); 
[00000011] *** 1
 
[00000013] *** Entering
 
[00000012] *** Strict: 1
 
[00000013] *** 1
 
[00000014] *** Lazy:   1

20.4.2 Slots

20.5 Channel

Returning data, typically asynchronous, with a label so that the “caller” can find it in the flow.

20.5.1 Prototypes

20.5.2 Construction

Channels are created like any other object. The constructor must be called with a string which will be the label.

 
var ch1 = Channel.new(
"my_label"
); 
[00000201] Channel_0x7985810
 
 
ch1 << 1; 
[00000201:my_label] 1
 
 
var ch2 = ch1; 
[00000201] Channel_0x7985810
 
 
ch2 << 1/2; 
[00000201:my_label] 0.5

20.5.3 Slots

20.6 Code

Functions written in urbiscript.

20.6.1 Prototypes

20.6.2 Construction

The keywords function and closure build Code instances.

 
function(){}.protos[0] === getSlot(
"Code"
); 
closure(){}.protos[0] === getSlot(
"Code"
);

20.6.3 Slots

20.7 Comparable

Objects that can be compared for equality and inequality. See also Orderable (??sec:std-Orderable).

This object, made to serve as prototype, provides a definition of != based on ==. Object provides a default implementation of == that bounces on the physical equality ===.

 
class Foo : Comparable 
{ 
  var value = 0; 
  function init (v) { value = v; }; 
  function ’==’ (lhs) { value == lhs.value; }; 
}; 
[00000000] Foo
 
Foo.new(1) == Foo.new(1); 
[00000000] true
 
Foo.new(1) == Foo.new(2); 
[00000000] false

20.7.1 Slots

20.8 Container

This object is meant to be used as a prototype for objects that support has and hasNot methods. Any class using this prototype must redefine either has, hasNot or both.

20.8.1 Prototypes

20.8.2 Slots

20.9 Control

Control is designed as a namespace for control sequences. Some of these entities are used by the Urbi engine to execute some urbiscript features; in other words, users are not expected to you use it, much less change it.

20.9.1 Prototypes

20.9.2 Slots

20.10 Date

This class is meant to record dates in time.

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

20.10.1 Prototypes

20.10.2 Construction

Without argument, newly constructed dates refer to the epoch (see epoch).

 
Date.new; 
[00000001] 1970-01-01 01:00:00

With a numeric argument s, refers to the date that is s seconds after the epoch.

 
Date.new(1234567890); 
[00023593] 2009-02-14 00:31:30

With a string argument d, refers to the date contained in d. The string should be formatted as ‘yyyy-mm-dd hh:mn:ss ’ (see asString). mn and ss are optional. If the block ‘hh:mn:ss ’ is absent, the behavior is undefined.

 
Date.new(
"2003-10-10 20:10:50"
); 
[00086457] 2003-10-10 20:10:50
 
Date.new(
"2003-10-10 20:10"
); 
[00091439] 2003-10-10 20:10:00
 
Date.new(
"2003-10-10 20"
); 
[00094386] 2003-10-10 20:00:00

If you create a date with a numeric argument which cannot be interpreted as a date you should get an error message warning you that the value cannot be converted into a integer

 
Date.new(0.1); 
[00095042:error] !!! new: bad numeric conversion: overflow or non empty fractional part: 0.1

20.10.3 Slots

20.11 Dictionary

A dictionary is an associative array, also known as a hash in some programming languages. They are arrays whose indexes are strings.

In a way objects are dictionaries: one can use setSlot, updateSlot, and getSlot. This is unsafe since slots also contains value and methods that object depend upon to run properly.

20.11.1 Example

The following session demonstrates the features of the Dictionary objects.

 
var d = [
"one"
 => 1, 
"two"
 => 2]; 
[00000001] ["one" => 1, "two" => 2]
 
for (var p : d) 
  echo (p.first + 
" => "
 + p.second); 
[00000003] *** one => 1
 
[00000002] *** two => 2
 
"three"
 in d; 
[00000004] false
 
d[
"three"
]; 
[00000005:error] !!! missing key: three
 
d[
"three"
] = d[
"one"
] + d[
"two"
] | {}; 
"three"
 in d; 
[00000006] true
 
d.getWithDefault(
"four"
, 4); 
[00000007] 4

20.11.2 Prototypes

20.11.3 Construction

The Dictionary constructor takes arguments by pair (key, value).

 
Dictionary.new(
"one"
, 1, 
"two"
, 2); 
[00000000] ["one" => 1, "two" => 2]
 
Dictionary.new; 
[00000000] [ => ]

Yet you are encouraged to use the specific syntax for Dictionary literals:

 
[
"one"
 => 1, 
"two"
 => 2]; 
[00000000] ["one" => 1, "two" => 2]
 
[=>]; 
[00000000] [ => ]

An extra comma can be added at the end of the list.

 
[ 
  
"one"
 => 1, 
  
"two"
 => 2, 
]; 
[00000000] ["one" => 1, "two" => 2]

20.11.4 Slots

20.12 Directory

A Directory represents a directory of the file system.

20.12.1 Prototypes

20.12.2 Construction

A Directory can be constructed with one argument: the path of the directory using a String (??sec:std-String) or a Path (??sec:std-Path). It can also be constructed by the method open of Path (??sec:std-Path).

 
Directory.new(
"."
); 
[00000001] Directory(".")
 
Directory.new(Path.new(
"."
)); 
[00000002] Directory(".")

20.12.3 Slots

20.13 Duration

This class records differences between Dates (??sec:std-Date).

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

20.13.1 Prototypes

20.13.2 Construction

Without argument, a null duration.

 
Duration.new; 
[00000001] Duration(0s)
 
Duration.new(1h); 
[00023593] Duration(3600s)

Durations can be negative.

 
Duration.new(-1); 
[00000001] Duration(-1s)

20.13.3 Slots

20.14 Event

An event can be “emitted” and “caught”, or “sent” and “received”. See also Section 12.2.

20.14.1 Prototypes

20.14.2 Examples

There are several examples of uses of events in the documentation of event-based constructs. See at (Section 19.9.1), waituntil (Section 19.9.5), whenever (Section 19.9.6), and so forth. The tutorial chapter about event-based programming contains other examples, see Chapter 12.

20.14.3 Construction

An Event is created like any other object, without arguments.

 
var e = Event.new; 
[00000001] Event_0x9ad8118

20.14.4 Slots

20.15 Exception

Exceptions are used to handle errors. More generally, they are a means to escape from the normal control-flow to handle exceptional situations.

The language support for throwing and catching exceptions (using try/catch and throw, see Section 19.7) work perfectly well with any kind of object, yet it is a good idea to throw only objects that derive from Exception.

20.15.1 Prototypes

20.15.2 Construction

There are several types of exceptions, each of which corresponding to a particular kind of error. The top-level object, Exception, takes a single argument: an error message.

 
Exception.new(
"something bad has happened!"
); 
[00000001] Exception something bad has happened!’
 
Exception.Arity.new(
"myRoutine"
, 1, 10, 23); 
[00000002] Exception.Arity myRoutine: expected between 10 and 23 arguments, given 1’

20.15.3 Slots

Exception has many slots which are specific exceptions. See Section 20.15.4 for their documentation.

20.15.4 Specific Exceptions

20.16 Executable

This class is used only as a common ancestor to Primitive (??sec:std-Primitive) and Code (??sec:std-Code).

20.16.1 Prototypes

20.16.2 Construction

There is no point in constructing an Executable.

20.16.3 Slots

20.17 File

20.17.1 Prototypes

20.17.2 Construction

Files may be created from a String (??sec:std-String), or from a Path (??sec:std-Path). The file must exist on the file system, and must be a file. You may use create to create a file that does not exist (or to override an existing one).

 
System.system(
"(echo 1; echo 2) >file.txt"
)|; 
File.new(
"file.txt"
); 
[00000001] File("file.txt")
 
 
File.new(Path.new(
"file.txt"
)); 
[00000001] File("file.txt")

You may use InputStream (??sec:std-InputStream) and OutputStream (??sec:std-OutputStream) to read or write to Files.

20.17.3 Slots

20.18 Finalizable

Objects that derive from this object will execute their finalize routine right before being destroyed (reclaimed) by the system. It is comparable to a destructor.

20.18.1 Example

The following object is set up to die verbosely.

 
var obj = 
  do (Finalizable.new) 
  { 
    function finalize () 
    { 
      echo (
"Ouch"
); 
    } 
  }|;

It is reclaimed by the system when it is no longer referenced by any other object.

 
var alias = obj|; 
obj = nil|;

Here, the object is still alive, since alias references it. Once it no longer does, the object dies.

 
alias = nil|; 
[00000004] *** Ouch

20.18.2 Prototypes

20.18.3 Construction

The constructor takes no argument.

 
Finalizable.new; 
[00000527] Finalizable_0x135360

Because of specific constraints of Finalizable, you cannot change the prototype of an object to make it “finalizable”: it must be an instance of Finalizable from its inception.

There, instead of these two invalid constructs,

 
class o1 : Finalizable.new 
{ 
  function finalize() 
  { 
    echo(
"Ouch"
); 
  } 
}|; 
[00000008:error] !!! <empty>: cannot inherit from a Finalizable without being a Finalizable too

 
class o2 
{ 
  protos = [Finalizable]; 
  function finalize() 
  { 
    echo(
"Ouch"
); 
  } 
}|; 
[00000010:error] !!! updateSlot: cannot inherit from a Finalizable without being a Finalizable too

write:

 
var o3 = 
  do (Finalizable.new) 
  { 
    function finalize() 
    { 
      echo(
"Ouch"
); 
    } 
  }|;

If you need multiple prototypes, do as follows.

 
class Global.Foo 
{ 
  function init() 
  { 
    echo(
"1"
); 
  }; 
}|; 
 
class Global.FinalizableFoo 
{ 
  addProto(Foo.new); 
 
  function new’() 
  { 
    var r = clone | 
    r.init | 
    Finalizable.new.addProto(r); 
  }; 
 
  function init() 
  { 
    echo(
"2"
); 
  }; 
 
  function finalize() 
  { 
    echo(
"3"
); 
  }; 
 
}|; 
 
var i = FinalizableFoo.new|; 
[00000117] *** 1
 
[00000117] *** 2
 
 
i = nil; 
[00000117] *** 3

20.18.4 Slots

20.19 Float

A Float is a floating point number. It is also used, in the current version of urbiscript, to represent integers.

20.19.1 Prototypes

20.19.2 Construction

The most common way to create fresh floats is using the literal syntax. Numbers are composed of three parts:

integral
(mandatory) a non empty sequence of (decimal) digits;
fractional
(optional) a period, and a non empty sequence of (decimal) digits;
exponent
(optional) either ‘e’ or ‘E’, an optional sign (‘+’ or ‘-’), then a non-empty sequence of digits.

In other words, float literals match the [0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)? regular expression. For instance:

 
0 == 0000.0000; 
// This is actually a call to the unary ’+’.
 
+1 == 1; 
0.123456 == 123456 / 1000000; 
1e3 == 1000; 
1e-3 == 0.001; 
1.234e3 == 1234;

There are also some special numbers, nan, inf (see below).

 
Math.log(0) == -inf; 
Math.exp(-inf) == 0; 
(inf/inf).asString == 
"nan"
;

A null float can also be obtained with Float’s new method.

 
Float.new == 0;

20.19.3 Slots

20.20 Float.limits

This singleton handles various limits related to the Float objects.

20.20.1 Slots

20.21 FormatInfo

A format info is used when formatting a la printf. It store the formatting pattern itself and all the format information it can extract from the pattern.

20.21.1 Prototypes

20.21.2 Construction

The constructor expects a string as argument, whose syntax is similar to printf’s. It is detailed below.

 
var f = FormatInfo.new(
"%+2.3d"
); 
[00000001] %+2.3d

A formatting pattern must one of the following (brackets denote optional arguments):

options is a sequence of 0 or several of the following characters:



- Left alignment.
= Centered alignment.
+ Show sign even for positive number.
‘ ’ If the string does not begin with ‘+’ or ‘-’, insert a space before the converted string.
0 Pad with 0’s (inserted after sign or base indicator).
# Show numerical base, and decimal point.


spec is the conversion character and must be one of the following:



s Default character, prints normally
d Case modifier: lowercase
D Case modifier: uppercase
x Prints in hexadecimal lowercase
X Prints in hexadecimal uppercase
o Prints in octal
e Prints floats in scientific format
E Prints floats in scientific format uppercase
f Prints floats in fixed format


20.21.3 Slots

20.22 Formatter

A formatter stores format information of a format string like used in printf in the C library or in boost::format.

20.22.1 Prototypes

20.22.2 Construction

Formatters are created with the format string. It cuts the string to separate regular parts of string and formatting patterns, and stores them.

 
Formatter.new(
"Name:%s, Surname:%s;"
); 
[00000001] Formatter ["Name:", %s, ", Surname:", %s, ";"]

Actually, formatting patterns are translated into FormatInfo (??sec:std-FormatInfo).

20.22.3 Slots

20.23 Global

Global is designed for the purpose of being global namespace. Since Global is a prototype of Object and all objects are an Object, all slots of Global are accessible from anywhere.

20.23.1 Prototypes

20.23.2 Slots

20.24 Group

A transparent means to send messages to several objects as if they were one.

20.24.1 Example

The following session demonstrates the features of the Group objects. It first creates the Sample family of object, makes a group of such object, and uses that group.

 
class Sample 
{ 
  var value = 0; 
  function init(v) { value = v; }; 
  function asString() { 
"<"
 + value.asString + 
">"
; }; 
  function timesTen() { new(value * 10); }; 
  function plusTwo()  { new(value + 2); }; 
}; 
[00000000] <0>
 
 
var group = Group.new(Sample.new(1), Sample.new(2)); 
[00000000] Group [<1>, <2>]
 
group << Sample.new(3); 
[00000000] Group [<1>, <2>, <3>]
 
group.timesTen.plusTwo; 
[00000000] Group [<12>, <22>, <32>]
 
 
// Bouncing getSlot and updateSlot.
 
group.value; 
[00000000] Group [1, 2, 3]
 
group.value = 10; 
[00000000] Group [10, 10, 10]
 
 
// Bouncing to each&.
 
var sum = 0| 
for& (var v : group) 
  sum += v.value; 
sum; 
[00000000] 30

20.24.2 Prototypes

20.24.3 Construction

Groups are created like any other object. The constructor can take members to add to the group.

 
Group.new; 
[00000000] Group []
 
Group.new(1, 
"two"
); 
[00000000] Group [1, "two"]

20.24.4 Slots

20.25 InputStream

InputStreams are used to read (possibly binary) files by hand. File (??sec:std-File) provides means to swallow a whole file either as a single large string, or a list of lines. InputStream provides a more fine-grained interface to read files.

20.25.1 Prototypes

Windows Issues

Beware that because of limitations in the current implementation, one cannot safely read from two different files at the same time under Windows.

20.25.2 Construction

An InputStream is a reading-interface to a file, so its constructor requires a File (??sec:std-File).

 
System.system(
"(echo 1; echo 2) >file.txt"
)|; 
InputStream.new(File.new(
"file.txt"
)); 
[00000001] InputStream_0x827000

20.25.3 Slots

20.26 IoService

A IoService is used to manage the various operations of a set of Socket (??sec:std-Socket).

All Socket (??sec:std-Socket) and Server (??sec:std-Server) are by default using the default IoService (??sec:std-IoService) which is polled regularly by the system.

20.26.1 Example

Using a different IoService (??sec:std-IoService) is required if you need to perform synchronous read operations.

The Socket (??sec:std-Socket) must be created by the IoService (??sec:std-IoService) that will handle it using its makeSocket function.

 
var io = IoService.new|; 
var s = io.makeSocket|;

You can then use this socket like any other.

 
// Make a simple hello server.
 
var serverPort = 0| 
do(Server.new) 
{ 
  listen(
"127.0.0.1"
, 
"0"
); 
  lobby.serverPort = port; 
  at(connection?(var s)) 
  { 
    s.write(
"hello"
); 
  } 
}|; 
// Connect to it using our socket.
 
s.connect(
"0.0.0.0"
, serverPort); 
at(s.received?(var data)) 
  echo(
"received something"
); 
s.write(
"1;"
);

... except that nothing will be read from the socket unless you call one of the poll functions of io.

 
sleep(200ms); 
s.isConnected(); 
// Nothing was received yet
 
[00000001] true
 
io.poll(); 
[00000002] *** received something
 
sleep(200ms);

20.26.2 Prototypes

20.26.3 Construction

A IoService is constructed with no argument.

20.26.4 Slots

20.27 Job

Jobs are independent threads of executions. Jobs can run concurrently. They can also be managed using Tags (??sec:std-Tag).

20.27.1 Prototypes

20.27.2 Construction

A Job is typically constructed via Control.detach, Control.disown, or System.spawn.

 
detach(sleep(10)); 
[00202654] Job<shell_4>
 
 
disown(sleep(10)); 
[00204195] Job<shell_5>
 
 
spawn (function () { sleep(10) }, false); 
[00274160] Job<shell_6>

20.27.3 Slots

20.28 Kernel1

This object plays the role of a name-space in which obsolete functions from urbiscript 1.0 are provided for backward compatibility. Do not use these functions, scheduled for removal.

20.28.1 Prototypes

20.28.2 Construction

Since it is a Singleton (??sec:std-Singleton), you are not expected to build other instances.

20.28.3 Slots

20.29 Lazy

Lazies are objects that hold a lazy value, that is, a not yet evaluated value. They provide facilities to evaluate their content only once (memoization) or several times. Lazy are essentially used in call messages, to represent lazy arguments, as described in Section 20.4.

20.29.1 Examples

20.29.1.1 Evaluating once

One usage of lazy values is to avoid evaluating an expression unless it’s actually needed, because it’s expensive or has undesired side effects. The listing below presents a situation where an expensive-to-compute value (heavy_computation) might be needed zero, one or two times. The objective is to save time by:

We thus make the wanted expression lazy, and use the value method to fetch its value when needed.

 
// This function supposedly performs expensive computations.
 
function heavy_computation() 
{ 
  echo(
"Heavy computation"
); 
  return 1 + 1; 
}|; 
 
// We want to do the heavy computations only if needed,
 
// and make it a lazy value to be able to evaluate it "on demand".
 
var v = Lazy.new(closure () { heavy_computation() }); 
[00000000] heavy_computation()
 
/* some code */
; 
// So far, the value was not needed, and heavy_computation
 
// was not evaluated.
 
/* some code */
; 
// If the value is needed, heavy_computation is evaluated.
 
v.value; 
[00000000] *** Heavy computation
 
[00000000] 2
 
// If the value is needed a second time, heavy_computation
 
// is not reevaluated.
 
v.value; 
[00000000] 2

20.29.1.2 Evaluating several times

Evaluating a lazy several times only makes sense with lazy arguments and call messages. See example with call messages in Section 20.4.1.1.

20.29.2 Caching

Lazy (??sec:std-Lazy) is meant for functions without argument. If you need caching for functions that depend on arguments, it is straightforward to implement using a Dictionary (??sec:std-Dictionary). In the future urbiscript might support dictionaries whose indices are not only strings, but in the meanwhile, convert the arguments into strings, as the following sample object demonstrates.

 
class UnaryLazy 
{ 
  function init(f) 
  { 
    results = [ => ]; 
    func = f; 
  }; 
  function value(p) 
  { 
    var sp = p.asString; 
    if (results.has(sp)) 
      return results[sp]; 
    var res = func(p); 
    results[sp] = res | 
    res 
  }; 
  var results; 
  var func; 
} | 
// The function to cache.
 
var inc = function(x) { echo(
"incing "
 + x) | x+1 } | 
// The function with cache.
 
// Use "getSlot" to get the unevaluated function.
 
var p = UnaryLazy.new(getSlot(
"inc"
)); 
[00062847] UnaryLazy_0x78b750
 
p.value(1); 
[00066758] *** incing 1
 
[00066759] 2
 
p.value(1); 
[00069058] 2
 
p.value(2); 
[00071558] *** incing 2
 
[00071559] 3
 
p.value(2); 
[00072762] 3
 
p.value(1); 
[00074562] 2

20.29.3 Prototypes

20.29.4 Construction

Lazies are seldom instantiated manually. They are mainly created automatically when a lazy function call is made (see Section 19.3.4). One can however create a lazy value with the standard new method of Lazy, giving it an argument-less function which evaluates to the value made lazy.

 
Lazy.new(closure () { 
/* Value to make lazy */
 0 }); 
[00000000] 0

20.29.5 Slots

20.30 List

Lists implement potentially-empty ordered (heterogeneous) collections of elements.

20.30.1 Prototypes

20.30.2 Construction

List can be created with their literal syntax: a possibly empty sequence of expressions in square brackets, separated by commas. Non-empty list may actually terminate with a comma, rather than separate; in other words, an optional trailing comma is accepted.

 
[]; 
// The empty list
 
[00000000] []
 
[1, 
"2"
, [3,],]; 
[00000000] [1, "2", [3]]

20.30.3 Slots

20.31 Loadable

Loadable objects can be switched on and off — typically physical devices.

20.31.1 Prototypes

20.31.2 Example

The intended use is rather as follows:

 
class Motor: Loadable 
{ 
  var val = 0; 
  function go(var d) 
  { 
    if (load) 
      val += d 
    else 
      echo(
"cannot advance, the motor is off"
)|; 
  }; 
}; 
[00000002] Motor
 
 
var m = Motor.new; 
[00000003] Motor_0xADDR
 
 
m.load; 
[00000004] false
 
 
m.go(1); 
[00000006] *** cannot advance, the motor is off
 
 
m.on; 
[00000007] Motor_0xADDR
 
 
m.go(123); 
m.val; 
[00000009] 123

20.31.3 Construction

Loadable can be constructed, but it hardly makes sense. This object should serve as a prototype.

20.31.4 Slots

20.32 Lobby

A lobby is the local environment for each (remote or local) connection to an Urbi server.

20.32.1 Prototypes

20.32.2 Construction

A lobby is implicitly created at each connection. At the top level, this is a Lobby.

 
this.protos; 
[00000001] [Lobby]
 
this.protos[0].protos; 
[00000003] [Channel_0xADDR]

Lobbies cannot be cloned, they must be created using create.

 
Lobby.new; 
[00000177:error] !!! new: Lobby objects cannot be cloned
 
Lobby.create; 
[00000174] Lobby_0x126450

20.32.3 Examples

Since every lobby is-a Channel (??sec:std-Channel), one can use the methods of Channel.

 
lobby << 123; 
[00478679] 123
 
lobby << 
"foo"
; 
[00478679] "foo"

20.32.4 Slots

20.33 Location

This class aggregates two Positions and provides a way to print them as done in error messages.

20.33.1 Prototypes

20.33.2 Construction

Without argument, a newly constructed Location has its Positions initialized to the first line and the first column.

 
Location.new; 
[00000001] 1.1

With a Position argument p, the Location will clone the Position into the begin and end Positions.

 
Location.new(Position.new(
"file.u"
,14,25)); 
[00000001] file.u:14.25

With two Positions arguments begin and end, the Location will clone both Positions into its own fields.

 
Location.new(Position.new(
"file.u"
,14,25), Position.new(
"file.u"
,14,35)); 
[00000001] file.u:14.25-34

20.33.3 Slots

20.34 Math

This object is actually meant to play the role of a name-space in which the mathematical functions are defined with a more conventional notation. Indeed, in an object-oriented language, writing pi.cos makes perfect sense, yet cos(pi) is more usual.

20.34.1 Prototypes

20.34.2 Construction

Since it is a Singleton (??sec:std-Singleton), you are not expected to build other instances.

20.34.3 Slots

20.35 Mutex

Mutex allow to define critical sections.

20.35.1 Prototypes

20.35.2 Construction

A Mutex can be constructed like any other Tag but without name.

 
var m = Mutex.new; 
[00000000] Mutex_0x964ed40

You can define critical sections by tagging your code using the Mutex.

 
var m = Mutex.new|; 
m: echo(
"this is critical section"
); 
[00000001] *** this is critical section

As a critical section, two pieces of code tagged by the same “Mutex” will never be executed at the same time.

20.35.3 Slots

20.36 nil

The special entity nil is an object used to denote an empty value. Contrary to void (??sec:std-void), it is a regular value which can be read.

20.36.1 Prototypes

20.36.2 Construction

Being a singleton, nil is not to be constructed, just used.

 
nil == nil;

20.36.3 Slots

20.37 Object

All objects in urbiscript must have Object (??sec:std-Object) in their parents. Object (??sec:std-Object) is done for this purpose so that it come with many primitives that are mandatory for all object in urbiscript.

20.37.1 Prototypes

20.37.2 Construction

Fresh object can be instantiated by cloning Object itself.

 
Object.new; 
[00000421] Object_0x00000000

The keyword class also allows to define objects which are intended to serve as prototype of a family of objects, similarly to classes in traditional object-oriented programming languages (see Section 9.4).

 
{ 
  class Foo 
  { 
    var attr = 23; 
  }; 
  assert 
  { 
    Foo.localSlotNames == [
"asFoo"
, 
"attr"
, 
"type"
]; 
    Foo.asFoo === Foo; 
    Foo.attr == 23; 
    Foo.type == 
"Foo"
; 
  }; 
};

20.37.3 Slots

20.38 Orderable

Objects that have a concept of “less than”. See also Comparable (??sec:std-Comparable).

This object, made to serve as prototype, provides a definition of < based on >, and vice versa; and definition of <=/>= based on </>==. You must define either < or >, otherwise invoking either method will result in endless recursions.

 
class Foo : Orderable 
{ 
  var value = 0; 
  function init (v) { value = v; }; 
  function ’<’ (lhs)  { value < lhs.value; }; 
  function asString() { 
"<"
 + value.asString + 
">"
; }; 
}; 
[00000000] <0>
 
var one = Foo.new(1); 
[00000001] <1>
 
var two = Foo.new(2); 
[00000002] <2>
 
 
assert( (one <= one) &&  (one <= two) && !(two <= one)); 
assert(!(one >  one) && !(one >  two) &&  (two >  one)); 
assert( (one >= one) && !(one >= two) &&  (two >= one));

20.39 OutputStream

OutputStreams are used to write (possibly binary) files by hand.

20.39.1 Prototypes

20.39.2 Construction

An OutputStream is a writing-interface to a file; its constructor requires a File (??sec:std-File). If the file already exists, content is appended to it. Remove the file beforehand if you want to override its content.

 
System.system(
"(echo 1; echo 2) >file.txt"
)|; 
OutputStream.new(File.new(
"file.txt"
)); 
[00000001] OutputStream_0x827000
 
 
OutputStream.new(File.create(
"new.txt"
)); 
[00000001] OutputStream_0x827000

20.39.3 Slots

20.40 Pair

A pair is a container storing two objects, similar in spirit to std::pair in C ++.

20.40.1 Prototype

20.40.2 Construction

A Pair is constructed with two arguments.

 
Pair.new(1, 2); 
[00000001] (1, 2)
 
 
Pair.new; 
[00000003:error] !!! Pair.init: expected 2 arguments, given 0
 
 
Pair.new(1, 2, 3, 4); 
[00000003:error] !!! Pair.init: expected 2 arguments, given 4

20.40.3 Slots

20.41 Path

A Path points to a file system entity (directory, file and so forth).

20.41.1 Prototypes

20.41.2 Construction

A Path is constructed with the string that points to the file system entity. This path can be relative or absolute.

 
Path.new(
"/path/file.u"
); 
[00000001] Path("/path/file.u")

Some minor simplifications are made, such as stripping useless ‘./’ occurrences.

 
Path.new(
"././///.//foo/"
); 
[00000002] Path("foo")

20.41.3 Slots

20.42 Pattern

Pattern class is used to make correspondences between a pattern and another Object. The visit is done either on the pattern or on the element against which the pattern is compared.

Patterns are used for the implementation of the pattern matching. So any class made compatible with the pattern matching implemented by this class will allow you to use it implicitly in your scripts.

 
[1, var a, var b] = [1, 2, 3]; 
[00000000] [1, 2, 3]
 
a; 
[00000000] 2
 
b; 
[00000000] 3

20.42.1 Prototypes

20.42.2 Construction

A Pattern can be created with any object that can be matched.

 
Pattern.new([1]); 
// create a pattern to match the list [1].
 
[00000000] Pattern_0x189ea80
 
Pattern.new(Pattern.Binding.new(
"a"
)); 
// match anything into "a".
 
[00000000] Pattern_0x18d98b0

20.42.3 Slots

20.43 Position

This class is used to handle file locations with a line, column and file name.

20.43.1 Prototypes

20.43.2 Construction

Without argument, a newly constructed Position has its fields initialized to the first line and the first column.

 
Position.new; 
[00000001] 1.1

With a position argument p, the newly constructed Position is a clone of p.

 
Position.new(Position.new(2, 3)); 
[00000001] 2.3

With two float arguments l and c, the newly constructed Position has its line and column defined and an empty file name.

 
Position.new(2, 3); 
[00000001] 2.3

With three arguments f, l and c, the newly constructed Position has its file name, line and column defined.

 
Position.new(
"file.u"
, 2, 3); 
[00000001] file.u:2.3

20.43.3 Slots

20.44 Primitive

C++ routine callable from urbiscript.

20.44.1 Prototypes

20.44.2 Construction

It is not possible to construct a Primitive.

20.44.3 Slots

20.45 Process

A Process is a separated task handled by the underneath operating system.

Windows Issues

Process is not yet supported under Windows.

20.45.1 Prototypes

20.45.2 Example

The following examples runs the cat program, a Unix standard command that simply copies on its (standard) output its (standard) input.

 
var p = Process.new(
"cat"
, []); 
[00000004] Process cat

Just created, this process is not running yet. Use run to launch it.

 
p.status; 
[00000005] not started
 
 
p.run; 
p.status; 
[00000006] running

Then we feed its input, named stdin in the Unix tradition, and close its input.

 
p.stdin << 
"1\n"
 | 
p.stdin << 
"2\n"
 | 
p.stdin << 
"3\n"
 |; 
 
p.status; 
[00000007] running
 
 
p.stdin.close;

At this stage, the status of the process is unknown, as it is running asynchronously. If it has had enough time to “see” that its input is closed, then it will have finished, otherwise we might have to wait for awhile. The method join means “wait for the process to finish”.

 
p.join; 
 
p.status; 
[00000008] exited with status 0

Finally we can check its output.

 
p.stdout.asList; 
[00000009] ["1", "2", "3"]

20.45.3 Construction

A Process needs a program name to run and a possibly-empty list of command line arguments. Calling run is required to execute the process.

 
Process.new(
"cat"
, []); 
[00000004] Process cat
 
 
Process.new(
"cat"
, [
"--version"
]); 
[00000004] Process cat

20.45.4 Slots

20.46 Profiling

Profiling is useful to get an idea of the efficiency of some small pieces of code.

20.46.1 Prototypes

20.46.2 Construction

A Profiling can be created with two arguments. The first argument is the expression which has to be profiled and the second is the number of iteration it should be run.

Creating a Profiling session prints the result of the profiled expression, the number of iterations, the number of cycles and the time of the evaluation. The number of cycles corresponds to the number of time the job is scheduled.

 
Profiling.new({1| 2| 3| 4}, 10000); 
[00000000] Profiling information
 
  Expression:       1 | 2 | 3 | 4 
  Iterations:       10000 
  Cycles:           10000 
  Total time:       1.00098 s 
  Single iteration: 0.000100098 s 
                    1 cycles 
 
 
Profiling.new({1; 2; 3; 4}, 10000); 
[00000000] Profiling information
 
  Expression:       1; 
2; 
3; 
4 
  Iterations:       10000 
  Cycles:           40000 
  Total time:       1.45856 s 
  Single iteration: 0.000145856 s 
                    4 cycles

20.47 PseudoLazy

20.48 PubSub

PubSub provides an abstraction over Barrier Barrier (??sec:std-Barrier) to queue signals for each subscriber.

20.48.1 Prototypes

20.48.2 Construction

A PubSub can be created with no arguments. Values can be published and read by each subscriber.

 
var ps = PubSub.new; 
[00000000] PubSub_0x28c1bc0

20.48.3 Slots

20.49 PubSub.Subscriber

Subscriber is created by PubSub.subscribe. It provides methods to access to the list of values published by PubSub instances.

20.49.1 Prototypes

20.49.2 Construction

A PubSub.Subscriber can be created with a call to PubSub.subscribe. This way of creating a Subscriber adds the subscriber as a watcher of values published on the instance of PubSub.

 
var ps = PubSub.new |; 
var sub = ps.subscribe; 
[00000000] Subscriber_0x28607c0

20.49.3 Slots

20.50 RangeIterable

This object is meant to be used as a prototype for objects that support an asList method, to use range-based for loops (Section 19.6.5.2).

20.50.1 Prototypes

20.50.2 Slots

20.51 Regexp

A Regexp is an object which allow you to match strings with a regular expression.

20.51.1 Prototypes

20.51.2 Construction

A Regexp is created with the regular expression once and for all, and it can be used many times to match with other strings.

 
Regexp.new(
"."
); 
[00000001] Regexp(".")

urbiscript supports Perl regular expressions, see the perlre man page. Expressions cannot be empty.

20.51.3 Slots

20.52 StackFrame

This class is meant to record backtrace (see Exception.backtrace) information.

For convenience, all snippets of code are supposed to be run after these function definitions. In this code, the getStackFrame function is used to get the first StackFrame of an exception backtrace. Backtrace of Exception (??sec:std-Exception) are filled with StackFrames when the is thrown.

 
//#push 1 "foo.u"
 
function inner () { throw Exception.new(
"test"
) }|; 
 
function getStackFrame() 
{ 
  try 
  { 
    inner 
  } 
  catch(var e) 
  { 
    e.backtrace[0] 
  }; 
}|; 
//pop

This feature is experimental. It might be changed in the future. Feedback on its use would be appreciated.

20.52.1 Construction

StackFrame are not made to be manually constructed. The initialization function expect 2 arguments, which are the name of the called function and the Location (??sec:std-Location) from which it has been called.

 
StackFrame.new(
"inner"
, 
  Location.new( 
    Position.new(
"foo.u"
, 7, 5), 
    Position.new(
"foo.u"
, 7, 10) 
  ) 
); 
[00000001] foo.u:7.5-9: inner

20.52.2 Slots

20.53 Semaphore

Semaphore are useful to limit the number of access to a limited number of resources.

20.53.1 Prototypes

20.53.2 Construction

A Semaphore can be created with as argument the number of processes allowed to enter critical sections at the same time.

 
Semaphore.new(1); 
[00000000] Semaphore_0x8c1e80

20.53.3 Slots

20.54 Server

A Server can listen to incoming connections. See Socket (??sec:std-Socket) for an example.

20.54.1 Prototypes

20.54.2 Construction

A Server is constructed with no argument. At creation, a new Server has its own slot connection. This slot is an event that is launched when a connection establishes.

 
var s = Server.new| 
s.localSlotNames; 
[00000001] ["connection"]

20.54.3 Slots

20.55 Singleton

A singleton is a prototype that cannot be cloned. All prototypes derived of Singleton are also singletons.

20.55.1 Prototypes

20.55.2 Construction

To be a singleton, the object must have Singleton as a prototype. The common way to do this is var s = Singleton.new, but this does not work : s is not a new singleton, it is the Singleton itself since it cannot be cloned. There are two other ways:

 
// Defining a new class and specifying Singleton as a parent.
 
class NewSingleton1: Singleton 
{ 
  var asString = 
"NewSingleton1"
; 
}| 
var s1 = NewSingleton1.new; 
[00000001] NewSingleton1
 
assert(s1 === NewSingleton1); 
assert(NewSingleton1 !== Singleton); 
 
// Create a new Object and set its prototype by hand.
 
var NewSingleton2 = Object.new| 
var NewSingleton2.asString = 
"NewSingleton2"
| 
NewSingleton2.protos = [Singleton]| 
var s2 = NewSingleton2.new; 
[00000001] NewSingleton2
 
assert(s2 === NewSingleton2); 
assert(NewSingleton2 !== Singleton);

20.55.3 Slots

20.56 Socket

A Socket can manage asynchronous input/output network connections.

20.56.1 Example

The following example demonstrates how both the Server (??sec:std-Server) and Socket (??sec:std-Socket) object work.

This simple example will establish a dialog between server and client. The following object, Dialog, contains the script of this exchange. It is put into Global so that both the server and client can read it. Dialog.reply(var s) returns the reply to a message s.

 
class Global.Dialog 
{ 
  var lines = 
  [ 
    
"Hi!"
, 
    
"Hey!"
, 
    
"Hey you doin’?"
, 
    
"Whazaaa!"
, 
    
"See ya."
, 
  ]|; 
 
  function reply(var s) 
  { 
    for (var i: lines.size - 1) 
      if (s == lines[i]) 
        return lines[i + 1]; 
    
"off"
; 
  } 
}|;

The server, an instance of Server (??sec:std-Server), expects incoming connections, notified by the socket’s connection? event. Once the connection establish, it listens to the socket for incoming messages, notified by the received? event. Its reaction to this event is to send the following line of the dialog. At the end of the dialog, the socket is disconnected.

 
var server = 
  do (Server.new) 
  { 
    at (connection?(var socket)) 
      at (socket.received?(var data)) 
      { 
        var reply = Dialog.reply(data); 
        socket.write(reply); 
        echo(
"server: "
 + reply); 
        if (reply == 
"off"
) 
          socket.disconnect; 
      }; 
  }|;

The client, an instance of Socket (??sec:std-Socket) expects incoming messages, notified by the received? event. Its reaction is to send the following line of the dialog.

 
var client = 
  do (Socket.new) 
  { 
    at (received?(var data)) 
    { 
      var reply = Dialog.reply(data); 
      write(reply); 
      echo(
"client: "
 + reply); 
    }; 
  }|;

As of today, urbiscript’s socket machinery requires to be regularly polled.

 
every (100ms) 
  Socket.poll,

The server is then activated, listening to incoming connections on a port that will be chosen by the system amongst the free ones.

 
server.listen(
"localhost"
, 
"0"
); 
clog << 
"connecting to %s:%s"
 % [server.host, server.port];

The client connects to the server, and initiates the dialog.

 
client.connect(server.host, server.port); 
echo(
"client: "
 + Dialog.lines[0]); 
client.write(Dialog.lines[0]); 
[00000003] *** client: Hi!

Because this dialog is asynchronous, the easiest way to wait for the dialog to finish is to wait for the disconnected? event.

 
waituntil(client.disconnected?); 
[00000004] *** server: Hey!
 
[00000005] *** client: Hey you doin’?
 
[00000006] *** server: Whazaaa!
 
[00000007] *** client: See ya.
 
[00000008] *** server: off

20.56.2 Prototypes

20.56.3 Construction

A Socket is constructed with no argument. At creation, a new Socket has four own slots: connected, disconnected, error and received.

 
var s = Socket.new|

20.56.4 Slots

20.57 String

A string is a sequence of characters.

20.57.1 Prototypes

20.57.2 Construction

Fresh Strings can easily be built using the literal syntax. Several escaping sequences (the traditional ones and urbiscript specific ones) allow to insert special characters. Consecutive string literals are merged together. See Section 19.1.6.6 for details and examples.

A null String can also be obtained with String’s new method.

 
String.new == 
""
; 
String == 
""
; 
"123"
.new == 
"123"
;

20.57.3 Slots

20.58 System

Details on the architecture the Urbi server runs on.

20.58.1 Prototypes

20.58.2 Slots

20.59 System.PackageInfo

Information about Urbi SDK and its components.

20.60 System.Platform

A description of the platform (the computer) the server is running on.

20.61 Tag

A tag is an object meant to label blocks of code in order to control them externally. Tagged code can be frozen, resumed, stopped…See also Section 11.3.

20.61.1 Examples

20.61.1.1 Stop

To stop a tag means to kill all the code currently running that it labels. It does not affect “newcomers”.

 
var t = Tag.new|; 
var t0 = time|; 
t: every(1s) echo(
"foo"
), 
sleep(2.2s); 
[00000158] *** foo
 
[00001159] *** foo
 
[00002159] *** foo
 
 
t.stop; 
// Nothing runs.
 
sleep(2.2s); 
 
t: every(1s) echo(
"bar"
), 
sleep(2.2s); 
[00000158] *** bar
 
[00001159] *** bar
 
[00002159] *** bar
 
 
t.stop;

System.stop can be used to inject a return value to a tagged expression.

 
var t = Tag.new|; 
var res; 
detach(res = { t: every(1s) echo(
"computing"
) })|; 
sleep(2.2s); 
[00000001] *** computing
 
[00000002] *** computing
 
[00000003] *** computing
 
 
t.stop(
"result"
); 
assert(res == 
"result"
);

Be extremely cautious, the precedence rules can be misleading: var = tag: exp is read as (var = tag): exp (i.e., defining var as an alias to tag and using it to tag exp), not as var = { tag: exp }. Contrast the following example, which is most probably an error from the user, with the previous, correct, one.

 
var t = Tag.new(
"t"
)|; 
var res; 
res = t: every(1s) echo(
"computing"
), 
sleep(2.2s); 
[00000001] *** computing
 
[00000002] *** computing
 
[00000003] *** computing
 
 
t.stop(
"result"
); 
assert(res == 
"result"
); 
[00000004:error] !!! failed assertion: res == "result" (Tag<t> != "result")

20.61.1.2 Block/unblock

To block a tag means:

One can unblock the tag. Contrary to freeze/unfreeze, tagged code does not resume the execution.

 
var ping = Tag.new(
"ping"
)|; 
ping: 
  every (1s) 
    echo(
"ping"
), 
assert(!ping.blocked); 
sleep(2.1s); 
[00000000] *** ping
 
[00002000] *** ping
 
[00002000] *** ping
 
 
ping.block; 
assert(ping.blocked); 
 
ping: 
  every (1s) 
    echo(
"pong"
), 
 
// Neither new nor old code runs.
 
ping.unblock; 
assert(!ping.blocked); 
sleep(2.1s); 
 
// But we can use the tag again.
 
ping: 
  every (1s) 
    echo(
"ping again"
), 
sleep(2.1s); 
[00004000] *** ping again
 
[00005000] *** ping again
 
[00006000] *** ping again

As with stop, one can force the value of stopped expressions.

 
[
"foo"
, 
"foo"
, 
"foo"
] 
== 
{ 
  var t = Tag.new; 
  var res = []; 
  for (3) 
    detach(res << {t: sleep(inf)}); 
  t.block(
"foo"
); 
  res; 
};

20.61.1.3 Freeze/unfreeze

To freeze a tag means holding the execution of code it labels. This applies to code already being run, and “arriving” pieces of code.

 
var t = Tag.new|; 
var t0 = time|; 
t: every(1s) echo(
"time   : %.0f"
 % (time - t0)), 
sleep(2.2s); 
[00000158] *** time   : 0
 
[00001159] *** time   : 1
 
[00002159] *** time   : 2
 
 
t.freeze; 
assert(t.frozen); 
t: every(1s) echo(
"shifted: %.0f"
 % (shiftedTime - t0)), 
sleep(2.2s); 
// The tag is frozen, nothing is run.
 
 
// Unfreeze the tag: suspended code is resumed.
 
// Note the difference between "time" and "shiftedTime".
 
t.unfreeze; 
assert(!t.frozen); 
sleep(2.2s); 
[00004559] *** shifted: 2
 
[00005361] *** time   : 5
 
[00005560] *** shifted: 3
 
[00006362] *** time   : 6
 
[00006562] *** shifted: 4

20.61.1.4 Scope tags

Scopes feature a scopeTag, i.e., a tag which will be stop when the execution reaches the end of the current scope. This is handy to implement cleanups, how ever the scope was exited from.

 
{ 
  var t = scopeTag; 
  t: every(1s) 
      echo(
"foo"
), 
  sleep(2.2s); 
}; 
[00006562] *** foo
 
[00006562] *** foo
 
[00006562] *** foo
 
 
{ 
  var t = scopeTag; 
  t: every(1s) 
      echo(
"bar"
), 
  sleep(2.2s); 
  throw 42; 
}; 
[00006562] *** bar
 
[00006562] *** bar
 
[00006562] *** bar
 
[00006562:error] !!! 42
 
sleep(2s);

20.61.1.5 Enter/leave events

Tags provide two events, enter and leave, that trigger whenever flow control enters or leaves statements the tag.

 
var t = Tag.new(
"t"
); 
[00000000] Tag<t>
 
 
at (t.enter?) 
  echo(
"enter"
); 
at (t.leave?) 
  echo(
"leave"
); 
 
t: {echo(
"inside"
); 42}; 
[00000000] *** enter
 
[00000000] *** inside
 
[00000000] *** leave
 
[00000000] 42

This feature is fundamental; it is a concise and safe way to ensure code will be executed upon exiting a chunk of code (like raii in C ++ or finally in Java). The exit code will be run no matter what the reason for leaving the block was: natural exit, exceptions, flow control statements like return or break, …

For instance, suppose we want to make sure we turn the gas off when we’re done cooking. Here is the bad way to do it:

 
{ 
  function cook() 
  { 
    turn_gas_on(); 
 
    
// Cooking code ...
 
 
    turn_gas_off(); 
  }| 
 
  enter_the_kitchen(); 
  cook(); 
  leave_the_kitchen(); 
};

This is wrong because there are several situations where we could leave the kitchen with gas still turned on. Consider the following cooking code:

 
{ 
  function cook() 
  { 
    turn_gas_on(); 
 
    if (meal_ready) 
    { 
      echo(
"The meal is already there, nothing to do!"
); 
      
// Oops ...
 
      return 
    }; 
 
    for (var ingredient in recipe) 
      if (ingredient not in kitchen) 
        
// Oops ...
 
        throw Exception(
"missing ingredient: %s"
 % ingredient) 
      else 
        put_ingredient(); 
 
    
// ...
 
 
    turn_gas_off(); 
  }| 
 
  enter_the_kitchen(); 
  cook(); 
  leave_the_kitchen(); 
};

Here, if the meal was already prepared, or if an ingredient is missing, we will leave the cook function without executing the turn_gas_off statement, through the return statement or the exception. The right way to ensure gas is necessarily turned off is:

 
{ 
  function cook() 
  { 
    var with_gas = Tag.new(
"with_gas"
); 
 
    at (with_gas.enter?) 
      turn_gas_on(); 
    at (with_gas.leave?) 
      turn_gas_off(); 
 
    with_gas: { 
      
// Cooking code. Even if exception are thrown here or return is called,
 
      
// the gas will be turned off.
 
    } 
  }| 
 
  enter_the_kitchen(); 
  cook(); 
  leave_the_kitchen(); 
};

20.61.1.6 Begin/end

The begin and end methods enable to monitor when code is executed. The following example illustrates the proper use of enter and leave events (Section 20.61.1.5), which are used to implement this feature.

 
var mytag = Tag.new(
"mytag"
); 
[00000000] Tag<mytag>
 
 
mytag.begin: echo(1); 
[00000000] *** mytag: begin
 
[00000000] *** 1
 
 
mytag.end: echo(2); 
[00000000] *** 2
 
[00000000] *** mytag: end
 
 
mytag.begin.end: echo(3); 
[00000000] *** mytag: begin
 
[00000000] *** 3
 
[00000000] *** mytag: end

20.61.2 Construction

As any object, tags are created using new to create derivatives of the Tag object. The name is optional, it makes easier to display a tag and remember what it is.

 
// Anonymous tag.
 
var t1 = Tag.new; 
[00000001] Tag<tag_8>
 
 
// Named tag.
 
var t2 = Tag.new(
"cool name"
); 
[00000001] Tag<cool name>

20.61.3 Slots

20.61.4 Hierarchical tags

Tags can be arranged in a parent/child relationship: any operation done on a tag — freezing, stopping, …is also performed on its descendants. Another way to see it is that tagging a piece of code with a child will also tag it with the parent. To create a child Tag, simply clone its parent.

 
var parent = Tag.new | 
var child = parent.clone | 
 
// Stopping parent also stops children.
 
{ 
  parent: {sleep(100ms); echo(
"parent"
)}, 
  child:  {sleep(100ms); echo(
"child"
)}, 
  parent.stop; 
  sleep(200ms); 
  echo(
"end"
); 
}; 
[00000001] *** end
 
 
// Stopping child has no effect on parent.
 
{ 
  parent: {sleep(100ms); echo(
"parent"
)}, 
  child:  {sleep(100ms); echo(
"child"
)}, 
  child.stop; 
  sleep(200ms); 
  echo(
"end"
); 
}; 
[00000002] *** parent
 
[00000003] *** end

Hierarchical tags are commonly laid out in slots so as to reflect their tag hierarchy.

 
var a = Tag.new; 
var a.b = a.clone; 
var a.b.c = a.b.clone; 
 
a:     foo; 
// Tagged by a
 
a.b:   bar; 
// Tagged by a and b
 
a.b.c: baz; 
// Tagged by a, b and c

20.62 Timeout

Timeout objects can be used as Tags (??sec:std-Tag) to execute some code in limited time.

20.62.1 Prototypes

20.62.2 Construction

At construction, a Timeout takes a duration, and a Boolean (??sec:std-Boolean) stating whether an exception should be thrown on timeout (by default, it does).

 
Timeout.new(300ms); 
[00000000] Timeout_0x953c1e0
 
Timeout.new(300ms, false); 
[00000000] Timeout_0x953c1e0

20.62.3 Examples

Use it as a tag:

 
var t = Timeout.new(300ms); 
[00000000] Timeout_0x133ec0
 
t:{ 
  echo(
"This will be displayed."
); 
  sleep(500ms); 
  echo(
"This will not."
); 
}; 
[00000000] *** This will be displayed.
 
[00000007:error] !!! Timeout_0x133ec0 has timed out.

The same Timeout, t can be reused. It is armed again each time it is used to tag some code.

 
t: { echo(
"Open"
); sleep(1s); echo(
"Close"
); }; 
[00000007] *** Open
 
[00000007:error] !!! Timeout_0x133ec0 has timed out.
 
t: { echo(
"Open"
); sleep(1s); echo(
"Close"
); }; 
[00000007] *** Open
 
[00000007:error] !!! Timeout_0x133ec0 has timed out.

Even if exceptions have been disabled, you can check whether the count-down expired with timedOut.

 
t:sleep(500ms); 
[00000007:error] !!! Timeout_0x133ec0 has timed out.
 
if (t.timedOut) 
  echo(
"The Timeout expired."
); 
[00000000] *** The Timeout expired.

20.62.4 Slots

20.63 TrajectoryGenerator

The trajectory generators change the value of a given variable from an initial value to a target value. They can be open-loop, i.e., the intermediate values depend only on the initial and/or target value of the variable; or closed-loop, i.e., the intermediate values also depend on the current value value of the variable.

Open-loop trajectories are insensitive to changes made elsewhere to the variable. Closed-loop trajectories are sensitive to changes made elsewhere to the variable — for instance when the human physically changes the position of a robot’s motor.

Trajectory generators are not made to be used directly, rather use the “continuous assignment” syntax (Section 19.10).

20.63.1 Prototypes

20.63.2 Examples

20.63.2.1 Accel

The Accel trajectory reaches a target value at a fixed acceleration (accel attribute).

 
var y = 0; 
y = 50 accel:10,
PICTPICT

20.63.2.2 Cos

The Cos trajectory implements a cosine around the target value, given an amplitude (ampli attribute) and period (cos attribute).

This trajectory is not “smooth”: the initial value of the variable is not taken into account.

 
var y = 0; 
y = 0 cos:2s ampli:10,
PICTPICT

20.63.2.3 Sin

The Sin trajectory implements a sine around the target value, given an amplitude (ampli attribute) and period (sin attribute).

This trajectory is not “smooth”: the initial value of the variable is not taken into account.

 
var y = 0; 
y = 0 sin:2s ampli:10,
PICTPICT

20.63.2.4 Smooth

The Smooth trajectory implements a sigmoid. It changes the variable from its current value to the target value “smoothly” in a given amount of time (smooth attribute).

 
var y = 0; 
{ 
  sleep(0.5s); 
  y = 100 smooth:3s, 
},
PICTPICT

20.63.2.5 Speed

The Speed trajectory changes the value of the variable from its current value to the target value at a fixed speed (the speed attribute).

 
var y = 0; 
assign: y = 20 speed: 5, 
{ 
  sleep(1s); 
  y = 10; 
  sleep(1s); 
  y = 4; 
},
PICTPICT

If the adaptive attribute is set to true, then the duration of the trajectory is constantly reevaluated.

 
var y = 0; 
assign: y = 20 speed: 5 adaptive: true, 
{ 
  sleep(1s); 
  y = 10; 
  sleep(1s); 
  y = 4; 
},
PICTPICT

20.63.2.6 Time

The Time trajectory changes the value of the variable from its current value to the target value within a given duration (the time attribute).

 
var y = 0; 
assign: y = 20 time:3s, 
{ 
  sleep(2s); 
  y = 30; 
},
PICTPICT

If the adaptive attribute is set to true, then the duration of the trajectory is constantly reevaluated.

 
var y = 0; 
assign: y = 20 time:3s adaptive: true, 
{ 
  sleep(2s); 
  y = 30; 
},
PICTPICT

20.63.2.7 Trajectories and Tags

Trajectories can be managed using Tags (??sec:std-Tag). Stopping or blocking a tag that manages a trajectory kill the trajectory.

 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 
{ 
  sleep(1.5s); 
  assign.stop; 
},
PICTPICT
 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 
{ 
  sleep(1.5s); 
  assign.block; 
  sleep(1s); 
  assign.unblock; 
},
PICTPICT

When a trajectory is frozen, its local time is frozen too, the movement proceeds from where it was rather than from where it would have been had it been not frozen.

 
var y = 0; 
assign: y = 0 cos:2s ampli:10, 
{ 
  sleep(1.5s); 
  assign.freeze; 
  sleep(1s); 
  assign.unfreeze; 
},
PICTPICT

20.63.3 Construction

You are not expected to construct trajectory generators by hand, using modifiers is the recommended way to construct trajectories. See Section 19.10 for details about trajectories, and see Section 20.63.2 for an extensive set of examples.

20.63.4 Slots

20.64 Triplet

A triplet (or triple) is a container storing three objects.

20.64.1 Prototype

20.64.2 Construction

A Triplet is constructed with three arguments.

 
Triplet.new(1, 2, 3); 
[00000001] (1, 2, 3)
 
 
Triplet.new(1, 2); 
[00000003:error] !!! Triplet.init: expected 3 arguments, given 2
 
 
Triplet.new(1, 2, 3, 4); 
[00000003:error] !!! Triplet.init: expected 3 arguments, given 4

20.64.3 Slots

20.65 Tuple

A tuple is a container storing a fixed number of objects. Examples include Pair (??sec:std-Pair) and Triplet (??sec:std-Triplet).

20.65.1 Prototype

20.65.2 Construction

The Tuple object is not meant to be instantiated, its main purpose is to share code for its descendants, such as Pair (??sec:std-Pair). Yet it accepts its members as a list.

 
var t = Tuple.new([1, 2, 3]); 
[00000000] (1, 2, 3)

The output generated for a Tuple can also be used to create a Tuple. Expressions are put inside parentheses and separated by commas. One extra comma is allowed after the last element. To avoid confusion between a 1 member Tuple and a parenthesized expression, the extra comma must be added. Tuple with no expressions are also accepted.

 
// not a Tuple
 
(1); 
[00000000] 1
 
 
// Tuples
 
(); 
[00000000] ()
 
(1,); 
[00000000] (1,)
 
(1, 2); 
[00000000] (1, 2)
 
(1, 2, 3, 4,); 
[00000000] (1, 2, 3, 4)

20.65.3 Slots

20.66 UObject

UObject is used by the UObject API (see Chapter I) to represent a bound C ++ instance.

All the UObjects are copied under an unique name as slots of uobjects.

20.66.1 Prototypes

20.66.2 Slots

20.67 UValue

The UValue object is used internally by the UObject API and is mostly hidden from the user.

20.68 UVar

This class is used internally by the UObject middleware (see Chapter I) to represent a variable that can be hooked in C++. Each slot on which a C++ urbi::UVar exists contains an instance of this class.

Instances of UVar are mostly transparent, they appear as the value they contain. Thus, since the UVar evaluates to the contained value, you must use getSlot to manipulate the UVar itself.

20.68.1 Construction

To instantiate a new UVar, pass the owner object and the slot name to the constructor.

 
UVar.new(Global, 
"x"
)| 
Global.x = 5; 
[000000001] 5
 
x; 
[000000002] 5

20.68.2 Prototypes

20.68.3 Slots

20.69 void

The special entity void is an object used to denote “no value”. It has no prototype and cannot be used as a value. In contrast with nil (??sec:std-nil), which is a valid object, void denotes a value one is not allowed to read.

20.69.1 Prototypes

None.

20.69.2 Construction

void is the value returned by constructs that return no value.

 
void.isVoid; 
{}.isVoid; 
{if (false) 123}.isVoid;

20.69.3 Slots