AgentSpeak(L++) does not support looping directly; however, we support lambda expressions which are based on lambda calculus. Similar to a for each call, each element in an input list (variable) can be looped.
This example creates a list of the number [1,20) and we are looping over the elements, first in sequential order and call the print action for each element and in the second call we add each value to the variable R. R is in this case the returning variable
L = collection/list/range(1, 20); (L) -> Y : generic/print(Y); (L) -> Y | R : R = Y+1;
Practical Example
This concept especially makes sense in situations where efficient processing of multiple elements is desired. Consider an agent Alice with a custom action myfriends( Phonebook )
which returns a list of her closest friends from her phone book. If Alice would want to send an invitation to each of her closest friends, she could use a lambda expression to send a message to each of them:
+!main
<-
L = myfriends( Phonebook );
(L) -> Friend : message/send( Friend, content( “invitation to my birthday, next week” ) )
.
But, can we optimise this further?
Alice probably would not want to wait until the message gets delivered. In practice she would hand all the envelopes to the postal clerk at the same time to have her mind free for other tasks.
The same can be achieved by adding the → annotation @
to the lambda expression to instruct LightJason to execute the expression in parallel:
+!main
<-
L = myfriends( Phonebook );
@(L) -> Friend : message/send( Friend, content( “invitation to my birthday, next week” ) )
.
But, what if some of her friends have to be invited via different kinds of messengers?
Here the feature that LightJason executes → plans with different plan signatures in parallel comes into play. Alice simply creates a plan +!sendinvitation( Friend )
to do the job. This plan gets executed in the next cycle (see → advanced triggering) and can also decide on how each friend can be reached best.
Note: Alice removed the
@
from the lambda expression as the plans will be executed in the next cycle in parallel.
+!main <- L = myfriends( Phonebook ); (L) -> Friend : !sendinvitation( Friend ) .
+!sendinvitation( Friend ) : isreachablebyemail( Friend ) <- message/send/email( Friend, content( “invitation to my birthday, next week” ) ) : isreachablebyjabber( Friend ) <- message/send/jabber( Friend, content( “invitation to my birthday, next week” ) ) .