使用变量和表达式#

介绍#

与 Python 类似,Colang 支持以下基本数据类型:stringintfloatboollistsetdict,以及 Colang 特定的事件、动作和流引用。我们已经了解了如何使用 ... as $ref 表示法将事件、动作和流引用分配给变量。这里的 $ref 也只是一个变量。为了在流名称中启用空格字符,Colang 变量必须始终以 $ 字符开头,并且自身不能包含空格字符。

重要提示

变量命名约定

  • 必须以字母字符开头

  • 可以包含字母数字字符,包括 _

  • 区分大小写

Regular expression: \$[^\W\d]\w*

Colang 中的变量行为与 Python 完全相同。因此,对于新的变量赋值,不会复制像列表这样的可变数据类型,而只会通过新变量引用。

variables/assignment/main.co#
flow main
    $value = "Hi"
    $value_copy = $value # Copy of the value
    await UtteranceBotAction(script=$value_copy)
    match AnEvent()

请注意,Colang 引用也是可变的,因此指向相同的底层对象

variables/references/main.co#
flow main
    match UtteranceUserAction.Finished() as $ref
    $ref_copy = $ref # Both references are pointing to same event object
    await UtteranceBotAction(script=$ref_copy.final_transcript)
    match AnEvent()

目前,不支持创建其他变量的引用。引用只能指向事件、动作或流对象,并且在 sendmatchstartawait 语句中使用 as 关键字创建。

重要提示

  • 变量赋值将始终在内存中创建值的副本

  • 事件、动作或流引用的副本仍然指向相同的对象

  • 流参数按值传递

以下是一些变量赋值示例

$string_value = "Hi"
$integer_value = 42
$float_value = 3.14159
$list_of_strings = ["one", "two", "three"]
$list_of_integers = [1, 2, 3, 4]
$set_of_floats = {0.1, 0.2, 0.3}
$dictionary = {"value_a":1, "value_b": 2}

表达式求值#

