-
Notifications
You must be signed in to change notification settings - Fork 1
/
const.mdtlbl
128 lines (104 loc) · 3.35 KB
/
const.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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#* 内联常量
* 这是通过 const Var = Value 来定义
* 当使用Value时将会进行一个内联常量查找
* 而内联常量是块定义的, 也就是仅在当前块内有效, 确切地说是当前的DExp
* 内联常量的值是一个Value, 也就是说你可以往里面塞一个DExp, 这可以有效的提高代码复用
* Value有一个特殊的值 `$`, 这个值为包裹这个Value的DExp的返回句柄
* 例如 `(x: read $ cell1 0;)`, 其中的`$`代表了这个DExp的返回句柄`x`
*
* 需要注意, DExp定义返回句柄的位置是会尝试对定义的Var进行追溯的, 并且只允许Var
*#
const N = 2;
const F = (read $ cell1 0;);
print "N: ";
print N;
print "F: ";
print F;
#* 以上代码会被编译为:
print "N: "
print 2
print "F: "
read __0 cell1 0
print __0
*#
# 由这里可以看出, 常量N的数字2被内联了, 常量F的DExp也被内联了
# 而$被替换为了这个DExp的返回句柄, 这经常用于常量、宏这种不知道返回句柄时
print X;
const X = 2;
print X;
const X = 3;
print X;
{
const X = 4;
print X;
}
print X;
#* 以上代码会被编译为
print X
print 2
print 3
print 4
print 3
*#
# 可以看到, 常量声明前使用并不会生效
# 常量声明后使用才会生效
# 并且这个常量是在块作用域的, 确切地说是`Expand`, 当你查看AST时可以看到它
# 且在同一个块中可以再次声明覆盖之前声明的常量
const FOO = (
print "传入值为: " ARG0 "\n";
op $ ARG0 + 1;
);
{
const ARG0 = 2;
take RES = FOO;
print "返回值为: " RES;
}
#* 以上代码会被编译为:
print "传入值为: "
print 2
print "\n"
op add __0 2 1
print "返回值为: "
print __0
*#
# 可以看到, 我们使用const与DExp可以完成内联函数这样的操作,
# 这会使代码复用性与组织性上升
# 在0.6.0版本改变了const的作用方式
const A = 1;
const B = A;
const A = 2;
print B;
#* 以上代码会被编译为
print 1
*#
# 如果在之前的版本它会被编译为`print 2`, 这显然不是我们所预期的
# 在之前是普通的const, 然后在使用时进行递归追值
# 而现在版本则是在const时如果是const就把值拿过来, 如果不是则与以前行为相同
# 然后使用时只进行一次追值
# 这样可以避免我们定义常量为另一个常量后再去追值时, 另一个常量已被覆盖或者遮蔽
# 我们可以完成如传入一个函数的操作
const DoOp = (
# 此处先将接受到的参数进行const
# 不然在take时, 根据take的原理会先将传入的覆盖到_0 _1这些 然后再去求后方的
# 如果我们不const, 那么我们开始求值_0 _1等时, 这些已经是被我们传入参数覆盖后的了
const Func = _0;
const a = _1;
const b = _2;
take[a b] RES = Func;
$ = RES;
);
const Add = (
op $ _0 + _1;
);
take[Add 1 2] RES = DoOp;
print RES;
#* 以上代码会被编译为
op add __1 1 2
set __0 __1
print __0
*#
# 我们可以看到, 我们传入的Add成功起效, 这可以提供更高的代码复用与抽象
# 但是, 我们还可以看到, 我们经过了一次无操作赋值, 这是`$ = RES`带来的
# 我们需要进行一个set将值返回出去, 目前还没有解决方法, 后续或许有办法
# 例如将返回句柄映射到RES而不是我们去对返回句柄赋值RES
# __这个问题在`v0.7.2`已经解决了, 请见`setres.mdtlbl`__