# 逻辑操作符

逻辑操作符（Logical Operators）用于连接或操作布尔值（true/false）并执行条件判断。

在需要执行判断的条件上下文（逻辑操作符、逻辑等式/不等式、条件判断语句）中非布尔类型的值默认会被隐式转换为"Truthy"（真值）或 "Falsy"（假值）。
在 aardio 中 null、0、false 为 `假值（Falsy）`， 非 false　非 null 非 0 的其为`真值（Truthy ）`。
空字符串 `""`、空表 `{}`、空数组 `[]` 在 aardio 中都是`真值（Truthy ）`。

## 一. 逻辑操作符

1. 逻辑非 <a id="not" href="#not">&#x23;</a>

    逻辑非运算符首先取得操作数的布尔值( boolean )，然后取反比较。如要操作数为 true 则返回 false,如果操作数为 false 则返回 true.也就是反过来取值的意思。  

    | 运算符 | 说明 |
    | --- | --- |
    | `!` | 逻辑非 |
    | not | 逻辑非 |

    在 aardio 中逻辑操作符有 `!` 与 `not` 两种，作用相同。

    使用 `!!x` 可将任意值 `x` 转换为布尔值。

2. 逻辑或 <a id="or" href="#or">&#x23;</a>

    逻辑或要求两个操作数其中之一为真( true ),如果第一个操作数为真则直接返回第一个操作数，否则返回第二个操作数。表达式会直接返回操作数的原值（不是转换为逻辑值的true或false）

    | 运算符 | 说明 |
    | --- | --- |
    | &#x7c;&#x7c; | 逻辑或 |
    | `or` | 逻辑或 |
    | `:` | 逻辑或，注意当  `:`  号作为用作表构造器中的键值对分隔符时不表示逻辑或。 |

    `||` 与 `or` 是完全等价的，优先级也相同。而 `:` 的优先级略低。 

    [条件赋值语句](#conditional-assignment) `a := b` 等价于 `a = a : b`，可用于常量赋值语句避免重复赋真值，例如 `::User32 := raw.loadDll("user32.dll");`。

    > 注意: 在构造表或纯数组时， `:` 在标识符、字符串字面量、数值字面量表示的键后面可作为健值分隔符使用。例如： `[123:"稀疏数组成员",1,2,3]` 

3. 逻辑与 <a id="and" href="#and">&#x23;</a>

    逻辑与要求两个操作数取布尔值后都为true,如果第一个操作数为真则返回第二个操作数，如果第一个操作数为假则返回第一个操作数(注意返回的是操作数原值，而不是转换后的布尔值)。  

    | 运算符 | 说明 |
    | --- | --- |
    | `&&` | 逻辑与 |
    | `and` | 逻辑与 |
    | `?` | 逻辑与 |

    `&&` 与 `and` 是完全等价的，优先级也相同。而 `?` 的优先级略低。 

## 二. 惰性求值 / 短路取值 <a id="short-cut-evaluation" href="#short-cut-evaluation">&#x23;</a>

逻辑与、逻辑或运算符支持惰性求值（Short-circuit Evaluation to Operand），
当取得第一个操作数的值并满足条件时，即不再计算第二个表达式的值。

示例：

```aardio
import console; 

a = true || console.log("偷懒成功,第一个操作数已经能确定返回值了") 
a = false && console.log("偷懒成功,第一个操作数已经能确定返回值了") 
a = true && console.log("偷懒失败,第一个操作数不能确定返回值") 

console.pause();
```

## 三. 原值返回 <a id="value-returning" href="#value-returning">&#x23;</a>

aardio 中逻辑或、逻辑运算符返回的不是转换后的布尔值，而是操作的原值（Value-returning）。
利用此特性，可以有条件的取得操作数的值。  

```aardio
import console; 

console.log( true ? 123 ) //显示123
console.log( false ? 123 ) //显示false
console.log( 0 : 123 ) //显示123
console.log( 1 : 123 ) //显示1 

console.log( false ? 2 : 3 ) //显示3
console.log( true ? 2 : 3 ) //显示2 
console.log( true ? false : 3 ) //显示3
console.log( true && false || 3 ) //同上

console.pause();
```  

## 四. 假值合并操作符

aardio 中的假值合并操作符（Falsy Coalescing Operator）通常是指 `:` 操作符。
由于低优先级的`逻辑或`操作符  `:` 具有的短路取值、原值返回等特性，常被 aardio 代码用于`假值合并`目的。
例如 `a : b` 在 a 为  `假值（Falsy）` 时返回 b ，否则返回 a 。

aardio 中的`Falsy`（假值）极为严格，只能是 false/null/0 之一。
false/null 通常用于表示无效返回，而 0 通常用于表示无效索引（aardio 有效起始索引为 1 ）。
而 空字符串 `""`、空表 `{}`、空数组 `[]` 在 aardio 中都是`真值（Truthy ）`。

aardio 中没有空值合并操作符（Nullish Coalescing Operator）。
aardio 将 `??` 或 `?:` 操作符视为笔误并自动转换为  `:` 操作符。

当不希望返回 false/null/0 时，使用 `:` 操作符就非常合适。
如果你希望仅排除 null ，在 aardio 应使用 if ... else 语句。

## 五. 伪三元操作符 <a id="pseudo-ternary" href="#pseudo-ternary">&#x23;</a>

aardio 的 `?` 与 `:` 都是逻辑操作符。
`a ? b : c` 的行为类似于其他语言中相同写法的三元操作符。

但 aardio 的 `a ? b : c` 的本质是`渴求真值`的逻辑运算，
当 b 为  `假值（Falsy）` 时总是返回 c ，这就是所谓假值陷阱（The Falsy Trap）。

但 aardio 的 `假值（Falsy）` 严格限制为 false/null/0 之一，
如果你希望尽可能排除  `假值（Falsy）` 那么这就不是假值隐进，可是可靠地二次兜底。

## 六. 条件赋值 <a id="conditional-assignment" href="#conditional-assignment">&#x23;</a>

逻辑或、逻辑与操作符可以用于赋值语句，进行有条件赋值。  

示例：

```aardio
a = a : 123;//如果a为false、null、0时赋值为123
a := 123; //等价于上面的语句，通常用于常量赋值，以避免重复赋值。
```  

`a := b` 是复合赋值语句，等价于 `a = a : b` ，也就相当于 `a = a or b`。  

示例：

```aardio
import console; 
str = "abcdefg"
str ?= string.left(str,3); //如果str为null，则不赋值，以避免string.left抛出错误
console.log( str )
```
  
`a ?= b(a)` 等价于 `a = a ? b(a)` ，也就相当于 `a = a and b(a)`。这样就实现了如果 `a` 为真则会调用 `b(a)`。

对于代码 `string.left(str,3)` ，如果 str 为 null 就会出错。使用 `str ?= string.left(str,3)` 就可以实现只有 str 为真（ 自然也就不可能是 null 值了 ）才会执行这句代码。
