-
Notifications
You must be signed in to change notification settings - Fork 1
/
const_match.mdtlbl
86 lines (77 loc) · 2.72 KB
/
const_match.mdtlbl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#**
* 这是0.16.0添加的语法, 很像match, 但是在前面添加const
* 与match不同的是, 它不会先把参数take, 而是尽量针对参数本身匹配
* 它会把每个参数进行const, 然后以其const后的依据去对指向的值进行匹配
*
* 它的var-pat和match很像, 但是它本身也是惰性的, 也就是说例如
* `[A B C]` 如果A匹配上了, 那么B和C将不会被take.
* 其作用是匹配目标值为Var且其值与pat相等
*
* 它还有其它几个模式:
* 下划线通配模式: 例如 `_`, 这会允许任何值
*
* 守卫模式: 例如 `[?foo]`, 这里里面是一个 op-expr, 当然一般也用不上.
* 在这里面将会有一个独立的参数环境, 拥有一个参数指向要匹配的值
* 在匹配时会将守卫take, 得到的句柄非`0`则判定通过
*
* 值模式: 例如 `[*V]`, 它会直接将对应这个位置的被匹配值take, 然后直接对句柄匹配
* 需要注意的是, 它可能在多个分支被take多次, 只是守卫模式的一个语法糖
* 其具体原理可以使用`A`编译选项查看
*
* 同时, 它还有一个take标志, 在pat前面加上`*`时,
* 将会在整个分支通过时采用take而非const绑定,
* 例如: `*A`
*#
# 在以前, 我们经常使用手动的_0 _1来接受参数, 哪怕有了match也依旧如此
# 因为match会将每个参数take, 如果某个参数不需要立即take时,
# 就基本整个都用不了match来方便的接受参数了
# 而const-match可以很好的解决这个问题
# 比如一个简单的For
const For = (const match @ {
Start Stop F {
take For[Start Stop 1 F];
}
*Start *Stop *Step F {
take I = ();
I = Start;
while I < Stop {
take F[I];
I += Step;
}
}
});
take For[0 10 (
print "a: "_0;
)];
take For[0 10 2 (
print "b: "_0;
)];
# 在0.16.21版本, 增加了快捷的类似setres的表示方法,
# 使用上类似匹配成功后对匹配到的额外编译一次setres
const Read = (const match @ {
$*Res Addr {
read Res cell1 Addr;
}
});
# 产生的结果类似如下
const Read = (const match @ {
*Res Addr {
setres Res;
read Res cell1 Addr;
}
});
# 注意, 在捕获之后take的话, 除非真的需要,
# 否则尽量避免编写如 `$Res`, 也就是未添加`*`的情况
# 不然按以上的展开示例, 会在setres和之后使用时产生对原始值多次take,
# 这通常不是预期的
# 在0.17.7版本添加了一个方便的语法糖, 在单分支时可用减少嵌套, 例如
const match @ => N {
print "num: "N;
}
# 相当于如下代码
const match @ {
N {
print "num: "N;
}
}
# 在只有一个分支时可以减少一层括号, 用于快速接收参数等情况非常舒适