Colang 支持对简单和复合数据类型求值常见的 Python 表达式(请参阅 Simple Eval

# Arithmetic expressions
21 + 21
21 + 19 / 7 + (8 % 3) ** 9

# Supported operators
+, -, *, / # standard arithmetic operators
** # to the power of: 2 ** 10 -> 1024
% # modulus
==, <, >, <=, >= # comparison operators
and, or, not # logical operators
in # is something contained within something else
>>, <<, ^, |, &, ~ # Bitwise operators

# Conditional expressions
"equal" if x == y else "not equal"
"a" if 1 == 2 else "b" if 2 == 3 else "c"

# Compound data types
list_variable[0] # Access item by index
dict_variable[key] # Access item by key
object.attribute # Access object attribute

# Supported custom functions
len(obj: Any) -> int # Return number of items of a compound variable
regex(pattern: str) -> Pattern # Creates a regex pattern that can be compared to
search(pattern: str, string: str) -> bool # Check for regex pattern in string
findall(pattern: str, string: str) -> List[str] # Return all matches of regex pattern with string
uid() -> str # Create new universal unique identifier
int(string: str) -> int # Convert the number in the string to an int
float(string: str) -> float # Convert the number in the string to a float
str(x: Any) -> str # Convert x to a string
pretty_str(x: Any) -> str # Convert x to a formatted string
int(x: Any) -> int # Convert x to a int
float(x: Any) -> float # Convert x to a float
escape(string: str) -> str # Escape a string and expressions inside the string
is_bool(x: Any) -> bool # Check if x is a bool
is_int(x: Any) -> bool # Check if x is an int
is_float(x: Any) -> bool # Check if x is a float
is_str(x: Any) -> bool # Check if x is a str
is_regex(x: Any) -> bool # Check if x is a regex pattern
type(x: Any) -> str # Returns type as string of object x
list(x: Iterable[T]) -> list[T] # Converts an iterable object to a list
rand() -> float # Return a random float between 0 and 1
randint(x: int) -> int # Return a random int below x
flows_info() -> dict # Returns a dictionary that contains more information about the current flow

以下是如何在 Colang 中使用表达式

# Expression in an assignment
$dict = {"value": 2 + 3}

# Expression as standalone statement
($dict.update({"value": 4}))

# Expression as a flow parameter
bot count to ($dict["value"])
bot count to (int("3"))

您可以看到表达式如何在不同的上下文中使用,并且如果用作独立语句流参数,则需要用括号括起来。

流变量访问#

默认情况下,在流中定义的变量具有局部作用域,并且无法从流外部访问。启用访问它们的一种方法是在流定义中使用 定义流 中所示的表示法将它们声明为流属性

variables/flow_attributes/main.co#
flow main
    await user said something as $ref
    await UtteranceBotAction(script=$ref.transcript)
    match AnEvent()

flow user said something -> $transcript
    match UtteranceUserAction.Finished() as $event_ref
    $transcript = $event_ref.final_transcript

通过这种方式,我们可以例如访问用户转录,并使用它通过机器人话语动作重复它。

在流之间使用变量共享信息的另一种方法是使用关键字 global 使其成为全局变量。

variables/global_variables/main.co#
flow main
    global $transcript
    await bot said something
    await UtteranceBotAction(script=$transcript)
    match AnEvent()

flow bot said something
    global $transcript
    match UtteranceUserAction.Finished() as $event_ref
    $transcript = $event_ref.final_transcript

正如您从示例中看到的,我们需要在每个流中定义变量 $transcript 是全局的,以便访问全局实例。否则,它将是一个隐藏全局实例的局部变量。但是请三思而后行,是否要使用全局变量,因为它可能表明 Colang 设计不是最优的。

字符串中的表达式#

与 Python 的格式化字符串文字一样,我们可以使用花括号来评估字符串内的表达式 "{$variable}"

variables/string_expression_evaluation/main.co#
flow main
    $user_name = "John"
    await UtteranceBotAction(script="Hi {$user_name}!")
    match AnEvent()

如果需要在文字文本中包含花括号字符,可以通过双写来转义它:{{}}

流成员变量#

要访问流实例的成员变量,您可以使用引用或流自身内部的保留变量 $self

$ref.uid: str # The unique id of the flow instance
$ref.flow_id: str # The name of the flow
$ref.status.value: str # Name of the low state ("waiting", "starting", "started", "stopping", "stopped", "finished")
$ref.loop_id: Optional[str] # The interaction loop id of the flow
$ref.parent_uid: Optional[str] # The unique id of the parent flow instance
$ref.child_flow_uids: List[str] # All unique ids of the child flow instances
$ref.context: dict # The variable context that contains all user defined variables in the flow
$ref.priority: float # Priority of the flow (range: [0.0-1.0], default: 1.0)
$ref.arguments: dict # All arguments of the flow
$ref.flow_instance_uid: str # Flow instance specific uid
$ref.source_flow_instance_uid: str # The parent flow uid of the flow
$ref.activate: bool # True if the flow was activated and will therefore restart immediately when finished
$ref.new_instance_started: bool # True if new instance was started of an activated flow

如果您不确定自己在做什么,则不应更改这些值,因为这可能会对流的进一步执行产生副作用!

动作成员变量#

要访问动作的成员变量,您可以使用动作引用

$ref.uid: str # The unique id of the action instance
$ref.name: str # The name of the action
$ref.flow_uid: str # The flow that started the action
$ref.status.value: str # The action status ("initialized", "starting", "started", "stopping", "finished")
$ref.context: dict # Contains all the action event parameters
$ref.start_event_arguments: dict # Contains all action start arguments

事件成员变量#

要访问事件的成员变量,您可以使用事件引用

$ref.name: str # The name of the event
$ref.arguments: dict # A dictionary with all the event arguments

# Only for flow events
$ref.flow: FlowReference # A reference to the flow of the event

系统和机器人配置值#

要访问系统或机器人特定的配置变量,您可以使用 $system

$system.config # Current bot configuration object (YAML)
$system.state # The bots current runtime state object

例如,如果您在 yaml 机器人配置中定义了一个新的布尔值 streaming

streaming: True

您可以像这样访问和打印它

print $system.config.streaming

接下来,我们将学习如何使用流控制来创建分支或循环交互模式。