23.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.
A Barrier can be created with no argument. Calls to signal and wait done on this instance are
restricted to this instance.
Barrier.new;
[00000000] Barrier_0x25d2280
- signal(payload)
Wake up one of the job waiting for a signal. The payload is sent to the wait method.
Return the number of jobs woken up.
do (Barrier.new)
{
echo(wait) &
echo(wait) &
assert
{
signal(1) == 1;
signal(2) == 1;
}
}|;
[00000000] *** 1
[00000000] *** 2
- signalAll(payload)
Wake up all the jobs waiting for a signal. The payload is sent to all wait methods. Return the
number of jobs woken up.
do (Barrier.new)
{
echo(wait) &
echo(wait) &
assert
{
signalAll(1) == 2;
signalAll(2) == 0;
}
}|;
[00000000] *** 1
[00000000] *** 1
- wait
Block until a signal is received. The payload sent with the signal function is returned by the
wait method.
do (Barrier.new)
{
echo(wait) &
signal(1)
}|;
[00000000] *** 1
23.2 Binary
A Binary object, sometimes called a blob, is raw memory, decorated with a user defined
header.
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.
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.
23.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.
The objects true and false have the following prototype.
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;
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:
- false, nil
false.
- raise an error.
- false iff null (Float).
- Dictionary, List, String
false iff empty (Dictionary, List, String).
- otherwise
true.
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
- ’!’
Logical negation. If this is false return true and vice-versa.
!true == false;
!false == true;
- asBool
Identity.
true.asBool == true;
false.asBool == false;
23.4 CallMessage
Capturing a method invocation: its target and arguments.
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
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
- args
The list of not yet evaluated arguments.
function args { call.args }|
assert
{
args == [];
args() == [];
args({echo(111); 1}) == [Lazy.new(closure() {echo(111); 1})];
args(1, 2) == [Lazy.new(closure () {1}),
Lazy.new(closure () {2})];
};
- argsCount
The number of arguments. Do not evaluate them.
function argsCount { call.argsCount }|;
assert
{
argsCount == 0;
argsCount() == 0;
argsCount({echo(1); 1}) == 1;
argsCount({echo(1); 1}, {echo(2); 2}) == 2;
};
- code
The body of the called function as a Code.
function code { call.getSlot("code") }|
assert (code == getSlot("code"));
- eval
Evaluate this, and return the result.
var c1 = do (CallMessage.new)
{
var this.target = 1;
var this.message = "+";
var this.args = [Lazy.new(function () {2})];
}|
assert { c1.eval == 3 };
// A lazy function that returns the sum of this and the second argument,
// regardless of the first argument.
function Float.addSecond
{
this + call.evalArgAt(1);
}|
var c2 = do (CallMessage.new)
{
var this.target = 2;
var this.message = "addSecond";
var this.args = [Lazy.new(function (){ assert (false) }),
Lazy.new(function (){ echo (5); 5 })];
}|
assert { c2.eval == 7 };
[00000454] *** 5
- evalArgAt(n)
Evaluate the n-th argument, and return its value. n must evaluate to an non-negative integer.
Repeated invocations repeat the evaluation, see Section 23.4.1.1.
function sumTwice
{
var n = call.evalArgAt(0);
call.evalArgAt(n) + call.evalArgAt(n)
}|;
function one () { echo("one"); 1 }|;
sumTwice(1, one, one + one);
[00000008] *** one
[00000009] *** one
[00000010] 2
sumTwice(2, one, one + one);
[00000011] *** one
[00000012] *** one
[00000011] *** one
[00000012] *** one
[00000013] 4
sumTwice(3, one, one);
[00000014:error] !!! evalArgAt: invalid index: 3
[00000014:error] !!! called from: sumTwice
sumTwice(3.14, one, one);
[00000015:error] !!! evalArgAt: invalid index: 3.14
[00000015:error] !!! called from: sumTwice
- evalArgs
Call evalArgAt for each argument, return the list of values.
function twice
{
call.evalArgs + call.evalArgs
}|;
twice({echo(1); 1}, {echo(2); 2});
[00000011] *** 1
[00000012] *** 2
[00000011] *** 1
[00000012] *** 2
[00000013] [1, 2, 1, 2]
- message
The name under which the function was called.
function myself { call.message }|
assert(myself == "myself");
- sender
The object from which the invocation was made (the caller in other languages). Not to be
confused with target.
function Global.getSender { call.sender } |
function Global.callGetSender { getSender } |
assert
{
// Call from the current Lobby, with the Lobby as target.
getSender === lobby;
// Call from the current Lobby, with Global as the target.
Global.getSender === lobby;
// Ask Lobby to call getSender.
callGetSender === lobby;
// Ask Global to call getSender.
Global.callGetSender === Global;
};
- target
The object on which the invocation is made. In other words, the object that will be bound to
this during the evaluation. Not to be confused with sender.
function Global.getTarget { call.target } |
function Global.callGetTarget { getTarget } |
assert
{
// Call from the current Lobby, with the Lobby as target.
getTarget === lobby;
// Call from the current Lobby, with Global as the target.
Global.getTarget === Global;
// Ask Lobby to call getTarget.
callGetTarget === lobby;
// Ask Global to call getTarget.
Global.callGetTarget === Global;
};
23.5 Channel
Returning data, typically asynchronous, with a label so that the “caller” can find it in the
flow.
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
23.6 Code
Functions written in urbiscript.
The keywords function and closure build Code instances.
function(){}.protos[0] === &Code;
closure (){}.protos[0] === &Code;
- Whether this and that are the same source code (actually checks that both have the
same asString), and same closed values.
Closures and functions are different, even if the body is the same.
function () { 1 } == function () { 1 };
function () { 1 } != closure () { 1 };
closure () { 1 } != function () { 1 };
closure () { 1 } == closure () { 1 };
No form of equivalence is applied on the body, it must be the same.
function () { 1 + 1 } == function () { 1 + 1 };
function () { 1 + 2 } != function () { 2 + 1 };
Arguments do matter, even if in practice the functions are the same.
function (var ignored) {} != function () {};
function (var x) { x } != function (y) { y };
A lazy function cannot be equal to a strict one.
function () { 1 } != function { 1 };
If the functions capture different variables, they are different.
{
var x;
function Global.capture_x() { x };
function Global.capture_x_again () { x };
{
var x;
function Global.capture_another_x() { x };
}
}|;
assert
{
&capture_x == &capture_x_again;
&capture_x != &capture_another_x;
};
If the functions capture different targets, they are different.
class Foo
{
function makeFunction() { function () {} };
function makeClosure() { closure () {} };
}|;
class Bar
{
function makeFunction() { function () {} };
function makeClosure() { closure () {} };
}|;
assert
{
Foo.makeFunction() == Bar.makeFunction();
Foo.makeClosure() != Bar.makeClosure();
};
- apply(args)
Invoke the routine, with all the arguments. The target, this, will be set to args[0] and the
remaining arguments with be given as arguments.
function (x, y) { x+y }.apply([nil, 10, 20]) == 30;
function () { this }.apply([123]) == 123;
// There is Object.apply.
1.apply([this]) == 1;
function () {}.apply([]);
[00000001:error] !!! apply: argument list must begin with ‘this’
function () {}.apply([1, 2]);
[00000002:error] !!! apply: expected 0 argument, given 1
- asString
Conversion to String.
closure () { 1 }.asString == "closure () { 1 }";
function () { 1 }.asString == "function () { 1 }";
- bodyString
Conversion to String of the routine body.
closure () { 1 }.bodyString == "1";
function () { 1 }.bodyString == "1";
23.7 Comparable
Objects that can be compared for equality and inequality. See also 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 ’==’ (that) { value == that.value; };
}|;
assert
{
Foo.new(1) == Foo.new(1);
Foo.new(1) != Foo.new(2);
};
- Whether ! (this != that).
class FortyTwo : Comparable
{
function ’!=’ (that) { 42 != that };
}|;
assert
{
FortyTwo != 51;
FortyTwo == 42;
};
- !=’(\var{that})Whether ! (this == that).
class FiftyOne : Comparable
{
function ’==’ (that) { 51 == that };
}|;
assert
{
FiftyOne == 51;
FiftyOne != 42;
};
23.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.
- has(e)
!hasNot(e). The indented semantics is “true when the container has a key (or item)
matching e”. This is what e in c is mapped onto.
class NotCell : Container
{
var val;
function init(var v) { val = v };
function hasNot(var v) { val != v };
}|;
var c = NotCell.new(23)|;
assert
{
c.has(23); 23 in c;
c.hasNot(3); 3 not in c;
};
- hasNot(e)
!has(e). The indented semantics is “true when the container does not have a key (or item)
matching e”.
class Cell : Container
{
var val;
function init(var v) { val = v };
function has(var v) { val == v };
}|;
var d = Cell.new(23)|;
assert
{
d.has(23); 23 in d;
d.hasNot(3); 3 not in d;
};
23.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.
23.10 Date
This class is meant to record dates in time, with microsecond resolution.
This feature is experimental. It might be changed in the future. Feedback on its use
would be appreciated.
Without argument, newly constructed Dates refer to the current date.
Date.new;
[00000001] 2010-08-17 14:40:52.549726
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:637");
[00000001] 2003-10-10 20:10:50.637000
Date.new("2003-10-10 20:10:50");
[00000001] 2003-10-10 20:10:50.000000
Date.new("2003-Oct-10 20:10");
[00000002] 2003-10-10 20:10:00.000000
Date.new("2003-10-10 20");
[00000003] 2003-10-10 20:00:00.000000
Pay attention that the format is rather strict; for instance too many spaces between day and time
result in an error.
Date.new("2003-10-10 20:10:50");
[00001968:error] !!! new: cannot convert to date: 2003-10-10 20:10:50
Pay attention that the format is not strict enough either; for instance, below, the ‘.’ separator seem
to prefix microseconds, but actually merely denotes the minutes. Seconds must be spelled out in order
to introduce microseconds.
Date.new("2003-10-10 00.12");
[00000003] 2003-10-10 00:12:00.000000
Date.new("2003-10-10 00:00.12");
[00000003] 2003-10-10 00:00:12.000000
23.11 Dictionary
A dictionary is an associative array, also known as a hash in some programming languages. They
are arrays whose indexes are arbitrary objects.
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
Arbitrary objects can be used as dictionary keys. To map to the same cell, two objects used as keys
must have equal hashes (retrieved with the Object.hash method) and be equal to each other (in the
Object.’==’ sense).
This means that two different objects may have the same hash: the equality operator
(Object.’==’) is checked in addition to the hash, to handle such collision. However a good hash
algorithm should avoid this case, since it hinders performances.
See Object.hash for more detail on how to override hash values. Most standard value-based
classes implement a reasonable hash function: see Float.hash, String.hash, List.hash,
…
The Dictionary constructor takes arguments by pair (key, value).
Dictionary.new("one", 1, "two", 2);
[00000000] ["one" => 1, "two" => 2]
Dictionary.new;
[00000000] [ => ]
There must be an even number of arguments.
Dictionary.new("1", 2, "3");
[00000001:error] !!! new: odd number of arguments
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]
It is guaranteed that the pairs to insert are evaluated left-to-write, key first, the value.
["a".fresh => "b".fresh, "c".fresh => "d".fresh]
== ["a_5" => "b_6", "c_7" => "d_8"];
- ’==’(that)
Whether this equals that. This suppose that elements contained inside the dictionary are
Comparable.
[ => ] == [ => ];
["a" => 1, "b" => 2] == ["b" => 2, "a" => 1];
- ’[]’(key)
Syntactic sugar for get(key).
assert (["one" => 1]["one"] == 1);
["one" => 1]["two"];
[00000012:error] !!! missing key: two
- ’[]=’(key, value)
Syntactic sugar for set(key, value), but returns value.
{
var d = ["one" =>"2"];
assert
{
(d["one"] = 1) == 1;
d["one"] == 1;
};
};
- asBool
Negation of empty.
[=>].asBool == false;
["key" => "value"].asBool == true;
- asList
The contents of the dictionary as a Pair list (key, value).
["one" => 1, "two" => 2].asList == [("one", 1), ("two", 2)];
Since Dictionary derives from RangeIterable, it is easy to iterate over a Dictionary using a
range-for (Section 22.7.5.2). No particular order is ensured.
{
var res = [];
for| (var entry: ["one" => 1, "two" => 2])
res << entry.second;
assert(res == [1, 2]);
};
- asString
A string representing the dictionary. There is no guarantee on the order of the output.
[=>].asString == "[ => ]";
["a" => 1, "b" => 2].asString == "[\"a\" => 1, \"b\" => 2]";
- elementAdded
An event emitted each time a new element is added to the Dictionary.
- elementChanged
An event emitted each time the value associated to a key of the Dictionary is changed.
- elementRemoved
An event emitted each time an element is removed from the Dictionary.
d = [ => ] |;
at(d.elementAdded?) echo ("added");
at(d.elementChanged?) echo ("changed");
at(d.elementRemoved?) echo ("removed");
d["key1"] = "value1";
[00000001] "value1"
[00000001] *** added
d["key2"] = "value2";
[00000001] "value2"
[00000001] *** added
d["key2"] = "value3";
[00000001] "value3"
[00000001] *** changed
d.erase("key2");
[00000002] ["key1" => "value1"]
[00000001] *** removed
d.clear;
[00000003] [ => ]
[00000001] *** removed
d.clear;
[00000003] [ => ]
- clear
Empty the dictionary.
["one" => 1].clear.empty;
- empty
Whether the dictionary is empty.
[=>].empty == true;
["key" => "value"].empty == false;
- erase(key)
Remove the mapping for key.
{
var d = ["one" => 1, "two" => 2];
assert
{
d.erase("two") === d;
d == ["one" => 1];
};
try
{
["one" => 1, "two" => 2].erase("three");
echo("never reached");
}
catch (var e if e.isA(Dictionary.KeyError))
{
assert(e.key == "three")
};
};
- get(key)
The value associated to key. A Dictionary.KeyError exception is thrown if the key is missing.
var d = ["one" => 1, "two" => 2]|;
assert(d.get("one") == 1);
["one" => 1, "two" => 2].get("three");
[00000010:error] !!! missing key: three
try
{
d.get("three");
echo("never reached");
}
catch (var e if e.isA(Dictionary.KeyError))
{
assert(e.key == "three")
};
- getWithDefault(key, defaultValue)
The value associated to key if it exists, defaultValue otherwise.
{
var d = ["one" => 1, "two" => 2];
assert
{
d.getWithDefault("one", -1) == 1;
d.getWithDefault("three", 3) == 3;
};
}|;
- has(key)
Whether the dictionary has a mapping for key.
{
var d = ["one" => 1];
assert
{
d.has("one");
!d.has("zero");
};
}|;
The infix operators in and not in use has (see Section 22.1.8.7).
"one" in ["one" => 1];
"two" not in ["one" => 1];
- init(key1, value1, ...)
Insert the mapping from key1 to value1 and so forth.
Dictionary.clone.init("one", 1, "two", 2);
[00000000] ["one" => 1, "two" => 2]
- keys
The list of all the keys. No particular order is ensured. Since List features the same function,
uniform iteration over a List or a Dictionary is possible.
{
var d = ["one" => 1, "two" => 2];
assert(d.keys == ["one", "two"]);
assert({
var res = [];
for (var k: d.keys)
res << d[k];
res
}
== [1, 2]);
};
- matchAgainst(handler, pattern)
Pattern matching on members. See Pattern.
{
// Match a subset of the dictionary.
["a" => var a] = ["a" => 1, "b" => 2];
// get the matched value.
assert(a == 1);
};
- set(key, value)
Map key to value and return this so that invocations to set can be chained. The possibly
existing previous mapping is overridden.
[=>].set("one", 2)
.set("two", 2)
.set("one", 1);
[00000000] ["one" => 1, "two" => 2]
- size
Number of element in the dictionary.
{
var d = [=>];
assert(d.size == 0);
d["a"] = 0;
assert(d.size == 1);
d["b"] = 1;
assert(d.size == 2);
d["a"] = 2;
assert(d.size == 2);
};
23.12 Directory
A Directory represents a directory of the file system.
A Directory can be constructed with one argument: the path of the directory using a String or a
Path. It can also be constructed by the method open of Path.
Directory.new(".");
[00000001] Directory(".")
Directory.new(Path.new("."));
[00000002] Directory(".")
- ’/’(str)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
The str String is concatenated with the directory path. If the resulting path is
either a directory or a file, ’/’ will returns either a Directory or a File object.
var dir1 = Directory.create("dir1")|;
var dir2 = Directory.create("dir1/dir2")|;
var file = File.create("dir1/file")|;
dir1 / "dir2";
[00000001] Directory("dir1/dir2")
dir1 / "file";
[00000002] File("dir1/file")
dir1.removeAll;
- ’<<’(entity)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
If entity is a Directory or a File, ’<<’ copies entity in the this directory. Return this to
allow chained operations.
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir2")|;
file = File.create("file")|;
dir1 << file << dir2;
[00000001] Directory("dir1")
dir1.content;
[00000003] ["dir2", "file"]
dir2;
[00000004] Directory("dir2")
file;
[00000005] File("file")
dir1.removeAll;
dir2.removeAll;
file.remove;
- asList
The contents of the directory as a Path list. The various paths include the name of the directory
this.
- asString
A String containing the path of the directory.
Directory.new(".").asString == ".";
- asPath
A Path being the path of the directory.
- content
The contents of the directory as a String list. The strings include only the last component name;
they do not contain the directory name of this.
- copy(dirname)
Copy recursively all items of the this directory into the directory dirname after creating it.
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir1/dir2")|;
file = File.create("dir1/file")|;
var directory1 = dir1.copy("directory1");
[00000001] Directory("directory1")
dir1;
[00000002] Directory("dir1")
directory1.content;
[00000003] ["dir2", "file"]
dir1.removeAll;
directory1.removeAll;
- copyInto(dirname)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Copy this into dirname without creating it.
var dir = Directory.create("dir")|;
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir1/dir2")|;
file = File.create("dir1/file")|;
dir1.copyInto(dir);
[00000001] Directory("dir/dir1")
dir1;
[00000002] Directory("dir1")
dir1.content;
[00000003] ["dir2", "file"]
dir.content;
[00000004] ["dir1"]
Directory.new("dir/dir1").content;
[00000005] ["dir2", "file"]
dir.removeAll;
dir1.removeAll;
- clear
Remove all children recursively but not the directory itself. After a call to clear, a call to empty
should return true.
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir1/dir2")|;
var file1 = File.create("dir1/file1")|;
var file2 = File.create("dir1/dir2/file2")|;
dir1.content;
[00000001] ["dir2", "file1"]
dir2.content;
[00000002] ["file2"]
dir1.clear;
assert(dir1.empty);
dir1.remove;
- create(name)
Create the directory name where name is either a String or a Path. In addition to
system errors that can occur, errors are raised if directory or file name already exists.
dir = Directory.new("dir");
[00000001:error] !!! new: directory does not exist: "dir"
dir = Directory.create("dir");
[00000002] Directory("dir")
dir = Directory.create("dir");
[00000001:error] !!! create: directory exists: "dir"
dir.content;
[00000003] []
dir.remove;
- createAll(name)
Create the directory name where name is either a String or a Path. If name is a path (or
a String describing a path) no errors are raised if one directory doesn’t exist or
already exists. Instead createAll creates them all as in the Unix ‘make -p’ command.
Directory.create("dir1/dir2/dir3");
[00000001:error] !!! create: no such file or directory: "dir1/dir2/dir3"
dir1 = Directory.create("dir1");
[00000002] Directory("dir1")
Directory.createAll("dir1/dir2/dir3");
[00000002] Directory("dir1/dir2/dir3")
dir1.removeAll;
- empty
Whether the directory is empty.
dir = Directory.create("dir")|;
assert(dir.empty);
File.create("dir/file")|;
assert(!dir.empty);
dir.removeAll;
- exists
Whether the directory still exists.
dir = Directory.create("dir");
[00000001] Directory("dir")
assert(dir.exists);
dir.remove;
assert(!dir.exists);
- fileCreated(name)
Event launched when a file is created inside the directory. May not exist if not supported by your
architecture.
if (Path.new("./dummy.txt").exists)
File.new("./dummy.txt").remove;
{
var d = Directory.new(".");
waituntil(d.fileCreated?(var name));
assert
{
name == "dummy.txt";
Path.new(d.asString + "/" + name).exists;
};
}
&
{
sleep(100ms);
File.create("./dummy.txt");
}|;
- fileDeleted(name)
Event launched when a file is deleted from the directory. May not exist if not supported by your
architecture.
if (!Path.new("./dummy.txt").exists)
File.create("./dummy.txt")|;
{
var d = Directory.new(".");
waituntil(d.fileDeleted?(var name));
assert
{
name == "dummy.txt";
!Path.new(d.asString + "/" + name).exists;
};
}
&
{
sleep(100ms);
File.new("./dummy.txt").remove;
}|;
- basename
Return a String containing the path of the directory without its dirname.
var dir1 = Directory.create("dir1");
[00000001] Directory("dir1")
var dir2 = Directory.create("dir1/dir2");
[00000002] Directory("dir1/dir2")
dir1.basename;
[00000002] "dir1"
dir2.basename;
[00000003] "dir2"
dir1.removeAll;
- lastModifiedDate
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Return a Date object stating when the directory was last modified.
- moveInto(dirname)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Move this into dirname without creating it.
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir1/dir2")|;
var file = File.create("dir1/file")|;
var dir = Directory.create("dir")|;
dir1.moveInto(dir);
[00000001] Directory("dir/dir1")
dir1;
[00000002] Directory("dir/dir1")
dir1.content;
[00000003] ["dir2", "file"]
dir.content;
[00000004] ["dir1"]
dir.removeAll;
- parent
Return the parent of the directory.
Directory.create("dir")|;
dir = Directory.create("dir/dir")|;
dir.parent;
[00000001] Directory("dir")
assert(dir.parent.parent.asString == Directory.current.asString);
dir.parent.removeAll;
- remove
Remove the directory only if it is empty.
dir = Directory.create("dir")|;
File.create("dir/file")|;
dir.remove;
[00000001:error] !!! remove: directory not empty: "dir"
dir.clear;
dir.remove;
assert(!dir.exists);
- removeAll
Remove all children recursively including the directory itself.
dir1 = Directory.create("dir1")|;
dir2 = Directory.create("dir1/dir2")|;
var file1 = File.create("dir1/file1")|;
var file2 = File.create("dir1/dir2/file2")|;
dir1.removeAll;
assert(!dir1.exists);
- rename
Rename or move the directory.
dir = Directory.create("dir")|;
File.create("dir/file")|;
dir.rename("other");
[00000001] Directory("other")
dir;
[00000002] Directory("other")
dir.content;
[00000003] ["file"]
dir2 = Directory.create("dir2")|;
dir.rename("dir2/other2");
[00000004] Directory("dir2/other2")
dir;
[00000005] Directory("dir2/other2")
dir.content;
[00000006] ["file"]
dir2.removeAll;
- size
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
The size of all the directory content computed recursively.
dir = Directory.create("dir")|;
Directory.create("dir/dir")|;
File.save("dir/file", "content");
file1 = File.create("dir/file")|;
File.save("dir/dir/file", "content");
file2 = File.create("dir/dir/file")|;
assert(dir.size() == file1.size() + file2.size());
23.13 Duration
This class records differences between Dates.
This feature is experimental. It might be changed in the future. Feedback on its use
would be appreciated.
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)
- asFloat
Return the duration as a Float.
Duration.new(1000).asFloat == 1000;
Duration.new(1000.1234).asFloat == 1000.1234;
- asString
Return the duration as a String.
Duration.new(1000).asString == "1000s";
- seconds
Return the duration as a Float.
Duration.new(1000) .seconds == 1000;
Duration.new(1000.52).seconds == 1000.52;
23.14 Enumeration
Prototype of enumeration types.
See Section 22.5.
An Enumeration is created with two arguments: the name of the enumeration type, and the list of
possible values. Most of the time, it is a good idea to store it in a variable with the same
name.
var Direction = Enumeration.new("Direction", ["up", "down", "left", "right"]);
[00000001] Direction
Direction.up;
[00000002] up
The following syntax is equivalent.
enum Direction
{
up,
down,
left,
right
};
[00000001] Direction
The created values are derive from the created enumeration type.
Direction.isA(Enumeration);
Direction.up.isA(Direction);
23.15 Event
An event can be “emitted” and “caught”, or “sent” and “received”. See also Section 14.2.
There are several examples of uses of events in the documentation of event-based constructs.
See at (Listing 22.10.1), waituntil (Listing 22.10.6), whenever (Listing 22.10.7), and so
forth. The tutorial chapter about event-based programming contains other examples, see
Listing 14.
An Event is created like any other object, without arguments.
var e = Event.new;
[00000001] Event_0x9ad8118
23.16 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 22.8) work perfectly well with any kind of object, yet it is a good idea to throw only objects
that derive from Exception.
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’
Exception has many slots which are specific exceptions. See Section 23.16.4 for their documentation.
- backtrace
The call stack at the moment the exception was thrown (not created), as a List of
StackFrames, from the innermost to the outermost call. Uses Traceable.backtrace.
//#push 1 "file.u"
try
{
function innermost () { throw Exception.new("Ouch") };
function inner () { innermost() };
function outer () { inner() };
function outermost () { outer() };
outermost();
}
catch (var e)
{
assert
{
e.backtrace[0].location.asString == "file.u:4.27-37";
e.backtrace[0].name == "innermost";
e.backtrace[1].location.asString == "file.u:5.27-33";
e.backtrace[1].name == "inner";
e.backtrace[2].location.asString == "file.u:6.27-33";
e.backtrace[2].name == "outer";
e.backtrace[3].location.asString == "file.u:8.3-13";
e.backtrace[3].name == "outermost";
};
};
//#pop
- location
The location from which the exception was thrown (not created).
eval("1/0");
[00090441:error] !!! 1.1-3: /: division by 0
[00090441:error] !!! called from: eval
try
{
eval("1/0");
}
catch (var e)
{
assert (e.location.asString == "1.1-3");
};
- message
The error message provided at construction.
Exception.new("Ouch").message == "Ouch";
In the following, since these slots are actually Objects, what is presented as arguments to the slots
are actually arguments to pass to the constructor of the corresponding exception type.
- Argument(routine, index, exception)
During the call of routine, the instantiation of the index-nth argument has thrown an
exception.
Exception.Argument
.new("myRoutine", 3, Exception.Type.new("19/11/2010", Date))
.asString
== "myRoutine: argument 3: unexpected \"19/11/2010\", expected a Date";
- ArgumentType(routine, index, effective, expected)
Deprecated exception that derives from Type. The routine was called with a index-nth
argument of type effective instead of expected.
Exception.ArgumentType
.new("myRoutine", 1, "hisResult", "Expectation")
.asString
== "myRoutine: argument 1: unexpected \"hisResult\", expected a String";
[00000003:warning] !!! ‘Exception.ArgumentType’ is deprecated
- Arity(routine, effective, min, max = void)
The routine was called with an incorrect number of arguments (effective). It requires at least
min arguments, and, if specified, at most max.
Exception.Arity.new("myRoutine", 1, 10, 23).asString
== "myRoutine: expected between 10 and 23 arguments, given 1";
- BadInteger(routine, fmt, effective)
The routine was called with an inappropriate integer (effective). Use the format fmt to
create an error message from effective. Derives from BadNumber.
Exception.BadInteger.new("myRoutine", "bad integer: %s", 12).asString
== "myRoutine: bad integer: 12";
- BadNumber(routine, fmt, effective)
The routine was called with an inappropriate number (effective). Use the format fmt to
create an error message from effective.
Exception.BadNumber.new("myRoutine", "bad number: %s", 12.34).asString
== "myRoutine: bad number: 12.34";
- Constness
An attempt was made to change a constant value.
Exception.Constness.new.asString
== "cannot modify const slot";
- FileNotFound(name)
The file named name cannot be found.
Exception.FileNotFound.new("foo").asString
== "file not found: foo";
- ImplicitTagComponent(msg)
An attempt was made to create an implicit tag, a component of which being undefined.
Exception.ImplicitTagComponent.new.asString
== "invalid component in implicit tag";
- Lookup(object, name)
A failed name lookup was performed on object to find a slot named name. Suggest what the user
might have meant if Exception.Lookup.fixSpelling is true (which is the default).
Exception.Lookup.new(Object, "GetSlot").asString
== "lookup failed: Object";
- MatchFailure
A pattern matching failed.
Exception.MatchFailure.new.asString
== "pattern did not match";
- NegativeNumber(routine, effective)
The routine was called with a negative number (effective). Derives from BadNumber.
Exception.NegativeNumber.new("myRoutine", -12).asString
== "myRoutine: unexpected -12, expected non-negative number";
- NonPositiveNumber(routine, effective)
The routine was called with a non-positive number (effective). Derives from BadNumber.
Exception.NonPositiveNumber.new("myRoutine", -12).asString
== "myRoutine: unexpected -12, expected positive number";
- Primitive(routine, msg)
The built-in routine encountered an error described by msg.
Exception.Primitive.new("myRoutine", "cannot do that").asString
== "myRoutine: cannot do that";
- Redefinition(name)
An attempt was made to refine a slot named name.
Exception.Redefinition.new("foo").asString
== "slot redefinition: foo";
- Scheduling(msg)
Something really bad has happened with the Urbi task scheduler.
Exception.Scheduling.new("cannot schedule").asString
== "cannot schedule";
- Syntax(loc, message, input)
Declare a syntax error in input, at location loc, described by message. loc is the location of
the syntax error, location is the place the error was thrown. They are usually equal, except
when the errors are caught while using System.eval or System.load. In that case loc is really
the position of the syntax error, while location refers to the location of the System.eval or
System.load invocation.
Exception.Syntax
.new(Location.new(Position.new("file.u", 14, 25)),
"unexpected pouCharque", "file.u")
.asString
== "file.u:14.25: syntax error: unexpected pouCharque";
try
{
eval("1 / / 0");
}
catch (var e)
{
assert
{
e.isA(Exception.Syntax);
e.loc.asString == "1.5";
e.input == "1 / / 0";
e.message == "unexpected /";
}
};
- Type(effective, expected)
A value of type effective was received, while a value of type expected was expected.
Exception.Type.new("hisResult", "Expectation").asString
== "unexpected \"hisResult\", expected a String";
- UnexpectedVoid
An attempt was made to read the value of void.
Exception.UnexpectedVoid.new.asString
== "unexpected void";
var a = void;
a;
[00000016:error] !!! unexpected void
[00000017:error] !!! lookup failed: a
23.17 Executable
This class is used only as a common ancestor to Primitive and Code.
There is no point in constructing an Executable.
- asExecutable
Return this.
23.18 File
Files may be created from a String, or from a Path. Using new, 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).
File.create("file.txt");
[00000001] File("file.txt")
File.new(Path.new("file.txt"));
[00000001] File("file.txt")
You may use InputStream and OutputStream to read or write to Files.
- asList
Read the file, and return its content as a list of its lines.
File.save("file.txt", "1\n2\n");
assert(File.new("file.txt").asList == ["1", "2"]);
- asPath
A Path being the path of the file.
- asPrintable
File.save("file.txt", "1\n2\n");
assert(File.new("file.txt").asPrintable == "File(\"file.txt\")");
- asString
The name of the opened file.
File.save("file.txt", "1\n2\n");
assert(File.new("file.txt").asString == "file.txt");
- basename
Return a String containing the path of the file without its dirname.
- content
The content of the file as a Binary object.
File.save("file.txt", "1\n2\n");
assert
{
File.new("file.txt").content == Binary.new("", "1\n2\n");
};
- copy(filename)
Copy the file to a new file named filename.
File.save("file", "content");
var file = File.new("file");
[00000001] File("file")
var file2 = file.copy("file2");
[00000002] File("file2")
assert(file2.content == file.content);
file.remove;
file2.remove;
- copyInto(dirname)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Copy file into dirname directory.
var dir = Directory.create("dir")|;
file = File.create("file")|;
file.copyInto(dir);
[00000001] File("dir/file")
file;
[00000002] File("file")
dir.content;
[00000003] ["file"]
dir.removeAll;
file.remove;
- create(name)
If the file name does not exist, create it and a return a File to it. Otherwise, first empty it. See
OutputStream for methods to add content to the file.
var p = Path.new("create.txt") |
assert (!p.exists);
// Create the file, and put something in it.
var f = File.create(p)|;
var o = OutputStream.new(f)|;
o << "Hello, World!"|;
o.close;
assert
{
// The file exists, with the expect contents.
p.exists;
f.content.data == "Hello, World!";
// If we create is again, it is empty.
File.create(p).isA(File);
f.content.data == "";
};
- lastModifiedDate
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Return a Date object stating when the file was last modified.
- moveInto(dirname)
This feature is experimental. It might be changed in the future. Feedback on its
use would be appreciated.
Move file into dirname directory.
dir = Directory.create("dir")|;
file = File.create("file")|;
file.moveInto(dir);
[00000001] File("dir/file")
file;
[00000001] File("dir/file")
dir.content;
[00000001] ["file"]
dir.removeAll;
- remove
Remove the current file. Returns void.
var p = Path.new("foo.txt") |
p.exists;
[00000002] false
var f = File.create(p);
[00000003] File("foo.txt")
p.exists;
[00000004] true
f.remove;
p.exists;
[00000006] false
- rename(name)
Rename the file to name. If the target exists, it is replaced by the opened file. Return the file
renamed.
File.save("file.txt", "1\n2\n");
File.new("file.txt").rename("bar.txt");
[00000001] File("bar.txt")
assert
{
!Path.new("file.txt").exists;
File.new("bar.txt").content.data == "1\n2\n";
};
- save(name, content)
Use create to create the File named name, store the content in it, and close the file. Return
void.
File.save("file.txt", "1\n2\n").isVoid;
File.new("file.txt").content.data == "1\n2\n";
- size
The size of the file.
File.save("file.txt", "1234");
File.new("file.txt").size;
[00000001] 4
23.19 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.
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
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] !!! apply: cannot inherit from a Finalizable without being one
class o2
{
protos = [Finalizable];
function finalize()
{
echo("Ouch");
}
}|;
[00000010:error] !!! updateSlot: cannot inherit from a Finalizable without being one
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
- finalize
a simple function that takes no argument that will be evaluated when the object is reclaimed. Its
return value is ignored.
Finalizable.new.setSlot("finalize", function() { echo("Ouch") })|;
[00033240] *** Ouch
23.20 Float
A Float is a floating point number. It is also used, in the current version of urbiscript, to represent
integers.
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).isNan;
A null float can also be obtained with Float’s new method.
- abs
Absolute value of the target.
(-5).abs == 5;
0 .abs == 0;
5 .abs == 5;
- acos
Arccosine of the target.
0.acos == Float.pi/2;
1.acos == 0;
- asBool
Whether non null.
0.asBool == false;
0.1.asBool == true;
(-0.1).asBool == true;
inf.asBool == true;
nan.asBool == true;
- asFloat
Return the target.
- asList
Bounces to seq.
3.asList == [0, 1, 2];
0.asList == [];
- asin
Arcsine of the target.
- asString
Return a string representing the target.
42.asString == "42";
42.51.asString == "42.51";
21474836470.asString == "21474836470";
4611686018427387904.asString == "4611686018427387904";
(-4611686018427387904).asString == "-4611686018427387904";
- atan
Return the arctangent of the target.
0.atan == 0;
1.atan == Float.pi/4;
- ’bitand’(that)
The bitwise-and between this and that.
- ’bitor’(that)
Bitwise-or between this and that.
- ceil
The smallest integral value greater than or equal to. See also floor and round.
0.ceil == 0;
1.4.ceil == 2; 1.5.ceil == 2; 1.6.ceil == 2;
(-1.4).ceil == -1; (-1.5).ceil == -1; (-1.6).ceil == -1;
inf.ceil == inf; (-inf).ceil == -inf;
nan.ceil.isNan;
- clone
Return a fresh Float with the same value as the target.
var x = 0;
[00000000] 0
var y = x.clone;
[00000000] 0
x === y;
[00000000] false
- compl
The complement to 1 of the target interpreted as a 32 bits integer.
compl 0 == 4294967295;
compl 4294967295 == 0;
- cos
Cosine of the target.
0.cos == 1;
Float.pi.cos == -1;
- each(fun)
Call the functional argument fun on every integer from 0 to target - 1, sequentially. The number
must be non-negative.
{
var res = [];
3.each(function (i) { res << 100 + i });
res
}
== [100, 101, 102];
{
var res = [];
for(var x : 3) { res << x; sleep(20ms); res << (100 + x); };
res
}
== [0, 100, 1, 101, 2, 102];
{
var res = [];
0.each (function (i) { res << 100 + i });
res
}
== [];
- ’each|’(fun)Call the functional argument fun on every integer from 0 to target - 1, with tight
sequentiality. The number must be non-negative.
{
var res = [];
3.’each|’(function (i) { res << 100 + i });
res
}
== [100, 101, 102];
{
var res = [];
for|(var x : 3) { res << x; sleep(20ms); res << (100 + x); };
res
}
== [0, 100, 1, 101, 2, 102];
- ’each&’(fun)
Call the functional argument fun on every integer from 0 to target - 1, concurrently. The number
must be non-negative.
{
var res = [];
for& (var x : 3) { res << x; sleep(30ms); res << (100 + x) };
res
}
== [0, 1, 2, 100, 101, 102];
- exp
Exponential of the target.
1.exp;
[00000000] 2.71828
- floor
the largest integral value less than or equal to this. See also ceil and round.
0.floor == 0;
1.4.floor == 1; 1.5.floor == 1; 1.6.floor == 1;
(-1.4).floor == -2; (-1.5).floor == -2; (-1.6).floor == -2;
inf.floor == inf; (-inf).floor == -inf;
nan.floor.isNan;
- format(finfo)
Format according to the FormatInfo object finfo. The precision, finfo.precision, sets the
maximum number of digits after decimal point when in fixed or scientific mode, and in total
when in default mode. Beware that 0 plays a special role, as it is not a “significant”
digit.
Windows Issues
Under Windows the behavior differs slightly.
"%1.0d" % 0.1 == "0.1";
"%1.0d" % 1.1 == {if (System.Platform.isWindows) "1.1" else "1"};
"%1.0f" % 0.1 == "0";
"%1.0f" % 1.1 == "1";
Conversion to hexadecimal requires this to be integral.
"%x" % 42 == "2a";
"%x" % 0xFFFF == "ffff";
"%x" % 0.5;
[00000005:error] !!! %: expected integer, got 0.5
- fresh
Return a new integer at each call.
{
var res = [];
for (var i: 10)
res << Float.fresh;
assert (res == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
res = [];
for (var i: 10)
res << Float.fresh;
assert (res == [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
};
- hash
Return a Hash object corresponding to this float value. Two float hashes are equal if the float are
equal. See Object.hash.
0.hash.isA(Hash);
0.hash == 0.hash;
0.hash != 1.hash;
- hex
A String with the conversion of this in hexadecimal. Requires this to be integral.
0.hex == "0";
0xFF.hex == "ff";
0xFFFF.hex == "ffff";
65535.hex == "ffff";
0xffffffff.hex == "ffffffff";
0.5.hex;
[00000005:error] !!! format: expected integer, got 0.5
- inf
Return the infinity.
Float.inf;
[00000000] inf
- isInf
Whether is infinite.
!0.isInf; !1.isInf; !(-1).isInf;
!nan.isInf;
inf.isInf; (-inf).isInf;
- isNan
Whether is NaN.
!0.isNan; !1.isNan; !(-1).isNan;
!inf.isNan; !(-inf).isNan;
nan.isNan;
- limits
See Float.limits.
- log
The logarithm of the target.
0.log == -inf;
1.log == 0;
1.exp.log == 1;
- max(arg1, ...)
Bounces to List.max on [this, arg1, ...].
1.max == 1;
1.max(2, 3) == 3;
3.max(1, 2) == 3;
- min(arg1, ...)
Bounces to List.min on [this, arg1, ...].
1.min == 1;
1.min(2, 3) == 1;
3.min(1, 2) == 1;
- nan
The “not a number” special float value. More precisely, this returns the “quiet NaN”, i.e., it is
propagated in the various computations, it does not raise exceptions.
Float.nan;
[00000000] nan
(Float.nan + Float.nan) / (Float.nan - Float.nan);
[00000000] nan
A NaN has one distinctive property over the other Floats: it is equal to no other
float, not even itself. This behavior is mandated by the IEEE 754-2008 standard.
{ var n = Float.nan; n === n};
{ var n = Float.nan; n != n};
- pi
π.
Float.pi.cos ** 2 + Float.pi.sin ** 2 == 1;
- random
A random integer between 0 (included) and the target (excluded).
20.map(function (dummy) { 5.random });
[00000000] [1, 2, 1, 3, 2, 3, 2, 2, 4, 4, 4, 1, 0, 0, 0, 3, 2, 4, 3, 2]
- round
The integral value nearest to this rounding half-way cases away from zero. See also ceil and
floor.
0.round == 0;
1.4.round == 1; 1.5.round == 2; 1.6.round == 2;
(-1.4).round == -1; (-1.5).round == -2; (-1.6).round == -2;
inf.round == inf; (-inf).round == -inf;
nan.round.isNan;
- seq
The sequence of integers from 0 to this- 1 as a list. The number must be non-negative.
3.seq == [0, 1, 2];
0.seq == [];
- sign
Return 1 if this is positive, 0 if it is null, -1 otherwise.
(-1164).sign == -1;
0.sign == 0;
(1164).sign == 1;
- sin
The sine of the target.
- sqr
Square of the target.
32.sqr == 1024;
32.sqr == 32 ** 2;
- sqrt
The square root of the target.
1024.sqrt == 32;
1024.sqrt == 1024 ** 0.5;
- srandom
Initialized the seed used by the random function. As opposed to common usage, you should not
use
{
var now = Date.now.timestamp;
now.srandom;
var list1 = 20.map(function (dummy) { 5.random });
now.srandom;
var list2 = 20.map(function (dummy) { 5.random });
assert
{
list1 == list2;
}
};
- tan
Tangent of the target.
assert(0.tan == 0);
(Float.pi/4).tan;
[00000000] 1
- times(fun)
Call the functional argument fun this times.
3.times(function () { echo("ping") });
[00000000] *** ping
[00000000] *** ping
[00000000] *** ping
- trunc
Return the target truncated.
1.9.trunc == 1;
(-1.9).trunc == -1;
- ’^’(that)
Bitwise exclusive or between this and that.
- ’>>’(that)
this shifted by that bits towards the right.
- ’<’(that)
Whether this is less than that. The other comparison operators (<=, >, …) can thus also be
applied on floats since Float inherits Orderable.
0 < 1;
!(1 < 0);
!(0 < 0);
- ’<<’(that)
this shifted by that bit towards the left.
- ’-’(that)
this subtracted by that.
- ’+’(that)
The sum of this and that.
- ’/’(that)
The quotient of this divided by that.
50 / 10 == 5;
10 / 50 == 0.2;
- ’%’(that)
this modulo that.
- ’*’(that)
Product of this by that.
- ’**’(that)
this to the that power (thisthat).
2 ** 10 == 1024;
2 ** 31 == 2147483648;
-2 ** 31 == -2147483648; // This is -(2**31).
2 ** 32 == 4294967296;
-2 ** 32 == -4294967296; // This is -(2**32).
- ’==’(that)
Whether this equals that.
23.21 Float.limits
This singleton handles various limits related to the Float objects.
- digits
Number of digits (in radix base) in the mantissa.
- digits10
Number of digits (in decimal base) that can be represented without change.
- epsilon
Machine epsilon (the difference between 1 and the least value greater than 1 that is
representable).
1 != 1 + Float.limits.epsilon;
1 == 1 + Float.limits.epsilon / 2;
- max
Maximum finite value.
Float.limits.max != Float.inf;
Float.limits.max * 2 == Float.inf;
- maxExponent
Maximum integer value for the exponent that generates a normalized floating-point number.
Float.inf != Float.limits.radix ** (Float.limits.maxExponent - 1);
Float.inf == Float.limits.radix ** Float.limits.maxExponent;
- maxExponent10
Maximum integer value such that 10 raised to that power generates a normalized finite
floating-point number.
Float.inf != 10 ** Float.limits.maxExponent10;
Float.inf == 10 ** (Float.limits.maxExponent10 + 1);
- min
Minimum positive normalized value.
- minExponent
Minimum negative integer value for the exponent that generates a normalized floating-point
number.
0 != Float.limits.radix ** Float.limits.minExponent;
- minExponent10
Minimum negative integer value such that 10 raised to that power generates a normalized
floating-point number.
0 != 10 ** Float.limits.minExponent10;
- radix
Base of the exponent of the representation.
23.22 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.
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 spec
- %|options[spec]|
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 |
|
|
| |
- alignment
Requested alignment: -1 for left, 0 for centered, 1 for right (default).
FormatInfo.new("%s").alignment == 1;
FormatInfo.new("%=s").alignment == 0;
FormatInfo.new("%-s").alignment == -1;
- alt
Whether the “alternative” display is requested (‘#’).
FormatInfo.new("%s").alt == false;
FormatInfo.new("%#s").alt == true;
- group
Separator to use for thousands. Corresponds to the ‘’’ option.
FormatInfo.new("%s").group == "";
FormatInfo.new("%’s").group == " ";
- pad
The padding character to use for alignment requests. Defaults to space.
FormatInfo.new("%s").pad == " ";
FormatInfo.new("%0s").pad == "0";
- pattern
The pattern given to the constructor.
FormatInfo.new("%#’12.8s").pattern == "%#’12.8s";
- precision
When formatting a Float, the maximum number of digits after decimal point when in fixed or
scientific mode, and in total when in default mode. When formatting other objects with
spec-char ‘s’, the conversion string is truncated to the precision first chars. The eventual padding
to width is done after truncation.
FormatInfo.new("%s").precision == 6;
FormatInfo.new("%23.3s").precision == 3;
- prefix
The string to display before positive numbers. Defaults to empty.
FormatInfo.new("%s").prefix == "";
FormatInfo.new("% s").prefix == " ";
FormatInfo.new("%+s").prefix == "+";
- spec
The specification character, regardless of the case conversion requests.
FormatInfo.new("%s").spec == "s";
FormatInfo.new("%23.3s").spec == "s";
FormatInfo.new("%’X").spec == "x";
- uppercase
Case conversion: -1 for lower case, 0 for no conversion (default), 1 for conversion to uppercase.
The value depends on the case of specification character, except for ‘%s’ which corresponds to 0.
FormatInfo.new("%s").uppercase == 0;
FormatInfo.new("%d").uppercase == -1;
FormatInfo.new("%D").uppercase == 1;
FormatInfo.new("%x").uppercase == -1;
FormatInfo.new("%X").uppercase == 1;
- width
Width requested for alignment.
FormatInfo.new("%s").width == 0;
FormatInfo.new("%10s").width == 10;
23.23 Formatter
A formatter stores format information of a format string like used in printf in the C library or in
boost::format.
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.
- asList
Return the content of the formatter as a list of strings and FormatInfo.
Formatter.new("Name:%s, Surname:%s;").asList.asString
== "[\"Name:\", %s, \", Surname:\", %s, \";\"]";
-
- ’%’(args)
Use this as format string and args as the list of arguments, and return the result (a String).
The arity of the Formatter (i.e., the number of expected arguments) and the size of args must
match exactly.
This operator concatenates regular strings and the strings that are result of asString called on
members of args with the appropriate FormatInfo.
Formatter.new("Name:%s, Surname:%s;") % ["Foo", "Bar"]
== "Name:Foo, Surname:Bar;";
If args is not a List, then the call is equivalent to calling ’%’([args]).
Formatter.new("%06.3f") % Math.pi
== "03.142";
Note that String.’%’ provides a nicer interface to this operator:
"%06.3f" % Math.pi == "03.142";
It is nevertheless interesting to use the Formatter for performance reasons if the format is reused
many times.
{
// Some large database of people.
var people =
[["Foo", "Bar" ],
["One", "Two" ],
["Un", "Deux"],];
var f = Formatter.new("Name:%7s, Surname:%7s;");
for (var p: people)
echo (f % p);
};
[00031939] *** Name: Foo, Surname: Bar;
[00031940] *** Name: One, Surname: Two;
[00031941] *** Name: Un, Surname: Deux;
23.24 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.
23.25 Group
A transparent means to send messages to several objects as if they were one.
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
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"]
- add(member, ...)
Add members to this group, and return this.
- asString
Report the members.
- each(action)
Apply action to all the members, in sequence, then return the Group of the results, in
the same order. Allows to iterate over a Group via for.
- each&(action)
Apply action to all the members, concurrently, then return the Group of the results. The
order is not necessarily the same. Allows to iterate over a Group via for&.
- fallback
This function is called when a method call on this failed. It bounces the call to the
members of the group, collects the results returned as a group. This allows to chain grouped
operation in a row. If the dispatched calls return void, returns a single void, not a “group
of void”.
- getProperty(slot, prop)
Bounced to the members so that this.slot->prop actually collects the values of the
property prop of the slots slot of the group members.
- hasProperty(name)
Bounced to the members.
- hasSlot(name)
True if and only if all the members have the slot.
var g = Group.new(1, 2);
[00000000] Group [1, 2]
g.hasSlot("foo");
[00000000] false
g.hasSlot("+");
[00000000] true
g + 1;
[00000000] Group [2, 3]
- remove(member, ...)
Remove members from this group, and return this.
- setProperty(slot, prop, value)
Bounced to the members so that this.slot->prop = value actually updates the value of the
property prop in the slots slot of the group members.
- updateSlot(name, value)
Bounced to the members so that this.name = value actually updates the value of the slot name
in the group members.
- ’<<’(member)
Syntactic sugar for add.
23.26 Hash
A hash is a condensed, easily comparable representation of another value. They are mainly used to
map Dictionary keys to values.
Equal objects must always have the same hash. Different objects should, as much as possible, have
different hashes.
Objects can be hashed with Object.hash.
Object.new.hash.isA(Hash);
- asFloat
A Float value equivalent to the Hash object. Two hashes have the same Float representation if
and only if they are equal.
var h1 = Object.new.hash|;
var h2 = Object.new.hash|;
assert
{
h1.asFloat == h1.asFloat;
h1.asFloat != h2.asFloat;
};
- combine(that)
Combine that’s hash with this, and return this. This is used to hash composite objects based
on more primitive object hashes. For instance, an object with two slots could be hashed by
hashing its first first, and combining the second in.
class C
{
function init(var a, var b)
{
var this.a = a;
var this.b = b;
};
function hash()
{
this.a.hash().combine(b)
};
}|
assert
{
C.new(0, 0).hash == C.new(0, 0).hash;
C.new(0, 0).hash != C.new(0, 1).hash;
};
23.27 InputStream
InputStreams are used to read (possibly binary) files by hand. 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.
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.
An InputStream is a reading-interface to a file, so its constructor requires a File.
File.save("file.txt", "1\n2\n");
var is = InputStream.new(File.new("file.txt"));
[00000001] InputStream_0x827000
Bear in mind that open streams should be closed (Section 23.61.2).
- get
Get the next available byte as a Float, or void if the end of file was reached. Raise an error if
the file is closed.
{
File.save("file.txt", "1\n2\n");
var i = InputStream.new(File.new("file.txt"));
var x;
while (!(x = i.get.acceptVoid).isVoid)
cout << x;
i.close;
i.get;
};
[00000001:output] 49
[00000002:output] 10
[00000003:output] 50
[00000004:output] 10
[00000005:error] !!! get: stream is closed
- getChar
Get the next available byte as a String, or void if the end of file was reached. Raise an error if
the file is closed.
{
File.save("file.txt", "1\n2\n");
var i = InputStream.new(File.new("file.txt"));
var x;
while (!(x = i.getChar.acceptVoid).isVoid)
cout << x;
i.close;
i.getChar;
};
[00000001:output] "1"
[00000002:output] "\n"
[00000003:output] "2"
[00000004:output] "\n"
[00000005:error] !!! getChar: stream is closed
- getLine
Get the next available line as a String, or void if the end of file was reached. The end-of-line
characters are trimmed. Raise an error if the file is closed.
{
File.save("file.txt", "1\n2\n");
var i = InputStream.new(File.new("file.txt"));
var x;
while (!(x = i.getLine.acceptVoid).isVoid)
cout << x;
i.close;
i.getLine;
};
[00000001:output] "1"
[00000002:output] "2"
[00000005:error] !!! getLine: stream is closed
23.28 IoService
A IoService is used to manage the various operations of a set of Socket.
All Socket and Server are by default using the default IoService which is polled regularly by the
system.
Using a different IoService is required if you need to perform synchronous read operations.
The Socket must be created by the 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);
A IoService is constructed with no argument.
- makeServer
Create and return a new Server using this IoService.
- makeSocket
Create and return a new Socket using this IoService.
- poll
Handle all pending socket operations(read, write, accept) that can be performed without
waiting.
- pollFor(duration)
Will block for duration seconds, and handle all ready socket operations during this period.
- pollOneFor(duration)
Will block for at most duration, and handle the first ready socket operation and
immediately return.
23.29 Job
Jobs are independent threads of executions. Jobs can run concurrently. They can also be managed
using Tags.
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>
- asJob
Return this.
- asString
The string Job<name> where name is the name of the job.
- backtrace
The current backtrace of the job as a list of StackFrames. Uses Traceable.backtrace.
//#push 1 "file.u"
var s = detach(sleep(10))|;
// Leave some time for s to be started.
sleep(1);
assert
{
s.backtrace[0].asString == "file.u:1.16-24: sleep";
s.backtrace[1].asString == "file.u:1.16-24: detach";
};
//#pop
- clone
Cloning a job is impossible since Job is considered as being an atom.
- dumpState
Pretty-print the state of the job.
//#push 1 "file.u"
var t = detach(sleep(10))|;
// Leave some time for s to be started.
sleep(1);
t.dumpState;
[00004295] *** Job: shell_10
[00004295] *** State: sleeping
[00004295] *** Tags:
[00004295] *** Tag<Lobby_1>
[00004297] *** Backtrace:
[00004297] *** file.u:1.16-24: sleep
[00004297] *** file.u:1.16-24: detach
//#pop
- name
The name of the job.
detach(sleep(10)).name;
[00004297] "shell_5"
- setSideEffectFree(value)
If value is true, mark the current job as side-effect free. It indicates whether the current state
may influence other parts of the system. This is used by the scheduler to choose whether other
jobs need scheduling or not. The default value is false.
- status
The current status of the job (starting, running, …), and its properties (frozen, …).
- tags
The list of Tags that manage this job.
- terminate
Kill this job.
var r = detach({ sleep(1s); echo("done") })|;
assert (r in jobs);
r.terminate;
assert (r not in jobs);
sleep(2s);
- timeShift
Get the total amount of time during which we were frozen.
tag: r = detach({ sleep(3); echo("done") })|;
tag.freeze();
sleep(2);
tag.unfreeze();
Math.round(r.timeShift);
[00000001] 2
- waitForChanges
Resume the scheduler, putting the current Job in a waiting status. The scheduler may reschedule
the job immediately.
- waitForTermination
Wait for the job to terminate before resuming execution of the current one. If the job has already
terminated, return immediately.
23.30 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.
Since it is a Singleton, you are not expected to build other instances.
- commands
Ignored for backward compatibility.
- connections
Ignored for backward compatibility.
- copy(binary)
Obsolete syntax for binary.copy, see Binary.
// copy.
var a = BIN 10;0123456789
[00000001] BIN 10
0123456789
var b = Kernel1.copy(a);
[00000003:warning] !!! ‘copy(binary)’ is deprecated, use ‘binary.copy’
[00000004] BIN 10
0123456789
echo (b);
[00000005] *** BIN 10
0123456789
- devices
Ignored for backward compatibility.
- events
Ignored for backward compatibility.
- functions
Ignored for backward compatibility.
- isvoid(obj)
Obsolete syntax for obj.isVoid, see Object.
- noop
Do nothing. Use {} instead.
- ping
Return time verbosely, see System.
Kernel1.ping;
[00000421] *** pong time=0.12s
- reset
Ignored for backward compatibility.
- runningcommands
Ignored for backward compatibility.
- seq(number)
Obsolete syntax for number.seq, see Float.
- size(list)
Obsolete syntax for list.size, see List.
Kernel1.size([1, 2, 3]) == [1, 2, 3].size;
[00000002:warning] !!! ‘size(list)’ is deprecated, use ‘list.size’
- strict
Ignored for backward compatibility.
- strlen(string)
Obsolete syntax for string.length, see String.
Kernel1.strlen("123") == "123".length;
[00000002:warning] !!! ‘strlen(string)’ is deprecated, use ‘string.length’
- taglist
Ignored for backward compatibility.
- undefall
Ignored for backward compatibility.
- unstrict
Ignored for backward compatibility.
- uservars
Ignored for backward compatibility.
- vars
Ignored for backward compatibility.
23.31 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 23.4.
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:
- Not evaluating it if it’s not needed.
- Evaluating it only once if it’s needed once or twice.
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
Evaluating a lazy several times only makes sense with lazy arguments and call messages. See example
with call messages in Section 23.4.1.1.
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. 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 function, not its evaluation.
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
Lazies are seldom instantiated manually. They are mainly created automatically when a lazy function
call is made (see Section 22.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
- Whether this and that are the same source code and value (an not yet evaluated Lazy is never
equal to an evaluated one).
Lazy.new(closure () { 1 + 1 }) == Lazy.new(closure () { 1 + 1 });
Lazy.new(closure () { 1 + 2 }) != Lazy.new(closure () { 2 + 1 });
{
var l1 = Lazy.new(closure () { 1 + 1 });
var l2 = Lazy.new(closure () { 1 + 1 });
assert (l1 == l2);
l1.eval;
assert (l1 != l2);
l2.eval;
assert (l1 == l2);
};
- asString
The conversion to String of the body of a non-evaluated argument.
Lazy.new(closure () { echo(1); 1 }).asString == "echo(1);\n1";
- eval
Force the evaluation of the held lazy value. Two calls to eval will systematically evaluate the
expression twice, which can be useful to duplicate its side effects.
- value
Return the held value, potentially evaluating it before. value performs memoization, that is, only
the first call will actually evaluate the expression, subsequent calls will return the cached value.
Unless you want to explicitly trigger side effects from the expression by evaluating it several time,
this should be preferred over eval to avoid evaluating the expression several times
uselessly.
23.32 List
Lists implement possibly-empty ordered (heterogeneous) collections of objects.
Since lists are RangeIterable, they also support RangeIterable.all and RangeIterable.any.
// Are all elements positive?
! [-2, 0, 2, 4].all(function (e) { 0 < e });
// Are all elements even?
[-2, 0, 2, 4].all(function (e) { e % 2 == 0 });
// Is there any even element?
! [-3, 1, -1].any(function (e) { e % 2 == 0 });
// Is there any positive element?
[-3, 1, -1].any(function (e) { 0 < e });
Lists can be created with their literal syntax: a possibly empty sequence of expressions in square
brackets, separated by commas. Non-empty lists may actually end with a comma.
[]; // The empty list
[00000000] []
[1, "2", [3,],];
[00000000] [1, "2", [3]]
However, new can be used as expected.
List.new;
[00000001] []
[1, 2, 3].new;
[00000002] [1, 2, 3]
- append(that)
Deprecated alias for ’+=’.
var one = [1]|;
one.append(["one", [1]]);
[00000005:warning] !!! ‘list.append(that)’ is deprecated, use ‘list += that’
[00000005] [1, "one", [1]]
- argMax(fun = function(a, b) { a < b })
The index of the (leftmost) “largest” member based on the comparison function fun.
[1].argMax == 0;
[1, 2].argMax == 1;
[1, 2, 2].argMax == 1;
[2, 1].argMax == 0;
[2, -1, 3, -4].argMax == 2;
[2, -1, 3, -4].argMax (function (a, b) { a.abs < b.abs }) == 3;
The list cannot be empty.
[].argMax;
[00000007:error] !!! argMax: list cannot be empty
- argMin(fun = function(a, b) { a < b })
The index of the (leftmost) “smallest” member based on the comparison function fun.
[1].argMin == 0;
[1, 2].argMin == 0;
[1, 2, 1].argMin == 0;
[2, 1].argMin == 1;
[2, -1, 3, -4].argMin == 3;
[2, -1, 3, -4].argMin (function (a, b) { a.abs < b.abs }) == 1;
The list cannot be empty.
[].argMin;
[00000011:error] !!! argMin: list cannot be empty
- asBool
Whether not empty.
[].asBool == false;
[1].asBool == true;
- asList
Return the target.
{
var l = [0, 1, 2];
assert (l.asList === l);
};
- asString
A string describing the list. Uses asPrintable on its members, so that, for instance, strings are
displayed with quotes.
[0, [1], "2"].asString == "[0, [1], \"2\"]";
- back
The last element of the target. An error if the target is empty.
assert([0, 1, 2].back == 2);
[].back;
[00000017:error] !!! back: cannot be applied onto empty list
- clear
Empty the target.
var x = [0, 1, 2];
[00000000] [0, 1, 2]
assert(x.clear == []);
- each(fun)
Apply the given functional value fun on all members, sequentially.
[0, 1, 2].each(function (v) {echo (v * v); echo (v * v)});
[00000000] *** 0
[00000000] *** 0
[00000000] *** 1
[00000000] *** 1
[00000000] *** 4
[00000000] *** 4
- eachi(fun)
Apply the given functional value fun on all members sequentially, additionally passing the
current element index.
["a", "b", "c"].eachi(function (v, i) {echo ("%s: %s" % [i, v])});
[00000000] *** 0: a
[00000000] *** 1: b
[00000000] *** 2: c
- ’each&’(fun)
Apply the given functional value on all members simultaneously.
[0, 1, 2].’each&’(function (v) {echo (v * v); echo (v * v)});
[00000000] *** 0
[00000000] *** 1
[00000000] *** 4
[00000000] *** 0
[00000000] *** 1
[00000000] *** 4
- empty
Whether the target is empty.
- filter(fun)
The list of all the members of the target that verify the predicate fun.
do ([0, 1, 2, 3, 4, 5])
{
assert
{
// Keep only odd numbers.
filter(function (v) {v % 2 == 1}) == [1, 3, 5];
// Keep all.
filter(function (v) { true }) == this;
// Keep none.
filter(function (v) { false }) == [];
};
}|;
- foldl(action, value)
Fold, also known as reduce or accumulate, computes a result from a list. Starting from value as
the initial result, apply repeatedly the binary action to the current result and the next member
of the list, from left to right. For instance, if action were the binary addition and value
were 0, then folding a list would compute the sum of the list, including for empty
lists.
[].foldl(function (a, b) { a + b }, 0) == 0;
[1, 2, 3].foldl(function (a, b) { a + b }, 0) == 6;
[1, 2, 3].foldl(function (a, b) { a - b }, 0) == -6;
- front
Return the first element of the target. An error if the target is empty.
assert([0, 1, 2].front == 0);
[].front;
[00000000:error] !!! front: cannot be applied onto empty list
- has(that)
Whether one of the members of the target equals the argument.
[0, 1, 2].has(1);
! [0, 1, 2].has(5);
The infix operators in and not in use has (see Section 22.1.8.7).
1 in [0, 1];
2 not in [0, 1];
!(2 in [0, 1]);
!(1 not in [0, 1]);
- hash
Return a Hash object corresponding to this list value. Two list hashes are equal if the list have
the same size, and elements hashes are equal two by two. See Object.hash.
[].hash.isA(Hash);
[].hash == [].hash;
[1, "foo"].hash == [1, "foo"].hash;
[0, 1].hash != [1, 0].hash;
- hasSame(that)
Whether one of the members of the target is physically equal to that.
var y = 1|;
assert
{
[0, y, 2].hasSame(y);
![0, y, 2].hasSame(1);
};
- head
Synonym for front.
assert([0, 1, 2].head == 0);
[].head;
[00000000:error] !!! head: cannot be applied onto empty list
- insert(where, what)
Insert what before the value at index where, return this.
{
var l = [0, 1];
assert
{
l.insert(0, 10) === l;
l == [10, 0, 1];
l.insert(2, 20) === l;
l == [10, 0, 20, 1];
};
}|;
The index must be valid, to insert past the end, use insertBack.
[].insert(0, "foo");
[00044239:error] !!! insert: invalid index: 0
[1, 2, 3].insert(4, 30);
[00044339:error] !!! insert: invalid index: 4
- insertBack(that)
Insert the given element at the end of the target, return this.
{
var l = [0, 1];
assert
{
l.insertBack(2) === l;
l == [0, 1, 2];
};
}|;
- insertFront(that)
Insert the given element at the beginning of the target. Return this.
{
var l = [0, 1];
assert
{
l.insertFront(0) === l;
l == [0, 0, 1];
};
}|;
- insertUnique(that)
If that is not in this, append it. Return this.
{
var l = [0, 1];
assert
{
l.insertUnique(0) === l;
l == [0, 1];
l.insertUnique(2) === l;
l == [0, 1, 2];
};
};
- join(sep = "", prefix = "", suffix = "")
Bounce to String.join.
["", "ob", ""].join == "ob";
["", "ob", ""].join("a") == "aoba";
["", "ob", ""].join("a", "B", "b") == "Baobab";
- keys
The list of valid indexes. This allows uniform iteration over a Dictionary or a List.
{
var l = ["a", "b", "c"];
assert
{
l.keys == [0, 1, 2];
{
var res = [];
for (var k: l.keys)
res << l[k];
res
}
== l;
};
};
- map(fun)
Apply the given functional value on every member, and return the list of results.
[0, 1, 2, 3].map(function (v) { v % 2 == 0})
== [true, false, true, false];
- matchAgainst(handler, pattern)
If pattern is a List of same size, use handler to match each member of this against the
corresponding pattern. Return true if the match succeeded, false in other cases.
assert
{
([1, 2] = [1, 2]) == [1, 2];
([1, var a] = [1, 2]) == [1, 2];
a == 2;
([var u, var v, var w] = [1, 2, 3]) == [1, 2, 3];
[u, v, w] == [1, 2, 3];
};
[1, 2] = [2, 1];
[00005863:error] !!! pattern did not match
[1, var a] = [2, 1];
[00005864:error] !!! pattern did not match
[1, var a] = [1];
[00005865:error] !!! pattern did not match
[1, var a] = [1, 2, 3];
[00005865:error] !!! pattern did not match
- max(fun = function(a, b) { a < b })
Return the “largest” member based on the comparison function fun.
[1].max == 1;
[1, 2].max == 2;
[2, 1].max == 2;
[2, -1, 3, -4].max == 3;
[2, -1, 3, -4].max (function (a, b) { a.abs < b.abs }) == -4;
The list cannot be empty.
[].max;
[00000001:error] !!! max: list cannot be empty
The members must be comparable.
[0, 2, "a", 1].max;
[00000002:error] !!! max: argument 2: unexpected "a", expected a Float
- min(fun = function(a, b) { a < b })
Return the “smallest” member based on the comparison function fun.
[1].min == 1;
[1, 2].min == 1;
[2, 1].min == 1;
[2, -1, 3, -4].min == -4;
[2, -1, 3, -4].min (function (a, b) { a.abs < b.abs }) == -1;
The list cannot be empty.
[].min;
[00000001:error] !!! min: list cannot be empty
- range(begin, end = nil)
Return a sub-range of the list, from the first index included to the second index excluded. An
error if out of bounds. Negative indices are valid, and number from the end.
If end is nil, calling range(n) is equivalent to calling range(0, n).
do ([0, 1, 2, 3])
{
assert
{
range(0, 0) == [];
range(0, 1) == [0];
range(1) == [0];
range(1, 3) == [1, 2];
range(-3, -2) == [1];
range(-3, -1) == [1, 2];
range(-3, 0) == [1, 2, 3];
range(-3, 1) == [1, 2, 3, 0];
range(-4, 4) == [0, 1, 2, 3, 0, 1, 2, 3];
};
}|;
[].range(1, 3);
[00428697:error] !!! range: invalid index: 1
- remove(val)
Remove all elements from the target that are equal to val, return this.
var c = [0, 1, 0, 2, 0, 3]|;
assert
{
c.remove(0) === c; c == [1, 2, 3];
c.remove(42) === c; c == [1, 2, 3];
};
- removeBack
Remove and return the last element of the target. An error if the target is empty.
var t = [0, 1, 2];
[00000000] [0, 1, 2]
assert(t.removeBack == 2);
assert(t == [0, 1]);
[].removeBack;
[00000000:error] !!! removeBack: cannot be applied onto empty list
- removeById(that)
Remove all elements from the target that physically equals that.
var d = 1|;
var e = [0, 1, d, 1, 2]|;
assert
{
e.removeById(d) == [0, 1, 1, 2];
e == [0, 1, 1, 2];
};
- removeFront
Remove and return the first element from the target. An error if the target is empty.
var g = [0, 1, 2]|;
assert
{
g.removeFront == 0;
g == [1, 2];
};
[].removeFront;
[00000000:error] !!! removeFront: cannot be applied onto empty list
- reverse
Return the target with the order of elements inverted.
[0, 1, 2].reverse == [2, 1, 0];
- size
Return the number of elements in the target.
[0, 1, 2].size == 3;
[].size == 0;
- sort(fun = function(a, b) { a < b })
A new List with the contents of this, sorted with respect to the comp comparison
function.
{
var l = [3, 0, -2, 1];
assert
{
l.sort == [-2, 0, 1, 3];
l == [3, 0, -2, 1];
l.sort(function(a, b) {a.abs < b.abs})
== [0, 1, -2, 3];
};
};
- subset(that)
Whether the members of this are members of that.
[].subset([]);
[].subset([1, 2, 3]);
[3, 2, 1].subset([1, 2, 3]);
[1, 3].subset([1, 2, 3]);
[1, 1].subset([1, 2, 3]);
![3].subset([]);
![3, 2].subset([1, 2]);
![1, 2, 3].subset([1, 2]);
- tail
Return the target, minus the first element. An error if the target is empty.
assert([0, 1, 2].tail == [1, 2]);
[].tail;
[00000000:error] !!! tail: cannot be applied onto empty list
- zip(fun, other)
Zip this list and the other list with the fun function, and return the list of results.
[1, 2, 3].zip(closure (x, y) { (x, y) }, [4, 5, 6])
== [(1, 4), (2, 5), (3, 6)];
[1, 2, 3].zip(closure (x, y) { x + y }, [4, 5, 6])
== [5, 7, 9];
- ’==’(that)
Check whether all elements in the target and that, are equal two by two.
[0, 1, 2] == [0, 1, 2];
!([0, 1, 2] == [0, 0, 2]);
- ’[]’(n)
Return the nth member of the target (indexing is zero-based). If n is negative, start from the end.
An error if out of bounds.
assert
{
["0", "1", "2"][0] == "0";
["0", "1", "2"][2] == "2";
};
["0", "1", "2"][3];
[00007061:error] !!! []: invalid index: 3
assert
{
["0", "1", "2"][-1] == "2";
["0", "1", "2"][-3] == "0";
};
["0", "1", "2"][-4];
[00007061:error] !!! []: invalid index: -4
- ’[]=’(index, value)
Assign value to the element of the target at the given index.
var f = [0, 1, 2];
[00000000] [0, 1, 2]
assert
{
(f[1] = 42) == 42;
f == [0, 42, 2];
};
for (var i: [0, 1, 2])
f[i] = 10 * f[i];
assert (f == [0, 420, 20]);
- ’*’(n)
Return the target, concatenated n times to itself.
[0, 1] * 0 == [];
[0, 1] * 3 == [0, 1, 0, 1, 0, 1];
n must be a non-negative integer.
[0, 1] * -2;
[00000063:error] !!! *: argument 1: expected non-negative integer, got -2
Note that since it is the very same list which is repeatedly concatenated (the content is not
cloned), side-effects on one item will reflect on “all the items”.
var l = [[]] * 3;
[00000000] [[], [], []]
l[0] << 1;
[00000000] [1]
l;
[00000000] [[1], [1], [1]]
- ’+’(other)
Return the concatenation of the target and the other list.
[0, 1] + [2, 3] == [0, 1, 2, 3];
[] + [2, 3] == [2, 3];
[0, 1] + [] == [0, 1];
[] + [] == [];
The target is left unmodified (contrary to ’+=’).
{
var l = [1, 2, 3];
assert
{
l + l == [1, 2, 3, 1, 2, 3];
l == [1, 2, 3];
};
};
- ’+=’(that)
Concatenate the contents of the List that to this, and return this. This function modifies its
target, contrary to ’+’. See also ’<<’.
{
var l = [];
var alias = l;
assert
{
(l += [1, 2]) == l;
l == [1, 2];
(l += [3, 4]) == l;
l == [1, 2, 3, 4];
alias == [1, 2, 3, 4];
};
};
- ’-’(other)
Return the target without the elements that are equal to any element in the other
list.
[0, 1, 0, 2, 3] - [1, 2] == [0, 0, 3];
[0, 1, 0, 1, 0] - [1, 2] == [0, 0, 0];
- ’<<’(that)
A synonym for insertBack.
- ’<’(other)
Return whether this is less than the other list. This is the lexicographic comparison:
this is “less that” if one of its member is “less than” the corresponding member of
other:
[0, 0, 0] < [0, 0, 1];
[0, 1, 2] < [0, 2, 1];
!([0, 1, 2] < [0, 1, 2]);
!([0, 1, 2] < [0, 0, 2]);
or other is a prefix (strict) of this:
[] < [0]; !( [0] < []);
[0, 1] < [0, 1, 2]; !([0, 1, 2] < [0, 1]);
!([0, 1, 2] < [0, 1, 2]);
Since List derives from Orderable, the other order-based operators are defined.
[] <= [];
[] <= [0, 1, 2];
[0, 1, 2] <= [0, 1, 2];
[] >= [];
[0, 1, 2] >= [];
[0, 1, 2] >= [0, 1, 2];
[0, 1, 2] >= [0, 0, 2];
!([] > []);
[0, 1, 2] > [];
!([0, 1, 2] > [0, 1, 2]);
[0, 1, 2] > [0, 0, 2];
23.33 Loadable
Loadable objects can be switched on and off — typically physical devices.
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
Loadable can be constructed, but it hardly makes sense. This object should serve as a
prototype.
- load
The current status.
- off(val)
Set load to false and return this.
do (Loadable.new)
{
assert
{
!load;
off === this;
!load;
on === this;
load;
off === this;
!load;
};
};
- on(val)
Set load to true and return this.
do (Loadable.new)
{
assert
{
!load;
on === this;
load;
on === this;
load;
};
};
- toggle
Set load from true to false, and vice-versa. Return val.
do (Loadable.new)
{
assert
{
!load;
toggle === this;
load;
toggle === this;
!load;
};
};
23.34 Lobby
A lobby is the local environment for each (remote or local) connection to an Urbi server.
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
Since every lobby is-a Channel, one can use the methods of Channel.
lobby << 123;
[00478679] 123
lobby << "foo";
[00478679] "foo"
- authors
Credit the authors of Urbi SDK. See also thanks and Section 1.4.
lobby.authors;
[00478679] *** Authors of Urbi:
[00478679] *** - Jean-Christophe Baillie (original designer)
[00478679] ***
[00478679] *** Urbi 2 and subsequent versions:
[00478679] *** - Akim Demaille
[00478679] *** - Matthieu Nottale
[00478679] *** - Quentin Hocquet
[00478679] ***
[00478679] *** See also ‘thanks;’.
- banner
Internal. Display Urbi SDK banner.
lobby.banner;
[00006124] *** ********************************************************
[00006124] *** Urbi version 2.7.4 rev. 268868e
[00006124] *** Copyright (C) 2004-2012 Gostai S.A.S.
[00006124] ***
[00006124] *** This program comes with ABSOLUTELY NO WARRANTY. It can
[00006124] *** be used under certain conditions. Type ‘license;’,
[00006124] *** ‘authors;’, or ‘copyright;’ for more information.
[00006124] ***
[00006124] *** Check our community site: http://www.urbiforge.org.
[00006124] *** ********************************************************
- bytesReceived
The number of bytes that were “input” to this. See also receive.
var l = Lobby.create|;
assert (l.bytesReceived == 0);
l.receive("123456789;");
[00000022] 123456789
assert (l.bytesReceived == 10);
l.receive("1234;");
[00000023] 1234
assert (l.bytesReceived == 15);
- bytesSent
The number of bytes that were “output” by this. See also send and write.
var l = Lobby.create|;
assert (l.bytesSent == 0);
l.send("0123456789");
[00011988] 0123456789
// 22 = "[00011988] 0123456789\n".size.
assert (l.bytesSent == 22);
l.send("xx", "label");
[00061783:label] xx
// 20 = "[00061783:label] xx\n".size.
assert (l.bytesSent == 42);
l.write("[01234567]\n");
[01234567]
assert (l.bytesSent == 53);
- connected
Whether this is connected.
- connectionTag
The tag of all code executed in the context of this. This tag applies to this, but the top-level
loop is immune to Tag.stop, therefore connectionTag controls every thing that was launched
from this lobby, yet the lobby itself is still usable.
every (1s) echo(1), sleep(0.5s); every (1s) echo(2),
sleep(1.2s);
connectionTag.stop;
[00000507] *** 1
[00001008] *** 2
[00001507] *** 1
[00002008] *** 2
"We are alive!";
[00002008] "We are alive!"
every (1s) echo(3), sleep(0.5s); every (1s) echo(4),
sleep(1.2s);
connectionTag.stop;
[00003208] *** 3
[00003710] *** 4
[00004208] *** 3
[00004710] *** 4
"and kicking!";
[00002008] "and kicking!"
Of course, a background job may stop a foreground one.
{ sleep(1.2s); connectionTag.stop; },
// Note the ‘;’, this is a foreground statement.
every (1s) echo(5);
[00005008] *** 5
[00005508] *** 5
"bye!";
[00006008] "bye!"
- copyright(deep = true)
Display the copyright of Urbi SDK. Include copyright information about sub-components if deep.
lobby.copyright(false);
[00028588] *** Urbi version 2.7.4 rev. 268868e
[00028588] *** Copyright (C) 2004-2012 Gostai S.A.S.
lobby.copyright;
[00041874] *** Urbi version 2.7.4 rev. 268868e
[00041874] *** Copyright (C) 2004-2012 Gostai S.A.S.
[00041874] ***
[00041874] *** Libport version 2.7.4 rev. 268868e
[00041874] *** Copyright (C) 2004-2012 Gostai S.A.S.
- create
Instantiate a new Lobby.
- echo(value, channel = "")
Send value.asString to this, prefixed by the String channel name if specified. This is the
preferred way to send informative messages (prefixed with ‘***’).
lobby.echo("111", "foo");
[00015895:foo] *** 111
lobby.echo(222, "");
[00051909] *** 222
lobby.echo(333);
[00055205] *** 333
- echoEach(list, channel = "")
Apply echo(m, channel) for each member m of list.
lobby.echo([1, "2"], "foo");
[00015895:foo] *** [1, "2"]
lobby.echoEach([1, "2"], "foo");
[00015895:foo] *** 1
[00015895:foo] *** 2
lobby.echoEach([], "foo");
- instances
A list of the currently alive lobbies. It contains at least the Lobby object itself, and the current
lobby.
lobby in Lobby.instances;
Lobby in Lobby.instances;
- license
Display the end user license agreement of the Urbi SDK.
lobby.license;
[00000000] *** GNU AFFERO GENERAL PUBLIC LICENSE
[00000000] *** Version 3, 19 November 2007
[00000000] ***
[00000000] *** Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
[00000000] *** Everyone is permitted to copy and distribute verbatim copies
[00000000] *** of this license document, but changing it is not allowed.
[00000000] ***
[...]
[00000000] *** For more information on this, and how to apply and follow the GNU AGPL, see
[00000000] *** <http://www.gnu.org/licenses/>.
- lobby
The lobby of the current connection. This is typically this.
But when several connections are active (e.g., when there are remote connections), it can be
different from the target of the call.
Lobby.create| Lobby.create|;
for (var l : lobbies)
assert (l.lobby == Lobby.lobby);
- onDisconnect(lobby)
Event launched when this is disconnected. There is a single event instance for all the lobby,
Lobby.onDisconnect, the disconnected lobby being passed as argument.
- quit
Shut this lobby down, i.e., close the connection. The server is still running, see System.shutdown
to quit the server.
- receive(value)
This is low-level routine. Pretend the String value was received from the connection. There is
no guarantee that value will be the next program block that will be processed: for instance, if
you load a file which, in its middle, uses lobby.receive("foo"), then "foo" will be appended
after the end of the file.
Lobby.create.receive("12;");
[00478679] 12
- remoteIP
When this is connected to a remote server, it’s Internet address.
- send(value, channel = "")
This is low-level routine. Send the String value to this, prefixed by the String channel name
if specified.
lobby.send("111", "foo");
[00015895:foo] 111
lobby.send("222", "");
[00051909] 222
lobby.send("333");
[00055205] 333
- thanks
Credit the contributors of Urbi SDK. See also authors and Section 1.4.
lobby.thanks;
[00478679] *** Contributors to Urbi:
[00478679] ***
[00478679] *** - Adam Oleksy <adam.oleksy@pwr.wroc.pl>
[00478679] *** - Alexandre Morgand
[...]
[00478679] ***
[00478679] *** See also ‘authors;’.
- wall(value, channel = "")
Perform echo(value, channel) on all the existing lobbies (except Lobby itself).
Lobby.wall("111", "foo");
[00015895:foo] *** 111
- write(value)
This is low-level routine. Send the String value to the connection. Note that because of
buffering, the output might not be visible before an end-of-line character is output.
lobby.write("[");
lobby.write("999999999:");
lobby.write("myTag] ");
lobby.write("Hello, World!");
lobby.write("\n");
[999999999:myTag] Hello, World!
23.35 Location
This class aggregates two Positions and provides a way to print them as done in error
messages.
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
23.36 Logger
Logger is used to report information to the final user or to the developer. It allows to pretty print
warnings, errors, debug messages or simple logs. Logger can also be used as Tag objects for it to
handle nested calls indentation. A log message is assigned a category which is shown between brackets
at beginning of lines, and a level which defines the context in which it has to be shown (see
Section 21.1.2). Log level definition and categories filtering can be changed using environment
variables defined in Section 21.1.2.
The proper use of Loggers is to instantiate your own category, and then to use the operator << for log
messages, possibly qualified by the proper level (in increase order of importance: dump, debug, trace,
log, warn, err):
var logger = Logger.new("Category")|;
logger.dump << "Low level debug message"|;
// Nothing displayed, unless the debug level is set to DUMP.
logger.warn << "something wrong happened, proceeding"|;
[ Category ] something wrong happened, proceeding
logger.err << "something really bad happened!"|;
[ Category ] something really bad happened!
You may also directly use the logger and passing arguments to these slots.
Logger.log("message", "Category") |;
[ Category ] message
Logger.log("message", "Category") :
{
Logger.log("indented message", "SubCategory")
}|;
[ Category ] message
[ SubCategory ] indented message
Logger can be used as is, without being cloned. It is possible to clone Logger defining a category
and/or a level of debug.
Logger.log("foo");
[ Logger ] foo
[00004702] Logger<Logger>
Logger.log("foo", "Category") |;
[ Category ] foo
var l = Logger.new("Category2");
[00004703] Logger<Category2>
l.log("foo")|;
[ Category2 ] foo
l.log("foo", "ForcedCategory") |;
[ ForcedCategory ] foo
- ’<<’(object)
Allow to use the Logger object as a Channel. This slot can only be used if both category
and level have been defined when cloning.
l = Logger.new("Category", Logger.Levels.Log);
[00090939] Logger<Category>
l << "foo";
[ Category ] foo
[00091939] Logger<Category>
- debug(message = "", category = category)
Report a debug message of category to the user. It will be shown if the debug level is Debug or
Dump. Return this to allow chained operations.
// None of these are displayed unless the current level is at least DEBUG.
logger.debug << "debug 1"|;
logger.debug("debug 2")|;
logger.debug("debug 3", "Category2")|;
- dump(message = "", category = category)
Report a debug message of category to the user. It will be shown if the debug level is Dump.
Return this to allow chained operations.
// None of these are displayed unless the current level is at least DEBUG.
logger.dump << "dump 1"|;
logger.dump("dump 2")|;
logger.dump("dump 3", "Category2")|;
- err(message = "", category = category)
Report an error message of category to the user. Return this to allow chained
operations.
- init(category)
Define the category of the new Logger object. If no category is given the new Logger will
inherit the category of its prototype.
- Levels
An Enumeration of the log levels defined in Section 21.1.2.
Logger.Levels.values;
[00000001] [None, Log, Trace, Debug, Dump]
- log(message = "", category = category)
Report a debug message of category to the user. It will be shown if debug is not disabled.
Return this to allow chained operations.
logger.log << "log 1"|;
[ Category ] log 1
logger.log("log 2")|;
[ Category ] log 2
logger.log("log 3", "Category2")|;
[ Category2 ] log 3
- onEnter
The primitive called when Logger is used as a Tag and is entered. This primitive only increments
the indentation level.
- onLeave
The primitive called when Logger is used as a Tag and is left. This primitive only decrements the
indentation level.
- trace(message = "", category = category)
Report a debug message of category to the user. It will be shown if the debug level is Trace,
Debug or Dump. Return this to allow chained operations.
// None of these are displayed unless the current level is at least TRACE.
logger.trace << "trace 1"|;
logger.trace("trace 2")|;
logger.trace("trace 3", "Category2")|;
- warn(message = "", category = category)
Report a warning message of category to the user. Return this to allow chained operations.
logger.warn << "warn 1"|;
[ Category ] warn 1
logger.warn("warn 2")|;
[ Category ] warn 2
logger.warn("warn 3", "Category2")|;
[ Category2 ] warn 3
23.37 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.
Since it is a Singleton, you are not expected to build other instances.
- abs(float)
Bounce to float.abs.
Math.abs(1) == 1;
Math.abs(-1) == 1;
Math.abs(0) == 0;
Math.abs(3.5) == 3.5;
- acos(float)
Bounce to float.acos.
- asin(float)
Bounce to float.asin.
- atan(float)
Bounce to float.atan.
- atan2(x, y)
Bounce to x.atan2(y).
Math.atan2(2, 2) ∼= pi/4;
Math.atan2(-2, 2) ∼= -pi/4;
- cos(float)
Bounce to float.cos.
Math.cos(0) == 1;
Math.cos(pi) ∼= -1;
- exp(float)
Bounce to float.exp.
- inf
Bounce to Float.inf.
- log(float)
Bounce to float.log.
- max(arg1, ...)
Bounce to [arg1, ...].max, see List.max.
max( 100, 20, 3 ) == 100;
max("100", "20", "3") == "3";
- min(arg1, ...)
Bounce to [arg1, ...].min, see List.min.
min( 100, 20, 3 ) == 3;
min("100", "20", "3") == "100";
- nan
Bounce to Float.nan.
- pi
Bounce to Float.pi.
- random(float)
Bounce to float.random.
- round(float)
Bounce to float.round.
Math.round(1) == 1;
Math.round(1.1) == 1;
Math.round(1.49) == 1;
Math.round(1.5) == 2;
Math.round(1.51) == 2;
- sign(float)
Bounce to float.sign.
Math.sign(2) == 1;
Math.sign(-2) == -1;
Math.sign(0) == 0;
- sin(float)
Bounce to float.sin.
Math.sin(0) == 0;
Math.sin(pi) ∼= 0;
- sqr(float)
Bounce to float.sqr.
- sqrt(float)
Bounce to float.sqrt.
- srandom(float)
Bounce to float.srandom.
- tan(float)
Bounce to float.tan.
- trunc(float)
Bounce to float.trunc.
Math.trunc(1) == 1;
Math.trunc(1.1) == 1;
Math.trunc(1.49) == 1;
Math.trunc(1.5) == 1;
Math.trunc(1.51) == 1;
23.38 Mutex
Mutex allow to define critical sections.
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.
- asMutex
Return this.
var m1 = Mutex.new|;
assert
{
m1.asMutex === m1;
};
23.39 nil
The special entity nil is an object used to denote an empty value. Contrary to void, it is a regular
value which can be read.
Being a singleton, nil is not to be constructed, just used.
- isNil
Whether this is nil. I.e., true. See also Object.isNil.
nil.isNil;
!Object.isNil;
23.40 Object
Object includes the mandatory primitives for all objects in urbiscript. All objects in urbiscript
must inherit (directly or indirectly) from it.
A fresh object can be instantiated by cloning Object itself.
Object.new;
[00000421] Object_0x00000000
The keyword class also allows to define objects intended to serve as prototype of a family
of objects, similarly to classes in traditional object-oriented programming languages (see
Section 11.4).
{
class Foo
{
var attr = 23;
};
assert
{
Foo.localSlotNames == ["asFoo", "attr", "type"];
Foo.asFoo === Foo;
Foo.attr == 23;
Foo.type == "Foo";
};
};