流控制#

流控制是所有编程语言中的基本工具,Colang 也支持它。它支持在单个流中进行分支和重复交互模式。

条件分支 (if/elif/else)#

重要提示

条件分支的语法定义

if <condition1>
    <interaction pattern sequence 1>
[elif <condition2>
    <interaction pattern sequence 2>]
.
.
.
[else
    <interaction pattern else sequence>]

条件分支是一个众所周知的概念,其工作方式与 Python 相同

control_flow_tools/conditional_branching/main.co#
flow main
    $number_of_users = 1
    if $number_of_users == 0
        await user became present
    elif $number_of_users > 1
        bot say "I am sorry, I can only interact with a single user!"
    else
        bot say "Welcome! Nice to meet you!"
    match RestartEvent()

在此示例中,机器人的反应取决于变量 $number_of_users 的状态,该变量将包含可用用户的数量。

事件分支 (when/or when/else)#

事件分支是一个新的基于 Colang 的概念,它支持基于预期事件的分支。

重要提示

基于事件的分支的语法定义

when <MixedGroup1>
    <interaction pattern sequence 1>
[or when <MixedGroup2>
    <interaction pattern sequence 2>]
.
.
.
[else
    <interaction pattern else sequence>]
  • <MixedGroup> 代表流、动作和事件的混合分组

  • when/or when 语句中的所有动作和流将并发启动

  • 如果未使用 or whenelse 语句,则 when 构造可以用 awaitmatch 语句替换

通过并发模式匹配机制,我们已经看到了一种基于用户输入设计分支交互模式的方法

control_flow_tools/concurrent_patterns/main.co#
flow main
    bot say "How are you?"
    bot react to user feeling good or bot react to user feeling bad

flow bot react to user feeling good
    user said "Good" or user said "Great"
    bot say "Great"

flow bot react to user feeling bad
    user said "Bad" or user said "Terrible"
    bot say "Sorry to hear"

根据用户的回答,我们将得到不同的机器人反应。虽然这种并发流机制非常强大,但有时最好将所有内容都放在一个流中,借助 when 构造

control_flow_tools/event_branching/main.co#
flow main
    bot say "How are you?"
    bot react to user wellbeing

flow bot react to user wellbeing
    when user said "Good" or user said "Great"
        bot say "Great"
    or when user said "Bad" or user said "Terrible"
        bot say "Sorry to hear"

可以通过添加更多 or when 语句轻松扩展案例数量。else 语句仅在所有 when/or when 语句都失败时才会触发。

从定义中我们可以看到 when/or when 语句支持混合组,其中可以包含事件、动作和流。对于事件,它的工作方式类似于 match 语句,而对于动作和流,它的行为类似于 await 语句。因此,动作和流将被启动,然后与其 Finished 事件匹配。请注意,所有流和动作将在不同的 when/or when 语句中并发启动,并在第一个案例成功后立即停止。

重要提示

一旦其中一个案例成功,所有 when/or when 语句中启动的所有流和动作都将停止。

我们还可以使用此构造轻松地为流创建分支,该流要么完成,要么失败

control_flow_tools/catch_failing_flow/main.co#
flow main
    start pattern a
    when pattern b
        bot say "Pattern b has finished"
    else
        bot say "Pattern b has failed"

flow pattern a
    user said "Hello"
    bot say "Hello"

flow pattern b
    user said something
    bot say "Hi"

由于事件生成冲突解决,“pattern b” 对于用户输入“Hello”将失败,但对于用户输入“Hi”将成功完成

> Hello

Hello

Pattern b has failed

> Hi

Hi

Pattern b has finished

当与以动作为开头的类动作流一起使用时,被认为是“糟糕的设计”

flow bot greet then comment
    when bot say "Hi there!"
        bot say "I am done talking first"
    or when bot gesture "Wave with one hand"
        bot say "I am done gesturing first"

flow bot say $text
    await UtteranceBotAction(script=$text)

flow bot gesture $gesture
    await GestureBotAction(gesture=$gesture)

此示例将无法正常工作,因为由于 UtteranceBotActionGestureBotAction 之间的动作冲突,只会启动两个动作中的一个。请注意,当遵循正确的流命名约定时,可以轻松检测到此类情况,因为 when bot say "Hi there!" 在语法上是不正确的。上面的示例需要像这样实现

flow bot greet then comment
    start bot say "Hi there!" as $action_1_ref
        and bot gesture "Wave with one hand" as $action_2_ref
    when $action_1_ref.Finished()
        bot say "I am done talking first"
    or when $action_2_ref.Finished()
        bot say "I am done gesturing first"

重要提示

when/or when/else 分支应仅与类似意图的流一起使用。

循环 (while)#

重要提示

循环的语法定义

while <condition>
    <interaction pattern sequence>

在此示例中,机器人将从一数到十

control_flow_tools/loop/main.co#
flow main
    bot count to 10

flow bot count to $number
    $current_number = 1
    while $current_number < $number
        bot say "{$current_number}"
        $current_number = $current_number + 1

为了提前中止循环或跳过当前循环迭代的其余部分,可以使用关键字 breakcontinue

flow bot count to $number
    $current_number = 0 # Initialized it with 0
    while True # Endless loop
        bot say "{$current_number}"
        $current_number = $current_number + 1
        if $current_number == 0
            continue # Skip the number 0
        if $current_number > $number
            break # Break out of loop when target number was reached

完成或中止流 (return/abort)#

可以使用关键字 returnabort 从流中的任何点完成或失败流

flow main
    user greeted then expressed feeling unwell

flow user greeted then expressed feeling unwell
    match user greeted
    when user expressed feeling unwell
        return
    or when user said something
        abort
    # We never reach this, except if both cases fail

此外,return 接受一个可选值,以便您可以像使用通用函数一样使用流

flow main
    $result = await multiply 3 4
    bot say "{$result}"

flow multiply $number_1 $number_2
    return $number_1 * $number_2

如果未提供返回值,则默认情况下会传递 None

注意

当将流的返回值分配给变量时,流名称前的 await 不是可选的。

空操作 (pass)#

有时,拥有一个空操作关键字 pass 很有用,例如,作为占位符以使语法有效

flow main
    user greeted then expressed feeling unwell

flow user greeted then expressed feeling unwell
    match user greeted
    when user expressed feeling unwell
        pass # Just continue with the flow
    or when user said something
        abort
    # The flow will successfully finish here