Getting Started | Documentation | Glish | Learn More | Programming | Contact Us |
Version 1.9 Build 1556 |
|
As noted earlier, all interactions between the Glish interpreter and agents happen by sending and receiving events. This separation encourages isolation of the system components. This isolation makes the components more reusable because they have a well defined interface. All of this means that these agents can be knitted together by the Glish interpreter in unanticipated ways. Each agent becomes a pluggable component of the system.
In general, events are sent to agents like:
demo := client("my_demo") demo->foo( [1, 4, 6] )In this example, the agent demo is a process running on the local operating system. The client function is used to create such agents. (See § 7.8, page .) Once the demo agent is created, a foo event is sent to demo with a value of [1, 4, 6].
In this case, no result was expected from demo as a result of the foo event. If the event had been sent in a different context, the interpreter would have waited for a result from the agent. For example (continuing the previous example):
if ( demo->bar( 1.71 ) ) print "true from demo"In this case, because of the context in which the event is sent, the interpreter waits for a result from demo and output is generated only if the result resolves to T. When the client process, ``my_demo'', receives the event, it is notified that a result is expected (See § 15.2, page ).
Sending an event is in many ways similar to making a function call. Values can be obtained from an agent:
v := database->get_voltage( 1:10 )This example sends a get_voltage event to the agent database with a value of 1:10, waits for database to generate an event in response, and assigns the value of that response to v. More than one value can be sent to an agent:
database->insert( "integral", 2.9812 )This example sends database an event with two values, the string "integral" and 2.9812. Values sent to an agent can also be named:
c := 0 while ( v := database->get( table = "A", offset = c +:= 1 ) ) print vThis example repeatedly sends get events to the client with the ``parameter'' table equal to
"A"
and offset equal to
c. Here, c is incremented each time through the
loop before
the event is sent. The loop only stops when demo
returns a value which
resolves to F. Passing these multi-element event
values is equivalent
to passing a single-valued event where the value is a record.
This last example,
for instance, is equivalent to:
c := 0 while ( v := database->get( [table = "A", offset = c +:= 1] ) ) print vFinally, if no values are are specified the event values is the boolean scalar F. Here:
print database->version( )the value which accompanies this version event is F.
It is important to note that the context (whether a result is required or not) affects the event that goes to the agent. In general, the only time when a result is not expected is when the expression that sends the event is on a line by itself. It is the difference between:
print any_client->event( 1:10 )and
any_client->event( 1:10 )In the first case, a result is needed so the event type that the client receives indicates that it needs to generate a result event. In the second case, no result is required.
In the cases above, events were sent to agents, but the agents only generated an event when it was required by events received by the agent. This happened in a request/reply sort of dialog between the interpreter and an agent. Agents can, however, generate events at anytime, and Glish has language constructs to deal with these events. These events can occur at anytime regardless of what the Glish interpreter is busy doing.
Suppose a is an agent-valued variable. In a Glish program you can process events that a generates using a whenever statement. Once executed,
a := client("demo") whenever a->bar do print "got a bar event"prints "got a bar event" every time the demo process generates a bar event.
The value of the most recently received event is kept in a special variable $value:
whenever a->bar do print "got a bar event =", $valueThis will display the value of each bar event that a generates.
The $value can be used in expressions just like other variables. Here's a fragment that only prints out the value of the bar event if it's an integer vector with 3 elements:
whenever a->bar do if ( is_integer($value) && len($value) == 3 ) print "got a bar event =", $valueThis fragment prints every other bar event:
count := 0 whenever a->bar do { count +:= 1 if ( count % 2 == 1 ) print $value }Event values can be stored in variables and record fields just like any other value:
last_bar := "none" whenever a->bar do { print "got a bar event =", $value print "the previous bar event was", last_bar last_bar := $value }This prints out both the value of each of a's bar events and the value the event had the previous time it was received. The output from this program looks something like:
got a bar event = 3 the previous bar event was none got a bar event = hello there the previous bar event was 3 got a bar event = 1 4 7 the previous bar event was hello thereand so on.
Furthermore, each agent value is also a record. (See § 7.2.2, page .) Whenever the agent generates an event, a field in the record with that event's name is set to the event's value. This means that:
whenever a->bar do print "got a bar event =", $valueis equivalent to
whenever a->bar do print "got a bar event =", a.barand that it's easy to refer to past events with different names:
whenever a->bar do { print "got a bar event =", a.bar print "the last foo event was", a.foo }