URBI - введение в urbiScript - часть 5

1. введение в urbiScript — часть 1
2. введение в urbiScript — часть 2
3. введение в urbiScript — часть 3
4. введение в urbiScript — часть 4
5. введение в urbiScript — часть 5

Продолжаем рассмотрение возможностей скриптового языка urbiScript от компании Gostai, предназначенного для управления роботами.

Последовательное программирование не удобно при работе с высоко-интерактивными агентами (роботами). Для этого требуется реагировать на внешние случайные события, а не линейно выполнять заданный код.
urbiScript полностью отвечает этому требованию, т.к. поддерживает программирование на основе событий (event-based programming).

25. Конструкции контроля событий

25.1 at

Первая конструкция событийного программирования — это ключевое слово at.
at(выражение)
	код
onleave
	код2

Код будет выполняться всякий раз, когда выражение будет истинно.
var x = 0;
[00000000] 0
at (x > 5)
	echo("ping");
x = 5;
[00000000] 5
// это запустит(trigger) событие
x = 6;
[00000000] 6
[00000000] *** ping
// код не запускается(trigger), т.к. выражение уже истинно.
x = 7;
[00000000] 7
// выражение станет ложным
x = 3;
[00000000] 3
x = 10;
[00000000] 10
[00000000] *** ping


Блок onleave может определять код для выполнения, кода выражение становится ложным.
var x = false;
[00000000] false
at (x)
	echo("x")
onleave
	echo("!x");
x = true;
[00000000] true
[00000000] *** x
x = false;
[00000000] false
[00000000] *** !x


25.2 whenever

Ключевое слово whenever аналогично at, однако выполнение кода систематически перезапускается в случае если условие/выражение остаётся истинным.

var x = false;
[00000000] false
whenever (x)
{
	echo("ping");
	sleep(1s);
};
x = true;
[00000000] true
sleep(3s);
// код whenever выполняется снова и снова
[00000000] *** ping
[00001000] *** ping
[00002000] *** ping
x = false;
[00002000] false
// код whenever не выполняется


Как at имеет onleave, так и whenever имеет else: код будет выполняться снова и снова пока выражение/условие остаётся ложным.

var x = false;
[00002000] false
whenever (x)
{
	echo("ping");
	sleep(1s);
}
else
{
	echo("pong");
	sleep(1s);
};
sleep (3s);
[00000000] *** pong
[00001000] *** pong
[00002000] *** pong
x = true;
[00003000] true
sleep (3s);
[00003000] *** ping
[00004000] *** ping
[00005000] *** ping
x = false;
[00006000] false
sleep (2s);
[00006000] *** pong
[00007000] *** pong


25.3 every

Ключевое слово every позволяет запустить повторение выполнения кода через заданный период времени.

// печатает сообщение каждую секунду
timeout (2.1s)
	every (1s)
		echo("Are you still there?");
[00000000] *** Are you still there?
[00001000] *** Are you still there?
[00002000] *** Are you still there?


25.4 waituntil

конструкция waituntil схожа c at, она используется для задержки выполнения участка кода, пока не будет выполнено заданное условие, которое может быть либо событием, либо логическим выражением.
var e = Event.new;
{
	waituntil (e?);
	echo ("caught e");
},
e!;
[00021054] *** caught e


26. События

urbiScript позволяет определять события, которые должны обрабатываться с помощью конструкций at и whenever.
Событие может быть создано с использованием прототипа Event. Запуск события можно выполнить с помощью команды (!).

var myEvent = Event.new;
[00000000] Event_0x0
at (myEvent?)
	echo("ping");
myEvent!;
[00000000] *** ping
// события хорошо работают параллельно
myEvent! & myEvent!;
[00000000] *** ping
[00000000] *** ping


С событиями at и whenever работают, как и было показано ранее. Т.е. at отрабатывает один раз при изменении/переключении условия/выражения. А код whenever выполняется снова и снова.
var myEvent = Event.new;
[00000000] Event_0x0
whenever (myEvent?)
{
	echo("ping (whenever)")|
	sleep(200ms)
};
at (myEvent?)
{
	echo("ping (at)")|
	sleep(200ms)
};
// запустим myEvent на 0.3 секунды
myEvent! ~ 300ms;
[00000000] *** ping (whenever)
[00000100] *** ping (whenever)
[00000000] *** ping (at)


27. Исключения

Для вызова исключения используется ключевое слово throw. Вызов исключения прерывает выполнение пока оно не будет обработано или пока не достигнут верхний уровень:

throw 42;
[00000000:error] !!! 42
function inner() { throw "exn" } |
function outer() { inner() }|
// Exceptions propagate to parent call up to the top-level
outer();
[00000000:error] !!! exn
[00000000:error] !!! called from: 3.20-26: inner
[00000000:error] !!! called from: 4.1-7: outer 


27.1 Перехват исключений
Перехват исключений осуществляется конструкцией try/catch.
В блоке try заключается операция, которая может вызвать исключение. Перехват исключения осуществляется последующими блоками catch, каждый из которых имеет паттерн с которым сравнивается возникшее исключение.

Возникшее исключение в блоке try последовательно сравнивается с паттерном блоков catch.
В случае совпадения, выполняется код соответствующего блока и выполнение продолжается после блока try/catch.
Если подходящего паттерна не нашлось, то исключение не будет перехвачено и оно пройдёт дальше.
function test(e)
{
	try
	{ throw e; }
	catch (0)
	{ echo("zero") }
	catch ([var x, var y])
	{ echo(x + y) }
} | {};
test(0);
[00002126] *** zero
test([22, 20]);
[00002131] *** 42
test(51);
[00002143:error] !!! 51
[00002143:error] !!! called from: 12.1-8: test


27.2 Просмотр исключений
Исключение — это объект Exception, у которого можно посмотреть свойства.

try
{
	Math.cos(3,1415);
}
catch (var e)
{
	echo ("Exception type: %s" % e.type);
	if (e.isA(Exception.Arity))
	{
		echo("Routine: %s" % e.routine);
		echo("Number of effective arguments: %s" % e.effective);
	};
};


28. Проверки с помощью assert

функция assert позволяет осуществлять проверки в коде. Эта функция очень полезна для отладки и отлова ошибок во время написания программы.
Однако использование этой функции в конечной версии программы нежелательно, т.к. сильно влияет на производительность.
Поэтому assert-ы можно отключить через System.ndebug.
Если переменную System.ndebug установить в true, то assert-ы выполняться не будут.
function one() { echo("called!"); 1 }|;
assert(!System.ndebug);
assert(one);
[00000617] *** called!
System.ndebug = true|;
assert(one);
System.ndebug = false|;
assert(one);
[00000622] *** called!


assert можно вызывать как обычную функцию, либо применительно к целой области
assert(1 == 1 + 1);
[00000002:error] !!! failed assertion: 1 == 1.'+'(1) (1 != 2)
assert
{ 
	1==1;
	2==2;
};
assert
{
	1==1; 
	2==3;
};
[00000000:error] !!! 30.1588-1591: failed assertion: 2 == 3 (2 != 3)
[00000000:error] !!! called from: 30.1588-1591: assertCall
  • +1
  • 24 ноября 2010, 10:49
  • noonv

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.