.. _expressions: =========== 表达式 =========== .. index:: single: Expressions ---------------- 赋值 ---------------- .. index:: single: assignment(=) single: move(<-) single: clone(:=) :: exp := exp '=' exp exp := exp '<-' exp exp := exp ':=' exp Daslang 实现 3 种赋值:复制赋值 (=):: a = 10 复制赋值等同于 C++ memcpy操作:: template __forceinline void das_copy ( TT & a, const QQ b ) { static_assert(sizeof(TT)<=sizeof(QQ),"can't copy from smaller type"); memcpy(&a, &b, sizeof(TT)); } “移动” 分配:: var b = new Foo var a: Foo? a <- b 移动分配使源 (b) 无效。 它的主要目的是正确移动所有权,并在您不需要繁重类型(例如数组、表)的 source 时优化复制。 某些外部处理类型可以是不可分配的,但仍然可以移动。 移动赋值等同于 C++ memcpy + memset操作:: template __forceinline void das_move ( TT & a, const QQ & b ) { static_assert(sizeof(TT)<=sizeof(QQ),"can't move from smaller type"); memcpy(&a, &b, sizeof(TT)); memset((TT *)&b, 0, sizeof(TT)); } "克隆" 分配:: a := b 克隆分配是调用 clone(var a: auto&; b: auto&) (如果存在)或 POD 类型的基本分配的语法糖。 它还为 das_string、数组和表类型实现,并创建一个 'deep' 副本。 某些外部处理类型可以是不可分配的,但仍然可以克隆 (参阅 :ref:`Clone `). ---------------- 运算符 ---------------- .. index:: single: Operators ^^^^^^^^^^^^^^^^^^^ \.\. 运算符 ^^^^^^^^^^^^^^^^^^^ .. index:: single: \.\. Operator; Operators :: expr1 \.\. expr2 这相当于 `interval(expr1,expr2)`。默认情况下, `interval(a,b:int)` 被实现为 `range(a,b)`,而 `interval(a,b:uint)` 被实现为 `urange(a,b)`。用户可以定义自己的区间函数或泛型。 ^^^^^^^^^^^^^ ?: 运算符 ^^^^^^^^^^^^^ .. index:: pair: ?: Operator; Operators :: exp := exp_cond '?' exp1 ':' exp2 这将根据表达式的结果有条件地计算表达式。 如果 expr_cond 为 true,则仅评估 exp1。同样,如果为 false,则只有 exp2. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ?? Null 合并运算符 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: pair: ?? Operator; Operators :: exp := exp1 '??' exp2 根据 exp1 的结果有条件地评估 exp2。 给定的代码等效于: :: exp := (exp1 '!=' null) '?' *exp1 ':' exp2 它计算表达式,直到第一个非 null 值(就像第一个 'true' 值的 |运算符一样)。 运算符优先级也遵循 C# 设计,因此 ?? 的优先级低于 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ?. 和 ?[ - Null 传播运算符 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: pair: ?. Operator; Operators :: exp := value '?.' key 如果值不为 null,则取消引用 struct 的字段 'key',否则返回 null。 :: struct TestObjectFooNative { fooData : int } struct TestObjectBarNative { fooPtr: TestObjectFooNative? barData: float } def test { var a: TestObjectFooNative? var b: TestObjectBarNative? var idummy: int var fdummy: float a?.fooData ?? idummy = 1 // 将返回对 idummy 的引用,因为 a 为 null assert(idummy == 1) a = new TestObjectFooNative a?.fooData ?? idummy = 2 // 将返回对 a.fooData 的引用,因为 a 现在不为 null assert(a.fooData == 2 & idummy == 1) b = new TestObjectBarNative b?.fooPtr?.fooData ?? idummy = 3 // 将返回对 idummy 的引用,因为 B 不是 null,而是 b。barData 仍为 null assert(idummy == 3) b.fooPtr <- a b?.fooPtr?.fooData ?? idummy = 4 // 将返回对 b.fooPtr.fooData 的引用 assert(b.fooPtr.fooData == 4 & idummy == 3) } 此外,索引 ?[ 可与表格一起使用:: var tab <- { "one"=>1, "two"=> 2 } let i = tab?["three"] ?? 3 print("i = {i}\n") 它检查容器指针和密钥的可用性。 ^^^^^^^^^^^^^ 算术 ^^^^^^^^^^^^^ .. index:: pair: Arithmetic Operators; Operators :: exp:= 'exp' op 'exp' Daslang 支持标准算术运算符 ``+, -, *, / and %``。 它还支持紧凑运算符 ``+=, -=, *=, /=, %=`` 以及递增和递减运算符 ``++ and --``:: a += 2 // 与写入相同 a = a + 2 x++ // 与写入相同 x = x + 1 所有运算符都是为数值和向量类型定义的,即 (u)int* 和 float* 和 double。 ^^^^^^^^^^^^^ 关系 ^^^^^^^^^^^^^ .. index:: pair: Relational Operators; Operators :: exp:= 'exp' op 'exp' Daslang 中的关系运算符是: ``==, <, <=, >, >=, !=``. 如果表达式为 false,则这些运算符返回 true,如果表达式为 true,则返回与 true 不同的值。 ^^^^^^^^^^^^^^ 逻辑 ^^^^^^^^^^^^^^ .. index:: pair: Logical operators; Operators :: exp := exp op exp exp := '!' exp Daslang 中的逻辑运算符是 : ``&&, ||, ^^, !, &&=, ||=, ^^=``. 运算符 ``&&`` (逻辑 and) 如果其第一个参数为 false,则返回 false,否则返回其第二个参数。 运算符 ``||`` (逻辑 OR) 如果不同于 false,则返回其第一个参数,否则返回第二个参数。 如果参数不同,则运算符 ``^^`` (逻辑异 or) 返回 true,否则返回 false。 理解&&和||不一定会“评估”他们的所有参数。 与它们的 C++ 等效项不同,&&= 和 ||= 也将取消右侧的评估。 "!"(否定)运算符如果给定值为 true,则返回 false,否则返回 false。 ^^^^^^^^^^^^^^^^^^^ 按位运算符 ^^^^^^^^^^^^^^^^^^^ .. index:: pair: Bitwise Operators; Operators :: exp:= 'exp' op 'exp' exp := '~' exp Daslang 支持标准的类 C 位运算符 ``&, |, ^, ~, <<, >>, <<<, >>>``。 这些运算符仅适用于整数值。 ^^^^^^^^^^^^^^^^^^^ 管道作器 ^^^^^^^^^^^^^^^^^^^ .. index:: pair: Pipe Operators; Operators :: exp:= 'exp' |> 'exp' exp:= 'exp' <| 'exp' Daslang 支持 pipe 运算符。管道运算符类似于 'call' 表达式,其中另一个表达式是第一个参数。 :: def addX(a, b) { assert(b == 2 || b == 3) return a + b } def test { let t = 12 |> addX(2) |> addX(3) assert(t == 17) return true } :: def addOne(a) { return a + 1 } def test { let t = addOne() <| 2 assert(t == 3) } ``lpipe`` 宏允许管道连接到上一行:: require daslib/lpipe def main { print() lpipe() <| "this is string constant" } 在上面的示例中,字符串 constant 将通过管道传输到上一行的 print 表达式。 这允许管道多个块,同时仍然使用重要的空格语法。 ^^^^^^^^^^^^^^^^^^^^^ 运算符优先级 ^^^^^^^^^^^^^^^^^^^^^ .. index:: pair: Operators Precedence; Operators +--------------------------------------------------------------------------+-----------+ | ``post++ post-- . -> ?. ?[ *(deref)`` | 最高 | +--------------------------------------------------------------------------+-----------+ | ``|> <|`` | | +--------------------------------------------------------------------------+-----------+ | ``is as`` | | +--------------------------------------------------------------------------+-----------+ | ``- + ~ ! ++ --`` | | +--------------------------------------------------------------------------+-----------+ | ``??`` | | +--------------------------------------------------------------------------+-----------+ | ``/ * %`` | | +--------------------------------------------------------------------------+-----------+ | ``+ -`` | | +--------------------------------------------------------------------------+-----------+ | ``<< >> <<< >>>`` | | +--------------------------------------------------------------------------+-----------+ | ``< <= > >=`` | | +--------------------------------------------------------------------------+-----------+ | ``== !=`` | | +--------------------------------------------------------------------------+-----------+ | ``&`` | | +--------------------------------------------------------------------------+-----------+ | ``^`` | | +--------------------------------------------------------------------------+-----------+ | ``|`` | | +--------------------------------------------------------------------------+-----------+ | ``&&`` | | +--------------------------------------------------------------------------+-----------+ | ``^^`` | | +--------------------------------------------------------------------------+-----------+ | ``||`` | | +--------------------------------------------------------------------------+-----------+ | ``? :`` | | +--------------------------------------------------------------------------+-----------+ | ``+= = -= /= *= %= &= |= ^= <<= >>= <- <<<= >>>= &&= ||= ^^=``| ... | +--------------------------------------------------------------------------+-----------+ | ``=>`` | | +--------------------------------------------------------------------------+-----------+ | ``',' comma`` | 最低 | +--------------------------------------------------------------------------+-----------+ .. _array_contructor: ----------------- 数组初始化器 ----------------- .. index:: single: Fixed Array Initializer :: exp := fixed_array '(' [explist] ')' exp := fixed_array '<' type '>' '(' [explist] ')' 创建新的固定大小数组:: let a = fixed_array(1, 2) // 创建包含两个元素的数组 var a = fixed_array(1,2) // 完全根据推断自己的类型创建 .. index:: single: Dynamic Array Initializer :: exp := array '(' [explist] ')' exp := array '<' type '>' '(' [explist] ')' exp := '[' [explist] ']' 例如:: let a <- [1,2,3] // 创建并初始化推断类型 (int) 的数组 let a <- array(1,2,3) // 与上一行相同 let a <- array(1,2,3) // 相同,但显式键入 let q <- [for x in range(0, 10); x * x] // 初始化数组的推导式 (参阅 :ref:`Arrays `, :ref:`Comprehensions `). .. _struct_contructor: ------------------------------------------- Struct、Class 和 Handled 类型初始值设定项 ------------------------------------------- .. index:: single: Struct, Class, and Handled type Initializer :: struct Foo { x: int = 1 y: int = 2 } let fExplicit = Foo(x = 13, y = 11) // x = 13, y = 11 let fPartial = Foo(x = 13) // x = 13, y = 2 let fComplete = Foo(uninitialized x = 13) // x = 13, y = 2 with 'construct' syntax let aArray <- array struct((x=11,y=22),(x=33),(y=44)) // 具有 'construct' 语法的 Foo 的动态数组 类和Handled的(外部)类型也可以使用结构初始化语法进行初始化。类和处理类型不能取消初始化。 (参阅 :ref:`Structs `, :ref:`Classes `, :ref:`Handles ` ). .. _tuple_contructor: ----------------- 元组初始化器 ----------------- .. index:: single: Tuple Initializer 创建新元组:: let a = tuple(a=1, b=2.0, c="3") // 创建具有命名字段的类型化元组 let b = tuple(1, 2.0, "3") // 推断元组类型 let c = (1, 2.0, "3") // 创建推断类型的元组 (参阅 :ref:`Tuples `). ------------------- 变体初始化器 ------------------- .. index:: single: Variant Initializer 变体是使用类似于结构体的语法创建的:: variant Foo { i : int f : float } let x = Foo(i = 3) let y = Foo(f = 4.0) let a = array variant(i=3, f=4.0) // 无名数组 Variant 是一种弱类型,因此也可以声明为 alias:: typedef Foo = variant // 与 structure-like 声明相同 (参阅 :ref:`Variants `). ----------------- 表初始化器 ----------------- .. index:: single: Table Initializer 通过指定 key => 值对(以冒号分隔)来创建表:: var a <- { 1=>"one", 2=>"two" } var a <- { 1=>"one", 2=>2 } // 错误、类型不匹配 (参阅 :ref:`Tables `).