Flow control
Flow control is an essential tool in all programming languages, and Colang supports this as well. It enables branching and repetition of interaction patterns in a single flow.
Conditional Branching (if/elif/else)
Syntax definition of conditional branching:
The conditional branching is a well known concept and works identical to Python:
control_flow_tools/conditional_branching/main.co
In this example, the bot’s reaction depends on the state of the variable $number_of_users that would contain the number of available users.
Event Branching (when/or when/else)
Event branching is a new Colang-based concept that enables a branching based on expected events.
Syntax definition of event-based branching:
- The
<MixedGroup>stands for a mixed grouping of flows, actions and events - All actions and flows in the
when/or whenstatements will be started concurrently - If neither the
or whennor theelsestatement is used, thewhenconstruct could be replaced with either just anawaitormatchstatement
With the concurrent pattern matching mechanism, we have already seen one way to design a branching interaction pattern based on the user’s input:
control_flow_tools/concurrent_patterns/main.co
Depending on the user’s answer we will get a different bot reaction. Although this concurrent flow mechanism is very powerful, it is sometimes better to have everything in a single flow with the help of the when construct:
control_flow_tools/event_branching/main.co
The number of cases can easily be extended by adding more or when statements. The else statement will only trigger if all of the when/or when statements have failed.
From the definition we see that when/or when statements support mixed groups that can contain events, actions, and flows. For events, this works like a match statement, whereas for actions and flows, it behaves like an await statement. Therefore, actions and flows will be started and then matched with their Finished event. Note that all flows and actions will be started concurrently in the different when/or when statements and stopped as soon as the first case succeeds.
All started flows and actions in all the when/or when statements will be stopped as soon as one of the cases succeeded.
We can also use this construct to easily create a branching for a flow that either finishes or fails:
control_flow_tools/catch_failing_flow/main.co
Due to the event generation conflict resolution, 'pattern b' will fail for the user input “Hello”, but successfully finish for the user input “Hi”:
It is considered “bad design” when used with action-like flows that start with an action:
This example will not work correctly because only one of the two actions will be started due to the action conflict between UtteranceBotAction and GestureBotAction. Note that such cases can be easily detected when following a proper flow naming convention since when bot say "Hi there!" is grammatically incorrect. The example above would need to be implemented like this:
The when/or when/else branching should only be used with intent-like flows.
Loop (while)
Syntax definition of a loop:
In this example, the bot will count from one to ten:
control_flow_tools/loop/main.co
In order to abort the loop early or to skip the rest of the current loop iteration, the keywords break and continue can be used, respectively:
Finish or abort a flow (return/abort)
Flows can be finished or failed at any point from within the flow using the keywords return and abort, respectively:
Additionally, return takes an optional value such that you can use a flow like a common function:
If you do not provide a return value, None is passed by default.
When assigning the return value of a flow to a variable await is not optional before the flow name.
No-op operation (pass)
Sometimes, it is useful to have a no-operation keyword pass, for example as a placeholder to make the syntax valid: