From e174b473428fa038cb3c1b9fae3c0a4038654602 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Thu, 23 Jan 2025 17:26:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=B8=80=E4=B8=8B=E6=95=99?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/learn.md | 82 +++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/examples/learn.md b/examples/learn.md index 4b372b8..119a1b2 100644 --- a/examples/learn.md +++ b/examples/learn.md @@ -57,8 +57,9 @@ Var 指的是逻辑语言中一切的 logic-value 逻辑值, > [!IMPORTANT] > 需要注意的是, 以上的逻辑变量并不完全在 Bang 适用, 比如 `a-b` 和 `let's`, -> 逻辑变量过于自由, 除了某几个符号无法使用, 剩下的符号都可以拼在一起组成变量, -> 如果 Bang 也完全使用将会很不方便, 所以 Bang 对逻辑变量的形式做了缩减, +> 逻辑变量过于自由, 除了某几个符号无法使用, 剩下的符号都可以拼在一起组成变量 +> +> 如果 Bang 也完全使用逻辑格式将会很不方便, 所以 Bang 对逻辑变量的形式做了缩减, > 依照常见编程语言的形式使用 unicode-xid, 所以可以支持许多中文变量名 > > 由一个 (xid-start 或下划线) 和若干个 xid-continue 组成一个普通的变量, @@ -94,6 +95,8 @@ set b let's > [!WARNING] > 注意不要使用一些特殊的符号, 虽然 Bang 支持但是逻辑里面有其它含义的符号, +> 但是编译到逻辑时逻辑就解析不了了 +> > 例如`#`在逻辑语言里面也是注释, `;`在逻辑语言里面也用于分隔语句 @@ -172,8 +175,9 @@ ReprVar (原始量) ValueBind (值绑定) ------------------------------------------------------------------------------- 用于将一个量绑定到一个值的求值结果上, 也就是这两个量, -并生成对另一个量的唯一对应关系, 只要绑定和被绑定的量在两次使用中一致, -那得到的绑定结果也会一致(仅单次编译中) +并生成对另一个量的唯一对应关系 + +只要绑定和被绑定的量在两次使用中一致, 那得到的绑定结果也会一致(仅单次编译中) 例如: ``` @@ -237,7 +241,7 @@ set 无法到达 3 `else` 表示"否则", 如果上述条件不成立则执行`else`的代码 -`elif` 是`else if`的类似物, 以前有必要现在只是写着方便 +`elif` 是`else if`的类似物, 虽然结构上有些不同, 以前有必要现在只是写着方便 ``` if a < b { @@ -571,7 +575,7 @@ case 4: > CmpDeps, 可以在比较某个条件前展开某些代码, > 和 DExp 有类似作用, 不过它的优先级是溢出的, 在许多地方需要加上括号使用 > -> `!` 运算并不实际存在, 它使用德摩根变换来反转内部条件, 直到反转到基本条件以结束 +> `!` 运算并不实际存在, 它使用德摩根变换来反转内部条件, 直到反转到简单条件后结束 简单语句 @@ -644,7 +648,7 @@ i, x = 2, abs(a-b) + sqrt(a)*2; } ``` -同时也提供三元运算等, 详见[op-expr](./op_expr.mdtlbl) +同时也提供三元运算等, 详见 [op-expr](./op_expr.mdtlbl) 关于注释 @@ -659,6 +663,7 @@ Bang 的注释基于逻辑语言进行扩展, 但是还添加了一种新的形 set a 不是注释; #* 这是一个多行注释 多行注释中 +* 多行注释中 *# set b 不是注释; set c 不是注释; ``` @@ -700,7 +705,7 @@ print 2 可以理解为, 直接将作用域内, 被 const 的值直接粘贴过来了, 但是别忽略那*一些额外的操作*, 当然现在可以先不管 -而同一个 Expand 中重复的对一个量进行 const 的话, 那么旧的将会被覆盖, 例如: +同一个 Expand 中重复的对一个量进行 const 的话, 那么旧的将会被覆盖, 例如: ``` const A = 2; const A = 3; @@ -711,10 +716,15 @@ print A; print 3 ``` -而如果是在子 Expand 中进行 const 的话, 那么在子 Expand 的范围内, -外部 const 的值将被遮蔽(shadow), 总是获取最内层里层的 const 值, + +遮蔽 (shadow) +------------------------------------------------------------------------------- +如果是在子 Expand 中进行 const 的话, 那么在子 Expand 的范围内, +外部 const 的值将被遮蔽(shadow) + +不管是求值还是追溯, 总是获取最内层里层的 const 值, 而内层 Expand 结束后, 外层 Expand 中 const 的值并没有改变, -只是在里层被遮住了, 这需要注意 +只是被里层的同名量遮住了 ``` const A = 2; @@ -790,7 +800,7 @@ print 2 - ValueBindRef (`->Name`): 和值绑定求值行为相同 - ClosuredValue: 正常的展开内部值, 但是会先设置闭包捕获的环境, 详见 [ClosuredValue (闭包值)](#ClosuredValue-闭包值) -- Cmper: 编译错误, 退出编译, 详见[条件依赖和条件内联](#条件依赖和条件内联) +- Cmper: 编译错误, 退出编译, 详见 [条件依赖和条件内联](#条件依赖和条件内联) 值绑定 (ValueBind) @@ -847,7 +857,8 @@ printflush message1 3. 常量表的绑定者: 常量表并不止被 const 的值, 还包含其它信息, 在后面有详细介绍 -可以看到仅一个 const, 就可以把 X Y Print 的映射关系都传递到了 FooVec +可以看到仅一个 const, 就可以把 X Y Print 的映射关系都传递到了 FooVec, +毕竟求值后都是同一个量 > [!TIP] @@ -887,7 +898,7 @@ print 2 --- -而我们有时需要句柄, 但是并不想立即使用, 或者在多处使用只想求值一次的情况, +我们有时需要句柄, 但是并不想立即使用, 或者在多处使用只想求值一次的情况, 我们可以使用 take 的另一种形式 ``` @@ -939,7 +950,7 @@ const Foo = ( ``` 可以从这种形式 const 后面的注释中看到有哪些标签 -而对绑定者来说, 如果你 const 的值本身追溯的目标就有绑定者, +对绑定者来说, 如果你 const 的值本身追溯的目标就有绑定者, 那么这个绑定者将采用追溯目标的, 否则如果你的 const 绑定到的是一个值绑定, 那么绑定者将会使用值绑定被绑定值的句柄 @@ -1000,6 +1011,7 @@ op mul foo 6 6 DExp 必备 - 设置返回句柄 (setres) ------------------------------------------------------------------------------- setres: 用来设置此语句所在的 DExp 的返回句柄, 例如: + ``` print (a: set $ 2; setres b;); # 请不要这么做 ``` @@ -1011,7 +1023,8 @@ print b > [!WARNING] > 以上代码在设置句柄前使用了返回句柄, -> 但是却在使用这个返回句柄后改变了返回句柄, +> 但是却在使用这个返回句柄后改变了返回句柄 +> > 通常我们是希望返回我们使用的返回句柄的, > 所以使用 setres 的时候要注意在使用处之前是否有用到返回, > 不然可能会悄悄的让之前希望使用的句柄作废 @@ -1145,8 +1158,9 @@ print ")" > [!NOTE] > 无论是老版本还是现版本, 设置参数或者`_0` `_1`这些时, -> 都不会像直接编写 const 语句那样收集标签, -> 所以对于要传入被重复展开的地方时, 需要使用 Consted-DExp, +> 都不会像直接编写 const 语句那样收集标签 +> +> 所以对于要传入被重复展开的地方时, 建议使用 Consted-DExp, > 在之后的[常用语法糖](#常用语法糖)会讲 @@ -1206,7 +1220,7 @@ match 里面由零至多个匹配后面跟上一个花括号组成, 称作一个 重复块 ---- +------------------------------------------------------------------------------- 重复块可以针对每n个参数, 顺序经过并设置参数(不会设置`_0` `_1`)这类, 例如: ``` @@ -1324,12 +1338,19 @@ x min= 1; ``` ``` -{ { take ___0 = x; ___0 = min(___0, 1); } { take ___1 = y; ___1 = min(___1, 2); } } +{ + { take ___0 = x; ___0 = min(___0, 1); } + { take ___1 = y; ___1 = min(___1, 2); } +} x, y min= 1, 2; ``` ``` -{ take ___0 = 1; { take ___1 = x; ___1 = min(___1, ___0); } { take ___2 = y; ___2 = min(___2, ___0); } } +{ + take ___0 = 1; + { take ___1 = x; ___1 = min(___1, ___0); } + { take ___2 = y; ___2 = min(___2, ___0); } +} x, y min= 1; ``` @@ -1427,7 +1448,12 @@ print (*++a); ## Multi print ``` -inline { print 1; print 2; inline@{ `'print'` @; } print 3; } # 使用'print'避开关键字 +inline { + `'print'` 1; + `'print'` 2; + inline@{ `'print'` @; } + `'print'` 3; +} # 使用'print'避开关键字 print 1 2 @ 3; ``` @@ -1476,7 +1502,7 @@ const C = goto(=>[a b] _0 < _1); ## Packed DExp like 一些 DExp 在语法上不能被直接使用, 需要使用包裹语法`(%)` -这算是语法设计的妥协, 也可以提醒大 DExp 后面可能接着其它东西 +这算是语法设计的妥协, 也可以提醒过长的 DExp 后面可能接着其它东西 ``` print ().x; # syntax error @@ -1491,8 +1517,8 @@ print (%v: $.x = 2;%).x; 各种高级的值 =============================================================================== -- 比较者 (Cmper): 用于条件内联, 详见[条件依赖和条件内联](#条件依赖和条件内联) -- 闭包值 (ClosuredValue): 用于追溯时捕获环境, 详见[ClosuredValue (闭包值)](#ClosuredValue-闭包值) +- 比较者 (Cmper): 用于条件内联, 详见 [条件依赖和条件内联](#条件依赖和条件内联) +- 闭包值 (ClosuredValue): 用于追溯时捕获环境, 详见 [ClosuredValue (闭包值)](#ClosuredValue-闭包值) ClosuredValue (闭包值) @@ -1513,7 +1539,7 @@ ClosuredValue (闭包值) 给句柄上相对应的绑定进行 take 或 const 就行了 > [!TIP] -> 对于求值捕获和追溯捕获, 当名称相同时可以简写, +> 对于求值捕获和追溯捕获, 当名称相同时可以简写, 算是一个语法糖 > - `A:A` -> `A` > - `&A:A` -> `&A` @@ -1619,6 +1645,7 @@ __0_const_Builder_x: =============================================================================== 一些语句有一些实用的扩展用法, 在这章进行简单介绍 + 关于有序整数分支结构的穿透 (select switch) ------------------------------------------------------------------------------- 这些结构中, 有一个很好用的操作, 可以让某个 case 执行完接着执行另一个 case @@ -1643,8 +1670,9 @@ print 2 ``` 从结果很容易看出, 当`n`为`0`时, 会打印 `01`, 这执行了多个 case, 也就是所谓的穿透 + --- -而对于 switch, 它将代码简单的编译为 select, 这会导致一个问题, +对于 switch, 它将代码简单的编译为 select, 这会导致一个问题, 也就是想在 switch 中应用穿透时, 是按大小顺序穿透的, 例如: ```