summaryrefslogtreecommitdiff
path: root/doc/yue-zh.md
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2026-02-24 00:35:05 +0800
committerLi Jin <dragon-fly@qq.com>2026-02-24 00:35:05 +0800
commit50221313c577a2e9f01a3a6b12c8e54594f13126 (patch)
treec2e45b3a7d2392d6cbb5aea9b7de4e2d35b03f69 /doc/yue-zh.md
parent52974cf6d560c123ecfcb20963e60e6caac87828 (diff)
downloadyuescript-0.33.2.tar.gz
yuescript-0.33.2.tar.bz2
yuescript-0.33.2.zip
Updated all-in-one docs.v0.33.2
Diffstat (limited to 'doc/yue-zh.md')
-rw-r--r--doc/yue-zh.md2495
1 files changed, 1 insertions, 2494 deletions
diff --git a/doc/yue-zh.md b/doc/yue-zh.md
index 93e21d8..d8b5346 100644
--- a/doc/yue-zh.md
+++ b/doc/yue-zh.md
@@ -1,11 +1,5 @@
1---
2title: 参考手册
3---
4
5# 月之脚本文档 1# 月之脚本文档
6 2
7<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;padding-bottom: 2em;"/>
8
9欢迎来到 <b>月之脚本(YueScript)</b> 官方文档!<br/> 3欢迎来到 <b>月之脚本(YueScript)</b> 官方文档!<br/>
10这里收录了语言特性、用法、参考示例和资源。<br/> 4这里收录了语言特性、用法、参考示例和资源。<br/>
11请选择左侧的章节索引或目录,开启你的月之脚本之旅 ☽ 5请选择左侧的章节索引或目录,开启你的月之脚本之旅 ☽
@@ -21,17 +15,6 @@ do
21print var -- 这里是nil 15print var -- 这里是nil
22``` 16```
23 17
24<YueDisplay>
25
26```yue
27do
28 var = "hello"
29 print var
30print var -- 这里是nil
31```
32
33</YueDisplay>
34
35&emsp;&emsp;月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。`do` 表达式支持通过 `break` 打断执行流并提前返回多个值。 18&emsp;&emsp;月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。`do` 表达式支持通过 `break` 打断执行流并提前返回多个值。
36 19
37```yuescript 20```yuescript
@@ -42,18 +25,6 @@ status, value = do
42 break "small", n 25 break "small", n
43``` 26```
44 27
45<YueDisplay>
46
47```yue
48status, value = do
49 n = 12
50 if n > 10
51 break "large", n
52 break "small", n
53```
54
55</YueDisplay>
56
57```yuescript 28```yuescript
58counter = do 29counter = do
59 i = 0 30 i = 0
@@ -65,21 +36,6 @@ print counter!
65print counter! 36print counter!
66``` 37```
67 38
68<YueDisplay>
69
70```yue
71counter = do
72 i = 0
73 ->
74 i += 1
75 i
76
77print counter!
78print counter!
79```
80
81</YueDisplay>
82
83```yuescript 39```yuescript
84tbl = { 40tbl = {
85 key: do 41 key: do
@@ -88,18 +44,6 @@ tbl = {
88} 44}
89``` 45```
90 46
91<YueDisplay>
92
93```yue
94tbl = {
95 key: do
96 print "分配键值!"
97 1234
98}
99```
100
101</YueDisplay>
102
103# 代码行修饰 47# 代码行修饰
104 48
105&emsp;&emsp;为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾: 49&emsp;&emsp;为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾:
@@ -108,28 +52,12 @@ tbl = {
108print "你好,世界" if name == "Rob" 52print "你好,世界" if name == "Rob"
109``` 53```
110 54
111<YueDisplay>
112
113```yue
114print "你好,世界" if name == "Rob"
115```
116
117</YueDisplay>
118
119&emsp;&emsp;修饰 for 循环的示例: 55&emsp;&emsp;修饰 for 循环的示例:
120 56
121```yuescript 57```yuescript
122print "项目: ", item for item in *items 58print "项目: ", item for item in *items
123``` 59```
124 60
125<YueDisplay>
126
127```yue
128print "项目: ", item for item in *items
129```
130
131</YueDisplay>
132
133&emsp;&emsp;修饰 while 循环的示例: 61&emsp;&emsp;修饰 while 循环的示例:
134 62
135```yuescript 63```yuescript
@@ -138,16 +66,6 @@ game\update! while game\isRunning!
138reader\parse_line! until reader\eof! 66reader\parse_line! until reader\eof!
139``` 67```
140 68
141<YueDisplay>
142
143```yue
144game\update! while game\isRunning!
145
146reader\parse_line! until reader\eof!
147```
148
149</YueDisplay>
150
151# 宏 69# 宏
152 70
153## 常见用法 71## 常见用法
@@ -183,39 +101,6 @@ if $and f1!, f2!, f3!
183 print "OK" 101 print "OK"
184``` 102```
185 103
186<YueDisplay>
187
188```yue
189macro PI2 = -> math.pi * 2
190area = $PI2 * 5
191
192macro HELLO = -> "'你好 世界'"
193print $HELLO
194
195macro config = (debugging) ->
196 global debugMode = debugging == "true"
197 ""
198
199macro asserts = (cond) ->
200 debugMode and "assert #{cond}" or ""
201
202macro assert = (cond) ->
203 debugMode and "assert #{cond}" or "#{cond}"
204
205$config true
206$asserts item ~= nil
207
208$config false
209value = $assert item
210
211-- 宏函数参数传递的表达式会被转换为字符串
212macro and = (...) -> "#{ table.concat {...}, ' and ' }"
213if $and f1!, f2!, f3!
214 print "OK"
215```
216
217</YueDisplay>
218
219## 直接插入代码 104## 直接插入代码
220 105
221&emsp;&emsp;宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。 106&emsp;&emsp;宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。
@@ -246,36 +131,6 @@ end
246]==] 131]==]
247``` 132```
248 133
249<YueDisplay>
250
251```yue
252macro yueFunc = (var) -> "local #{var} = ->"
253$yueFunc funcA
254funcA = -> "无法访问宏生成月之脚本里定义的变量"
255
256macro luaFunc = (var) -> {
257 code: "local function #{var}() end"
258 type: "lua"
259}
260$luaFunc funcB
261funcB = -> "无法访问宏生成 Lua 代码里定义的变量"
262
263macro lua = (code) -> {
264 :code
265 type: "lua"
266}
267
268-- raw字符串的开始和结束符号会自动被去除了再传入宏函数
269$lua[==[
270-- 插入原始Lua代码
271if cond then
272 print("输出")
273end
274]==]
275```
276
277</YueDisplay>
278
279## 导出宏 134## 导出宏
280 135
281&emsp;&emsp;宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 136&emsp;&emsp;宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
@@ -295,28 +150,6 @@ import "utils" as {
295[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ 150[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
296``` 151```
297 152
298<YueDisplay>
299
300```yue
301-- 文件: utils.yue
302export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
303export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
304export macro foreach = (items, action) -> "for _ in *#{items}
305 #{action}"
306
307-- 文件 main.yue
308-- 在浏览器中不支持import函数,请在真实环境中尝试
309--[[
310import "utils" as {
311 $, -- 表示导入所有宏的符号
312 $foreach: $each -- 重命名宏 $foreach 为 $each
313}
314[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
315]]
316```
317
318</YueDisplay>
319
320## 内置宏 153## 内置宏
321 154
322&emsp;&emsp;月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。 155&emsp;&emsp;月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。
@@ -326,15 +159,6 @@ print $FILE -- 获取当前模块名称的字符串
326print $LINE -- 获取当前代码行数:2 159print $LINE -- 获取当前代码行数:2
327``` 160```
328 161
329<YueDisplay>
330
331```yue
332print $FILE -- 获取当前模块名称的字符串
333print $LINE -- 获取当前代码行数:2
334```
335
336</YueDisplay>
337
338## 用宏生成宏 162## 用宏生成宏
339 163
340&emsp;&emsp;在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。 164&emsp;&emsp;在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。
@@ -357,28 +181,6 @@ print "有效的枚举类型:", $BodyType Static
357-- print "编译报错的枚举类型:", $BodyType Unknown 181-- print "编译报错的枚举类型:", $BodyType Unknown
358``` 182```
359 183
360<YueDisplay>
361
362```yue
363macro Enum = (...) ->
364 items = {...}
365 itemSet = {item, true for item in *items}
366 (item) ->
367 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
368 "\"#{item}\""
369
370macro BodyType = $Enum(
371 Static
372 Dynamic
373 Kinematic
374)
375
376print "有效的枚举类型:", $BodyType Static
377-- print "编译报错的枚举类型:", $BodyType Unknown
378```
379
380</YueDisplay>
381
382## 宏参数检查 184## 宏参数检查
383 185
384&emsp;&emsp;可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。 186&emsp;&emsp;可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
@@ -393,20 +195,6 @@ macro printNumAndStr = (num `Num, str `String) -> |
393$printNumAndStr 123, "hello" 195$printNumAndStr 123, "hello"
394``` 196```
395 197
396<YueDisplay>
397
398```yue
399macro printNumAndStr = (num `Num, str `String) -> |
400 print(
401 #{num}
402 #{str}
403 )
404
405$printNumAndStr 123, "hello"
406```
407
408</YueDisplay>
409
410&emsp;&emsp;如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。 198&emsp;&emsp;如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
411 199
412```yuescript 200```yuescript
@@ -418,19 +206,6 @@ macro printNumAndStr = (num, str) ->
418$printNumAndStr 123, "hello" 206$printNumAndStr 123, "hello"
419``` 207```
420 208
421<YueDisplay>
422
423```yue
424macro printNumAndStr = (num, str) ->
425 error "expected Num as first argument" unless $is_ast Num, num
426 error "expected String as second argument" unless $is_ast String, str
427 "print(#{num}, #{str})"
428
429$printNumAndStr 123, "hello"
430```
431
432</YueDisplay>
433
434&emsp;&emsp;更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。 209&emsp;&emsp;更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
435 210
436# 错误处理 211# 错误处理
@@ -465,38 +240,6 @@ catch err
465 print result 240 print result
466``` 241```
467 242
468<YueDisplay>
469
470```yue
471try
472 func 1, 2, 3
473catch err
474 print yue.traceback err
475
476success, result = try
477 func 1, 2, 3
478catch err
479 yue.traceback err
480
481try func 1, 2, 3
482catch err
483 print yue.traceback err
484
485success, result = try func 1, 2, 3
486
487try
488 print "尝试中"
489 func 1, 2, 3
490
491-- 使用if赋值模式
492if success, result := try func 1, 2, 3
493catch err
494 print yue.traceback err
495 print result
496```
497
498</YueDisplay>
499
500## 错误处理简化 243## 错误处理简化
501 244
502&emsp;&emsp;`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。 245&emsp;&emsp;`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
@@ -519,44 +262,14 @@ catch e
519 e 262 e
520``` 263```
521 264
522<YueDisplay>
523
524```yue
525a, b, c = try? func!
526
527-- 与空值合并运算符一起使用
528a = (try? func!) ?? "default"
529
530-- 作为函数参数
531f try? func!
532
533-- 带 catch 块的 try!
534f try?
535 print 123
536 func!
537catch e
538 print e
539 e
540```
541
542</YueDisplay>
543
544# 表格字面量 265# 表格字面量
545 266
546&emsp;&emsp;和 Lua 一样,表格可以通过花括号进行定义。 267&emsp;&emsp;和 Lua 一样,表格可以通过花括号进行定义。
547 268
548```yuescript 269```yuescript
549some_values = [1, 2, 3, 4] 270some_values = {1, 2, 3, 4}
550```
551
552<YueDisplay>
553
554```yue
555some_values = [1, 2, 3, 4]
556``` 271```
557 272
558</YueDisplay>
559
560&emsp;&emsp;但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。 273&emsp;&emsp;但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。
561 274
562```yuescript 275```yuescript
@@ -567,18 +280,6 @@ some_values = {
567} 280}
568``` 281```
569 282
570<YueDisplay>
571
572```yue
573some_values = {
574 name: "Bill",
575 age: 200,
576 ["favorite food"]: "rice"
577}
578```
579
580</YueDisplay>
581
582&emsp;&emsp;如果只分配一个键值对的表格,可以省略花括号。 283&emsp;&emsp;如果只分配一个键值对的表格,可以省略花括号。
583 284
584```yuescript 285```yuescript
@@ -588,17 +289,6 @@ profile =
588 favorite_foods: ["冰淇淋", "甜甜圈"] 289 favorite_foods: ["冰淇淋", "甜甜圈"]
589``` 290```
590 291
591<YueDisplay>
592
593```yue
594profile =
595 height: "4英尺",
596 shoe_size: 13,
597 favorite_foods: ["冰淇淋", "甜甜圈"]
598```
599
600</YueDisplay>
601
602&emsp;&emsp;可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值: 292&emsp;&emsp;可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值:
603 293
604```yuescript 294```yuescript
@@ -610,19 +300,6 @@ values = {
610} 300}
611``` 301```
612 302
613<YueDisplay>
614
615```yue
616values = {
617 1, 2, 3, 4
618 5, 6, 7, 8
619 name: "超人"
620 occupation: "打击犯罪"
621}
622```
623
624</YueDisplay>
625
626&emsp;&emsp;创建单行表格字面量时,也可以省略花括号: 303&emsp;&emsp;创建单行表格字面量时,也可以省略花括号:
627 304
628```yuescript 305```yuescript
@@ -631,16 +308,6 @@ my_function dance: "探戈", partner: "无"
631y = type: "狗", legs: 4, tails: 1 308y = type: "狗", legs: 4, tails: 1
632``` 309```
633 310
634<YueDisplay>
635
636```yue
637my_function dance: "探戈", partner: "无"
638
639y = type: "狗", legs: 4, tails: 1
640```
641
642</YueDisplay>
643
644&emsp;&emsp;表格字面量的键可以使用 Lua 语言的关键字,而无需转义: 311&emsp;&emsp;表格字面量的键可以使用 Lua 语言的关键字,而无需转义:
645 312
646```yuescript 313```yuescript
@@ -650,17 +317,6 @@ tbl = {
650} 317}
651``` 318```
652 319
653<YueDisplay>
654
655```yue
656tbl = {
657 do: "某事"
658 end: "饥饿"
659}
660```
661
662</YueDisplay>
663
664&emsp;&emsp;如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符: 320&emsp;&emsp;如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符:
665 321
666```yuescript 322```yuescript
@@ -671,18 +327,6 @@ person = { :hair, :height, shoe_size: 40 }
671print_table :hair, :height 327print_table :hair, :height
672``` 328```
673 329
674<YueDisplay>
675
676```yue
677hair = "金色"
678height = 200
679person = { :hair, :height, shoe_size: 40 }
680
681print_table :hair, :height
682```
683
684</YueDisplay>
685
686&emsp;&emsp;如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。 330&emsp;&emsp;如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。
687 331
688```yuescript 332```yuescript
@@ -692,17 +336,6 @@ t = {
692} 336}
693``` 337```
694 338
695<YueDisplay>
696
697```yue
698t = {
699 [1 + 2]: "你好"
700 "你好 世界": true
701}
702```
703
704</YueDisplay>
705
706&emsp;&emsp;Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。 339&emsp;&emsp;Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。
707 340
708```yuescript 341```yuescript
@@ -710,15 +343,6 @@ some_values = [ 1, 2, 3, 4 ]
710list_with_one_element = [ 1, ] 343list_with_one_element = [ 1, ]
711``` 344```
712 345
713<YueDisplay>
714
715```yue
716some_values = [ 1, 2, 3, 4 ]
717list_with_one_element = [ 1, ]
718```
719
720</YueDisplay>
721
722# 推导式 346# 推导式
723 347
724&emsp;&emsp;推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。 348&emsp;&emsp;推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。
@@ -732,43 +356,18 @@ items = [1, 2, 3, 4]
732doubled = [item * 2 for i, item in ipairs items] 356doubled = [item * 2 for i, item in ipairs items]
733``` 357```
734 358
735<YueDisplay>
736
737```yue
738items = [1, 2, 3, 4]
739doubled = [item * 2 for i, item in ipairs items]
740```
741
742</YueDisplay>
743
744&emsp;&emsp;可以使用 `when` 子句筛选新表中包含的项目: 359&emsp;&emsp;可以使用 `when` 子句筛选新表中包含的项目:
745 360
746```yuescript 361```yuescript
747slice = [item for i, item in ipairs items when i > 1 and i < 3] 362slice = [item for i, item in ipairs items when i > 1 and i < 3]
748``` 363```
749 364
750<YueDisplay>
751
752```yue
753slice = [item for i, item in ipairs items when i > 1 and i < 3]
754```
755
756</YueDisplay>
757
758&emsp;&emsp;因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为: 365&emsp;&emsp;因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为:
759 366
760```yuescript 367```yuescript
761doubled = [item * 2 for item in *items] 368doubled = [item * 2 for item in *items]
762``` 369```
763 370
764<YueDisplay>
765
766```yue
767doubled = [item * 2 for item in *items]
768```
769
770</YueDisplay>
771
772&emsp;&emsp;在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理: 371&emsp;&emsp;在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
773 372
774```yuescript 373```yuescript
@@ -780,19 +379,6 @@ flat = [...v for k,v in pairs data]
780-- flat 现在为 [1, 2, 3, 4, 5, 6] 379-- flat 现在为 [1, 2, 3, 4, 5, 6]
781``` 380```
782 381
783<YueDisplay>
784
785```yue
786data =
787 a: [1, 2, 3]
788 b: [4, 5, 6]
789
790flat = [...v for k,v in pairs data]
791-- flat 现在为 [1, 2, 3, 4, 5, 6]
792```
793
794</YueDisplay>
795
796&emsp;&emsp;for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。 382&emsp;&emsp;for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。
797 383
798&emsp;&emsp;使用多个 for 子句与使用多重循环的效果相同: 384&emsp;&emsp;使用多个 for 子句与使用多重循环的效果相同:
@@ -805,32 +391,12 @@ points = [ [x, y] for x in *x_coords \
805for y in *y_coords] 391for y in *y_coords]
806``` 392```
807 393
808<YueDisplay>
809
810```yue
811x_coords = [4, 5, 6, 7]
812y_coords = [9, 2, 3]
813
814points = [ [x, y] for x in *x_coords \
815for y in *y_coords]
816```
817
818</YueDisplay>
819
820&emsp;&emsp;在推导式中也可以使用简单的数值 for 循环: 394&emsp;&emsp;在推导式中也可以使用简单的数值 for 循环:
821 395
822```yuescript 396```yuescript
823evens = [i for i = 1, 100 when i % 2 == 0] 397evens = [i for i = 1, 100 when i % 2 == 0]
824``` 398```
825 399
826<YueDisplay>
827
828```yue
829evens = [i for i = 1, 100 when i % 2 == 0]
830```
831
832</YueDisplay>
833
834## 表格推导式 400## 表格推导式
835 401
836&emsp;&emsp;表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。 402&emsp;&emsp;表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。
@@ -847,32 +413,10 @@ thing = {
847thing_copy = {k, v for k, v in pairs thing} 413thing_copy = {k, v for k, v in pairs thing}
848``` 414```
849 415
850<YueDisplay>
851
852```yue
853thing = {
854 color: "red"
855 name: "fast"
856 width: 123
857}
858
859thing_copy = {k, v for k, v in pairs thing}
860```
861
862</YueDisplay>
863
864```yuescript 416```yuescript
865no_color = {k, v for k, v in pairs thing when k != "color"} 417no_color = {k, v for k, v in pairs thing when k != "color"}
866``` 418```
867 419
868<YueDisplay>
869
870```yue
871no_color = {k, v for k, v in pairs thing when k != "color"}
872```
873
874</YueDisplay>
875
876&emsp;&emsp;**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。 420&emsp;&emsp;**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。
877 421
878```yuescript 422```yuescript
@@ -880,15 +424,6 @@ numbers = [1, 2, 3, 4]
880sqrts = {i, math.sqrt i for i in *numbers} 424sqrts = {i, math.sqrt i for i in *numbers}
881``` 425```
882 426
883<YueDisplay>
884
885```yue
886numbers = [1, 2, 3, 4]
887sqrts = {i, math.sqrt i for i in *numbers}
888```
889
890</YueDisplay>
891
892&emsp;&emsp;表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值: 427&emsp;&emsp;表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值:
893 428
894&emsp;&emsp;在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。 429&emsp;&emsp;在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。
@@ -898,15 +433,6 @@ tuples = [ ["hello", "world"], ["foo", "bar"]]
898tbl = {unpack tuple for tuple in *tuples} 433tbl = {unpack tuple for tuple in *tuples}
899``` 434```
900 435
901<YueDisplay>
902
903```yue
904tuples = [ ["hello", "world"], ["foo", "bar"]]
905tbl = {unpack tuple for tuple in *tuples}
906```
907
908</YueDisplay>
909
910## 切片 436## 切片
911 437
912&emsp;&emsp;当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。 438&emsp;&emsp;当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。
@@ -917,42 +443,18 @@ tbl = {unpack tuple for tuple in *tuples}
917slice = [item for item in *items[1, 5]] 443slice = [item for item in *items[1, 5]]
918``` 444```
919 445
920<YueDisplay>
921
922```yue
923slice = [item for item in *items[1, 5]]
924```
925
926</YueDisplay>
927
928&emsp;&emsp;切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素: 446&emsp;&emsp;切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素:
929 447
930```yuescript 448```yuescript
931slice = [item for item in *items[2,]] 449slice = [item for item in *items[2,]]
932``` 450```
933 451
934<YueDisplay>
935
936```yue
937slice = [item for item in *items[2,]]
938```
939
940</YueDisplay>
941
942&emsp;&emsp;如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …) 452&emsp;&emsp;如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …)
943 453
944```yuescript 454```yuescript
945slice = [item for item in *items[,,2]] 455slice = [item for item in *items[,,2]]
946``` 456```
947 457
948<YueDisplay>
949
950```yue
951slice = [item for item in *items[,,2]]
952```
953
954</YueDisplay>
955
956&emsp;&emsp;最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。 458&emsp;&emsp;最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
957 459
958```yuescript 460```yuescript
@@ -960,29 +462,12 @@ slice = [item for item in *items[,,2]]
960slice = [item for item in *items[-4,-1]] 462slice = [item for item in *items[-4,-1]]
961``` 463```
962 464
963<YueDisplay>
964
965```yue
966-- 取最后4个元素
967slice = [item for item in *items[-4,-1]]
968```
969
970</YueDisplay>
971
972&emsp;&emsp;切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。 465&emsp;&emsp;切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
973 466
974```yuescript 467```yuescript
975reverse_slice = [item for item in *items[-1,1,-1]] 468reverse_slice = [item for item in *items[-1,1,-1]]
976``` 469```
977 470
978<YueDisplay>
979
980```yue
981reverse_slice = [item for item in *items[-1,1,-1]]
982```
983
984</YueDisplay>
985
986### 切片表达式 471### 切片表达式
987 472
988&emsp;&emsp;切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。 473&emsp;&emsp;切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
@@ -995,18 +480,6 @@ sub_list = items[2, 4]
995last_four_items = items[-4, -1] 480last_four_items = items[-4, -1]
996``` 481```
997 482
998<YueDisplay>
999
1000```yue
1001-- 取第2和第4个元素作为新的列表
1002sub_list = items[2, 4]
1003
1004-- 取最后4个元素作为新的列表
1005last_four_items = items[-4, -1]
1006```
1007
1008</YueDisplay>
1009
1010# 面向对象编程 483# 面向对象编程
1011 484
1012&emsp;&emsp;在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。 485&emsp;&emsp;在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。
@@ -1025,22 +498,6 @@ class Inventory
1025 @items[name] = 1 498 @items[name] = 1
1026``` 499```
1027 500
1028<YueDisplay>
1029
1030```yue
1031class Inventory
1032 new: =>
1033 @items = {}
1034
1035 add_item: (name) =>
1036 if @items[name]
1037 @items[name] += 1
1038 else
1039 @items[name] = 1
1040```
1041
1042</YueDisplay>
1043
1044&emsp;&emsp;在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。 501&emsp;&emsp;在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。
1045 502
1046&emsp;&emsp;值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。 503&emsp;&emsp;值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。
@@ -1055,16 +512,6 @@ inv\add_item "t-shirt"
1055inv\add_item "pants" 512inv\add_item "pants"
1056``` 513```
1057 514
1058<YueDisplay>
1059
1060```yue
1061inv = Inventory!
1062inv\add_item "t-shirt"
1063inv\add_item "pants"
1064```
1065
1066</YueDisplay>
1067
1068&emsp;&emsp;在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。 515&emsp;&emsp;在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。
1069 516
1070&emsp;&emsp;需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。 517&emsp;&emsp;需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。
@@ -1087,26 +534,6 @@ b\give_item "shirt"
1087print item for item in *a.clothes 534print item for item in *a.clothes
1088``` 535```
1089 536
1090<YueDisplay>
1091
1092```yue
1093class Person
1094 clothes: []
1095 give_item: (name) =>
1096 table.insert @clothes, name
1097
1098a = Person!
1099b = Person!
1100
1101a\give_item "pants"
1102b\give_item "shirt"
1103
1104-- 会同时打印出裤子和衬衫
1105print item for item in *a.clothes
1106```
1107
1108</YueDisplay>
1109
1110&emsp;&emsp;避免这个问题的正确方法是在构造函数中创建对象的可变状态: 537&emsp;&emsp;避免这个问题的正确方法是在构造函数中创建对象的可变状态:
1111 538
1112```yuescript 539```yuescript
@@ -1115,16 +542,6 @@ class Person
1115 @clothes = [] 542 @clothes = []
1116``` 543```
1117 544
1118<YueDisplay>
1119
1120```yue
1121class Person
1122 new: =>
1123 @clothes = []
1124```
1125
1126</YueDisplay>
1127
1128## 继承 545## 继承
1129 546
1130&emsp;&emsp;`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。 547&emsp;&emsp;`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。
@@ -1137,18 +554,6 @@ class BackPack extends Inventory
1137 super name 554 super name
1138``` 555```
1139 556
1140<YueDisplay>
1141
1142```yue
1143class BackPack extends Inventory
1144 size: 10
1145 add_item: (name) =>
1146 if #@items > size then error "背包已满"
1147 super name
1148```
1149
1150</YueDisplay>
1151
1152&emsp;&emsp;在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。 557&emsp;&emsp;在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。
1153 558
1154&emsp;&emsp;在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。 559&emsp;&emsp;在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。
@@ -1164,19 +569,6 @@ class Shelf
1164class Cupboard extends Shelf 569class Cupboard extends Shelf
1165``` 570```
1166 571
1167<YueDisplay>
1168
1169```yue
1170class Shelf
1171 @__inherited: (child) =>
1172 print @__name, "被", child.__name, "继承"
1173
1174-- 将打印: Shelf 被 Cupboard 继承
1175class Cupboard extends Shelf
1176```
1177
1178</YueDisplay>
1179
1180## super 关键字 572## super 关键字
1181 573
1182&emsp;&emsp;`super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。 574&emsp;&emsp;`super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。
@@ -1201,22 +593,6 @@ class MyClass extends ParentClass
1201 assert super == ParentClass 593 assert super == ParentClass
1202``` 594```
1203 595
1204<YueDisplay>
1205
1206```yue
1207class MyClass extends ParentClass
1208 a_method: =>
1209 -- 以下效果相同:
1210 super "你好", "世界"
1211 super\a_method "你好", "世界"
1212 super.a_method self, "你好", "世界"
1213
1214 -- super 作为值等于父类:
1215 assert super == ParentClass
1216```
1217
1218</YueDisplay>
1219
1220&emsp;&emsp;**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。 596&emsp;&emsp;**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。
1221 597
1222## 类型 598## 类型
@@ -1230,17 +606,6 @@ assert b.__class == BackPack
1230print BackPack.size -- 打印 10 606print BackPack.size -- 打印 10
1231``` 607```
1232 608
1233<YueDisplay>
1234
1235```yue
1236b = BackPack!
1237assert b.__class == BackPack
1238
1239print BackPack.size -- 打印 10
1240```
1241
1242</YueDisplay>
1243
1244## 类对象 609## 类对象
1245 610
1246&emsp;&emsp;在月之脚本中,当我们编写类的定义语句时,实际上是在创建一个类对象。这个类对象被保存在一个与该类同名的变量中。 611&emsp;&emsp;在月之脚本中,当我们编写类的定义语句时,实际上是在创建一个类对象。这个类对象被保存在一个与该类同名的变量中。
@@ -1259,14 +624,6 @@ print BackPack.size -- 打印 10
1259print BackPack.__name -- 打印 Backpack 624print BackPack.__name -- 打印 Backpack
1260``` 625```
1261 626
1262<YueDisplay>
1263
1264```yue
1265print BackPack.__name -- 打印 Backpack
1266```
1267
1268</YueDisplay>
1269
1270&emsp;&emsp;基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。 627&emsp;&emsp;基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。
1271 628
1272&emsp;&emsp;另外,如果一个类是从另一个类派生而来的,那么其父类对象则会被存储在名为 `__parent` 的地方。这种机制允许在类之间实现继承和功能扩展。 629&emsp;&emsp;另外,如果一个类是从另一个类派生而来的,那么其父类对象则会被存储在名为 `__parent` 的地方。这种机制允许在类之间实现继承和功能扩展。
@@ -1285,20 +642,6 @@ Things\some_func!
1285assert Things().some_func == nil 642assert Things().some_func == nil
1286``` 643```
1287 644
1288<YueDisplay>
1289
1290```yue
1291class Things
1292 @some_func: => print "Hello from", @__name
1293
1294Things\some_func!
1295
1296-- 类变量在实例中不可见
1297assert Things().some_func == nil
1298```
1299
1300</YueDisplay>
1301
1302&emsp;&emsp;在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。 645&emsp;&emsp;在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。
1303 646
1304```yuescript 647```yuescript
@@ -1314,37 +657,12 @@ Counter!
1314print Counter.count -- 输出 2 657print Counter.count -- 输出 2
1315``` 658```
1316 659
1317<YueDisplay>
1318
1319```yue
1320class Counter
1321 @count: 0
1322
1323 new: =>
1324 @@count += 1
1325
1326Counter!
1327Counter!
1328
1329print Counter.count -- 输出 2
1330```
1331
1332</YueDisplay>
1333
1334&emsp;&emsp;@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。 660&emsp;&emsp;@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。
1335 661
1336```yuescript 662```yuescript
1337@@hello 1,2,3,4 663@@hello 1,2,3,4
1338``` 664```
1339 665
1340<YueDisplay>
1341
1342```yue
1343@@hello 1,2,3,4
1344```
1345
1346</YueDisplay>
1347
1348## 类声明语句 666## 类声明语句
1349 667
1350&emsp;&emsp;在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。 668&emsp;&emsp;在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。
@@ -1356,15 +674,6 @@ class Things
1356 @class_var = "hello world" 674 @class_var = "hello world"
1357``` 675```
1358 676
1359<YueDisplay>
1360
1361```yue
1362class Things
1363 @class_var = "hello world"
1364```
1365
1366</YueDisplay>
1367
1368&emsp;&emsp;这些表达式会在所有属性被添加到类的基对象后执行。 677&emsp;&emsp;这些表达式会在所有属性被添加到类的基对象后执行。
1369 678
1370&emsp;&emsp;在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便: 679&emsp;&emsp;在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便:
@@ -1378,19 +687,6 @@ class MoreThings
1378 log "hello world: " .. secret 687 log "hello world: " .. secret
1379``` 688```
1380 689
1381<YueDisplay>
1382
1383```yue
1384class MoreThings
1385 secret = 123
1386 log = (msg) -> print "LOG:", msg
1387
1388 some_method: =>
1389 log "hello world: " .. secret
1390```
1391
1392</YueDisplay>
1393
1394## @ 和 @@ 值 690## @ 和 @@ 值
1395 691
1396&emsp;&emsp;当 @ 和 @@ 前缀在一个名字前时,它们分别代表在 self 和 self.\_\_class 中访问的那个名字。 692&emsp;&emsp;当 @ 和 @@ 前缀在一个名字前时,它们分别代表在 self 和 self.\_\_class 中访问的那个名字。
@@ -1402,29 +698,12 @@ assert @ == self
1402assert @@ == self.__class 698assert @@ == self.__class
1403``` 699```
1404 700
1405<YueDisplay>
1406
1407```yue
1408assert @ == self
1409assert @@ == self.__class
1410```
1411
1412</YueDisplay>
1413
1414&emsp;&emsp;例如,使用 @@ 从实例方法快速创建同一类的新实例的方法: 701&emsp;&emsp;例如,使用 @@ 从实例方法快速创建同一类的新实例的方法:
1415 702
1416```yuescript 703```yuescript
1417some_instance_method = (...) => @@ ... 704some_instance_method = (...) => @@ ...
1418``` 705```
1419 706
1420<YueDisplay>
1421
1422```yue
1423some_instance_method = (...) => @@ ...
1424```
1425
1426</YueDisplay>
1427
1428## 构造属性提升 707## 构造属性提升
1429 708
1430&emsp;&emsp;为了减少编写简单值对象定义的代码。你可以这样简单写一个类: 709&emsp;&emsp;为了减少编写简单值对象定义的代码。你可以这样简单写一个类:
@@ -1443,24 +722,6 @@ class Something
1443 @@baz = baz 722 @@baz = baz
1444``` 723```
1445 724
1446<YueDisplay>
1447
1448```yue
1449class Something
1450 new: (@foo, @bar, @@biz, @@baz) =>
1451
1452-- 这是以下声明的简写形式
1453
1454class Something
1455 new: (foo, bar, biz, baz) =>
1456 @foo = foo
1457 @bar = bar
1458 @@biz = biz
1459 @@baz = baz
1460```
1461
1462</YueDisplay>
1463
1464&emsp;&emsp;你也可以使用这种语法为一个函数初始化传入对象的字段。 725&emsp;&emsp;你也可以使用这种语法为一个函数初始化传入对象的字段。
1465 726
1466```yuescript 727```yuescript
@@ -1469,16 +730,6 @@ obj = new {}, 123, "abc"
1469print obj 730print obj
1470``` 731```
1471 732
1472<YueDisplay>
1473
1474```yue
1475new = (@fieldA, @fieldB) => @
1476obj = new {}, 123, "abc"
1477print obj
1478```
1479
1480</YueDisplay>
1481
1482## 类表达式 733## 类表达式
1483 734
1484&emsp;&emsp;类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。 735&emsp;&emsp;类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。
@@ -1489,16 +740,6 @@ x = class Bucket
1489 add_drop: => @drops += 1 740 add_drop: => @drops += 1
1490``` 741```
1491 742
1492<YueDisplay>
1493
1494```yue
1495x = class Bucket
1496 drops: 0
1497 add_drop: => @drops += 1
1498```
1499
1500</YueDisplay>
1501
1502## 匿名类 743## 匿名类
1503 744
1504&emsp;&emsp;声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。 745&emsp;&emsp;声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。
@@ -1510,31 +751,12 @@ BigBucket = class extends Bucket
1510assert Bucket.__name == "BigBucket" 751assert Bucket.__name == "BigBucket"
1511``` 752```
1512 753
1513<YueDisplay>
1514
1515```yue
1516BigBucket = class extends Bucket
1517 add_drop: => @drops += 10
1518
1519assert Bucket.__name == "BigBucket"
1520```
1521
1522</YueDisplay>
1523
1524&emsp;&emsp;你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类: 754&emsp;&emsp;你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类:
1525 755
1526```yuescript 756```yuescript
1527x = class 757x = class
1528``` 758```
1529 759
1530<YueDisplay>
1531
1532```yue
1533x = class
1534```
1535
1536</YueDisplay>
1537
1538## 类混合 760## 类混合
1539 761
1540&emsp;&emsp;你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 762&emsp;&emsp;你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
@@ -1557,28 +779,6 @@ y\func!
1557assert y.__class.__parent ~= X -- X 不是 Y 的父类 779assert y.__class.__parent ~= X -- X 不是 Y 的父类
1558``` 780```
1559 781
1560<YueDisplay>
1561
1562```yue
1563MyIndex = __index: var: 1
1564
1565class X using MyIndex
1566 func: =>
1567 print 123
1568
1569x = X!
1570print x.var
1571
1572class Y using X
1573
1574y = Y!
1575y\func!
1576
1577assert y.__class.__parent ~= X -- X 不是 Y 的父类
1578```
1579
1580</YueDisplay>
1581
1582# with 语句 782# with 语句
1583 783
1584在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。 784在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。
@@ -1597,18 +797,6 @@ with Person!
1597 print .name 797 print .name
1598``` 798```
1599 799
1600<YueDisplay>
1601
1602```yue
1603with Person!
1604 .name = "Oswald"
1605 \add_relative my_dad
1606 \save!
1607 print .name
1608```
1609
1610</YueDisplay>
1611
1612with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。 800with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。
1613 801
1614```yuescript 802```yuescript
@@ -1616,15 +804,6 @@ file = with File "favorite_foods.txt"
1616 \set_encoding "utf8" 804 \set_encoding "utf8"
1617``` 805```
1618 806
1619<YueDisplay>
1620
1621```yue
1622file = with File "favorite_foods.txt"
1623 \set_encoding "utf8"
1624```
1625
1626</YueDisplay>
1627
1628`with` 表达式支持 `break` 返回一个值: 807`with` 表达式支持 `break` 返回一个值:
1629 808
1630```yuescript 809```yuescript
@@ -1632,15 +811,6 @@ result = with obj
1632 break .value 811 break .value
1633``` 812```
1634 813
1635<YueDisplay>
1636
1637```yue
1638result = with obj
1639 break .value
1640```
1641
1642</YueDisplay>
1643
1644在 `with` 中使用 `break value` 后,`with` 表达式将不再返回其目标对象,而是返回 `break` 给出的值。 814在 `with` 中使用 `break value` 后,`with` 表达式将不再返回其目标对象,而是返回 `break` 给出的值。
1645 815
1646```yuescript 816```yuescript
@@ -1653,20 +823,6 @@ b = with obj
1653-- b 是 .x,不是 obj 823-- b 是 .x,不是 obj
1654``` 824```
1655 825
1656<YueDisplay>
1657
1658```yue
1659a = with obj
1660 .x = 1
1661-- a 是 obj
1662
1663b = with obj
1664 break .x
1665-- b 是 .x,不是 obj
1666```
1667
1668</YueDisplay>
1669
1670与 `for` / `while` / `repeat` / `do` 不同,`with` 只支持一个 break 返回值。 826与 `for` / `while` / `repeat` / `do` 不同,`with` 只支持一个 break 返回值。
1671 827
1672或者… 828或者…
@@ -1680,19 +836,6 @@ create_person = (name, relatives) ->
1680me = create_person "Leaf", [dad, mother, sister] 836me = create_person "Leaf", [dad, mother, sister]
1681``` 837```
1682 838
1683<YueDisplay>
1684
1685```yue
1686create_person = (name, relatives) ->
1687 with Person!
1688 .name = name
1689 \add_relative relative for relative in *relatives
1690
1691me = create_person "Leaf", [dad, mother, sister]
1692```
1693
1694</YueDisplay>
1695
1696在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。 839在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。
1697 840
1698如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。 841如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。
@@ -1703,16 +846,6 @@ with str := "你好"
1703 print "大写:", \upper! 846 print "大写:", \upper!
1704``` 847```
1705 848
1706<YueDisplay>
1707
1708```yue
1709with str := "你好"
1710 print "原始:", str
1711 print "大写:", \upper!
1712```
1713
1714</YueDisplay>
1715
1716你可以在 `with` 语句中使用 `[]` 访问特殊键。 849你可以在 `with` 语句中使用 `[]` 访问特殊键。
1717 850
1718```yuescript 851```yuescript
@@ -1725,20 +858,6 @@ with tb
1725 [] = "abc" -- 追加到 "tb" 858 [] = "abc" -- 追加到 "tb"
1726``` 859```
1727 860
1728<YueDisplay>
1729
1730```yue
1731with tb
1732 [1] = 1
1733 print [2]
1734 with [abc]
1735 [3] = [2]\func!
1736 ["key-name"] = value
1737 [] = "abc" -- 追加到 "tb"
1738```
1739
1740</YueDisplay>
1741
1742`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。 861`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
1743 862
1744```yuescript 863```yuescript
@@ -1746,15 +865,6 @@ with? obj
1746 print obj.name 865 print obj.name
1747``` 866```
1748 867
1749<YueDisplay>
1750
1751```yue
1752with? obj
1753 print obj.name
1754```
1755
1756</YueDisplay>
1757
1758# 赋值 868# 赋值
1759 869
1760&emsp;&emsp;月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。 870&emsp;&emsp;月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。
@@ -1765,16 +875,6 @@ a, b, c = 1, 2, 3
1765hello = 123 -- 访问现有的变量 875hello = 123 -- 访问现有的变量
1766``` 876```
1767 877
1768<YueDisplay>
1769
1770```yue
1771hello = "world"
1772a, b, c = 1, 2, 3
1773hello = 123 -- 访问现有的变量
1774```
1775
1776</YueDisplay>
1777
1778## 执行更新 878## 执行更新
1779 879
1780&emsp;&emsp;你可以使用各式二进制运算符执行更新赋值。 880&emsp;&emsp;你可以使用各式二进制运算符执行更新赋值。
@@ -1790,21 +890,6 @@ s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局
1790arg or= "默认值" 890arg or= "默认值"
1791``` 891```
1792 892
1793<YueDisplay>
1794
1795```yue
1796x = 1
1797x += 1
1798x -= 1
1799x *= 10
1800x /= 10
1801x %= 10
1802s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
1803arg or= "默认值"
1804```
1805
1806</YueDisplay>
1807
1808## 链式赋值 893## 链式赋值
1809 894
1810&emsp;&emsp;你可以进行链式赋值,将多个项目赋予相同的值。 895&emsp;&emsp;你可以进行链式赋值,将多个项目赋予相同的值。
@@ -1814,15 +899,6 @@ a = b = c = d = e = 0
1814x = y = z = f! 899x = y = z = f!
1815``` 900```
1816 901
1817<YueDisplay>
1818
1819```yue
1820a = b = c = d = e = 0
1821x = y = z = f!
1822```
1823
1824</YueDisplay>
1825
1826## 显式声明局部变量 902## 显式声明局部变量
1827 903
1828```yuescript 904```yuescript
@@ -1842,27 +918,6 @@ do
1842 B = 2 918 B = 2
1843``` 919```
1844 920
1845<YueDisplay>
1846
1847```yue
1848do
1849 local a = 1
1850 local *
1851 print "预先声明后续所有变量为局部变量"
1852 x = -> 1 + y + z
1853 y, z = 2, 3
1854 global instance = Item\new!
1855
1856do
1857 local X = 1
1858 local ^
1859 print "只预先声明后续大写的变量为局部变量"
1860 a = 1
1861 B = 2
1862```
1863
1864</YueDisplay>
1865
1866## 显式声明全局变量 921## 显式声明全局变量
1867 922
1868```yuescript 923```yuescript
@@ -1882,27 +937,6 @@ do
1882 local Temp = "一个局部值" 937 local Temp = "一个局部值"
1883``` 938```
1884 939
1885<YueDisplay>
1886
1887```yue
1888do
1889 global a = 1
1890 global *
1891 print "预先声明所有变量为全局变量"
1892 x = -> 1 + y + z
1893 y, z = 2, 3
1894
1895do
1896 global x = 1
1897 global ^
1898 print "只预先声明大写的变量为全局变量"
1899 a = 1
1900 B = 2
1901 local Temp = "一个局部值"
1902```
1903
1904</YueDisplay>
1905
1906# 可变参数赋值 940# 可变参数赋值
1907 941
1908&emsp;&emsp;你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。 942&emsp;&emsp;你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。
@@ -1916,19 +950,6 @@ first = select 1, ...
1916print ok, count, first 950print ok, count, first
1917``` 951```
1918 952
1919<YueDisplay>
1920
1921```yue
1922list = [1, 2, 3, 4, 5]
1923fn = (ok) -> ok, table.unpack list
1924ok, ... = fn true
1925count = select '#', ...
1926first = select 1, ...
1927print ok, count, first
1928```
1929
1930</YueDisplay>
1931
1932# If 赋值 953# If 赋值
1933 954
1934&emsp;&emsp;`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。 955&emsp;&emsp;`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。
@@ -1938,15 +959,6 @@ if user := database.find_user "moon"
1938 print user.name 959 print user.name
1939``` 960```
1940 961
1941<YueDisplay>
1942
1943```yue
1944if user := database.find_user "moon"
1945 print user.name
1946```
1947
1948</YueDisplay>
1949
1950```yuescript 962```yuescript
1951if hello := os.getenv "hello" 963if hello := os.getenv "hello"
1952 print "你有 hello", hello 964 print "你有 hello", hello
@@ -1956,19 +968,6 @@ else
1956 print "什么都没有 :(" 968 print "什么都没有 :("
1957``` 969```
1958 970
1959<YueDisplay>
1960
1961```yue
1962if hello := os.getenv "hello"
1963 print "你有 hello", hello
1964elseif world := os.getenv "world"
1965 print "你有 world", world
1966else
1967 print "什么都没有 :("
1968```
1969
1970</YueDisplay>
1971
1972&emsp;&emsp;使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。 971&emsp;&emsp;使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。
1973 972
1974```yuescript 973```yuescript
@@ -1977,16 +976,6 @@ if success, result := pcall -> "无报错地获取结果"
1977print "好的" 976print "好的"
1978``` 977```
1979 978
1980<YueDisplay>
1981
1982```yue
1983if success, result := pcall -> "无报错地获取结果"
1984 print result -- 变量 result 是有作用域的
1985print "好的"
1986```
1987
1988</YueDisplay>
1989
1990## While 赋值 979## While 赋值
1991 980
1992&emsp;&emsp;你可以在 while 循环中同样使用赋值来获取循环条件的值。 981&emsp;&emsp;你可以在 while 循环中同样使用赋值来获取循环条件的值。
@@ -1997,16 +986,6 @@ while byte := stream\read_one!
1997 print byte 986 print byte
1998``` 987```
1999 988
2000<YueDisplay>
2001
2002```yue
2003while byte := stream\read_one!
2004 -- 对 byte 做一些操作
2005 print byte
2006```
2007
2008</YueDisplay>
2009
2010# 解构赋值 989# 解构赋值
2011 990
2012&emsp;&emsp;解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。 991&emsp;&emsp;解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。
@@ -2022,17 +1001,6 @@ thing = [1, 2]
2022print a, b 1001print a, b
2023``` 1002```
2024 1003
2025<YueDisplay>
2026
2027```yue
2028thing = [1, 2]
2029
2030[a, b] = thing
2031print a, b
2032```
2033
2034</YueDisplay>
2035
2036&emsp;&emsp;在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。 1004&emsp;&emsp;在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。
2037 1005
2038```yuescript 1006```yuescript
@@ -2048,23 +1016,6 @@ print hello, the_day
2048:day = obj -- 可以不带大括号进行简单的解构 1016:day = obj -- 可以不带大括号进行简单的解构
2049``` 1017```
2050 1018
2051<YueDisplay>
2052
2053```yue
2054obj = {
2055 hello: "world"
2056 day: "tuesday"
2057 length: 20
2058}
2059
2060{hello: hello, day: the_day} = obj
2061print hello, the_day
2062
2063:day = obj -- 可以不带大括号进行简单的解构
2064```
2065
2066</YueDisplay>
2067
2068&emsp;&emsp;这也适用于嵌套的数据结构: 1019&emsp;&emsp;这也适用于嵌套的数据结构:
2069 1020
2070```yuescript 1021```yuescript
@@ -2080,23 +1031,6 @@ obj2 = {
2080print first, second, color 1031print first, second, color
2081``` 1032```
2082 1033
2083<YueDisplay>
2084
2085```yue
2086obj2 = {
2087 numbers: [1,2,3,4]
2088 properties: {
2089 color: "green"
2090 height: 13.5
2091 }
2092}
2093
2094{numbers: [first, second], properties: {color: color}} = obj2
2095print first, second, color
2096```
2097
2098</YueDisplay>
2099
2100&emsp;&emsp;如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例: 1034&emsp;&emsp;如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例:
2101 1035
2102```yuescript 1036```yuescript
@@ -2108,75 +1042,30 @@ print first, second, color
2108} = obj2 1042} = obj2
2109``` 1043```
2110 1044
2111<YueDisplay>
2112
2113```yue
2114{
2115 numbers: [first, second]
2116 properties: {
2117 color: color
2118 }
2119} = obj2
2120```
2121
2122</YueDisplay>
2123
2124&emsp;&emsp;有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符: 1045&emsp;&emsp;有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符:
2125 1046
2126```yuescript 1047```yuescript
2127{:concat, :insert} = table 1048{:concat, :insert} = table
2128``` 1049```
2129 1050
2130<YueDisplay>
2131
2132```yue
2133{:concat, :insert} = table
2134```
2135
2136</YueDisplay>
2137
2138&emsp;&emsp;这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段: 1051&emsp;&emsp;这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段:
2139 1052
2140```yuescript 1053```yuescript
2141{:mix, :max, random: rand} = math 1054{:mix, :max, random: rand} = math
2142``` 1055```
2143 1056
2144<YueDisplay>
2145
2146```yue
2147{:mix, :max, random: rand} = math
2148```
2149
2150</YueDisplay>
2151
2152&emsp;&emsp;在进行解构时,你可以指定默认值,如: 1057&emsp;&emsp;在进行解构时,你可以指定默认值,如:
2153 1058
2154```yuescript 1059```yuescript
2155{:name = "nameless", :job = "jobless"} = person 1060{:name = "nameless", :job = "jobless"} = person
2156``` 1061```
2157 1062
2158<YueDisplay>
2159
2160```yue
2161{:name = "nameless", :job = "jobless"} = person
2162```
2163
2164</YueDisplay>
2165
2166&emsp;&emsp;在进行列表解构时,你可以使用`_`作为占位符: 1063&emsp;&emsp;在进行列表解构时,你可以使用`_`作为占位符:
2167 1064
2168```yuescript 1065```yuescript
2169[_, two, _, four] = items 1066[_, two, _, four] = items
2170``` 1067```
2171 1068
2172<YueDisplay>
2173
2174```yue
2175[_, two, _, four] = items
2176```
2177
2178</YueDisplay>
2179
2180## 范围解构 1069## 范围解构
2181 1070
2182&emsp;&emsp;你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。 1071&emsp;&emsp;你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
@@ -2189,18 +1078,6 @@ print bulk -- 打印: {"second", "third", "fourth"}
2189print last -- 打印: last 1078print last -- 打印: last
2190``` 1079```
2191 1080
2192<YueDisplay>
2193
2194```yue
2195orders = ["first", "second", "third", "fourth", "last"]
2196[first, ...bulk, last] = orders
2197print first -- 打印: first
2198print bulk -- 打印: {"second", "third", "fourth"}
2199print last -- 打印: last
2200```
2201
2202</YueDisplay>
2203
2204&emsp;&emsp;展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获: 1081&emsp;&emsp;展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
2205 1082
2206```yuescript 1083```yuescript
@@ -2214,21 +1091,6 @@ print last -- 打印: last
2214[first, ..._, last] = orders 1091[first, ..._, last] = orders
2215``` 1092```
2216 1093
2217<YueDisplay>
2218
2219```yue
2220-- 捕获第一个元素之后的所有元素
2221[first, ...rest] = orders
2222
2223-- 捕获最后一个元素之前的所有元素
2224[...start, last] = orders
2225
2226-- 跳过中间的元素,只捕获第一个和最后一个元素
2227[first, ..._, last] = orders
2228```
2229
2230</YueDisplay>
2231
2232## 在其它地方的解构赋值 1094## 在其它地方的解构赋值
2233 1095
2234&emsp;&emsp;解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中: 1096&emsp;&emsp;解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中:
@@ -2243,20 +1105,6 @@ for [left, right] in *tuples
2243 print left, right 1105 print left, right
2244``` 1106```
2245 1107
2246<YueDisplay>
2247
2248```yue
2249tuples = [
2250 ["hello", "world"]
2251 ["egg", "head"]
2252]
2253
2254for [left, right] in *tuples
2255 print left, right
2256```
2257
2258</YueDisplay>
2259
2260&emsp;&emsp;我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。 1108&emsp;&emsp;我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。
2261 1109
2262# 使用 using 语句:防止破坏性赋值 1110# 使用 using 语句:防止破坏性赋值
@@ -2279,26 +1127,6 @@ my_func!
2279print i -- 将打印 0 1127print i -- 将打印 0
2280``` 1128```
2281 1129
2282<YueDisplay>
2283
2284```yue
2285i = 100
2286
2287-- 许多代码行...
2288
2289my_func = ->
2290 i = 10
2291 while i > 0
2292 print i
2293 i -= 1
2294
2295my_func!
2296
2297print i -- 将打印 0
2298```
2299
2300</YueDisplay>
2301
2302&emsp;&emsp;在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。 1130&emsp;&emsp;在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。
2303 1131
2304&emsp;&emsp;如果我们可以明确指出哪些变量是我们想在当前作用域内修改的,并且防止我们不小心更改了其他作用域中同名的变量,那将大有裨益。 1132&emsp;&emsp;如果我们可以明确指出哪些变量是我们想在当前作用域内修改的,并且防止我们不小心更改了其他作用域中同名的变量,那将大有裨益。
@@ -2315,20 +1143,6 @@ my_func!
2315print i -- 打印 100,i 没有受到影响 1143print i -- 打印 100,i 没有受到影响
2316``` 1144```
2317 1145
2318<YueDisplay>
2319
2320```yue
2321i = 100
2322
2323my_func = (using nil) ->
2324 i = "hello" -- 这里创建了一个新的局部变量
2325
2326my_func!
2327print i -- 打印 100,i 没有受到影响
2328```
2329
2330</YueDisplay>
2331
2332&emsp;&emsp;using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称: 1146&emsp;&emsp;using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称:
2333 1147
2334```yuescript 1148```yuescript
@@ -2344,23 +1158,6 @@ my_func(22)
2344print i, k -- 这些已经被更新 1158print i, k -- 这些已经被更新
2345``` 1159```
2346 1160
2347<YueDisplay>
2348
2349```yue
2350tmp = 1213
2351i, k = 100, 50
2352
2353my_func = (add using k, i) ->
2354 tmp = tmp + add -- 创建了一个新的局部tmp
2355 i += tmp
2356 k += tmp
2357
2358my_func(22)
2359print i, k -- 这些已经被更新
2360```
2361
2362</YueDisplay>
2363
2364# 使用方法 1161# 使用方法
2365 1162
2366## Lua 模块 1163## Lua 模块
@@ -2527,55 +1324,6 @@ with apple
2527export 🌛 = "月之脚本" 1324export 🌛 = "月之脚本"
2528``` 1325```
2529 1326
2530<YueDisplay>
2531
2532```yue
2533-- 导入语法
2534import p, to_lua from "yue"
2535
2536-- 隐式对象
2537inventory =
2538 equipment:
2539 - "sword"
2540 - "shield"
2541 items:
2542 - name: "potion"
2543 count: 10
2544 - name: "bread"
2545 count: 3
2546
2547-- 列表推导
2548map = (arr, action) ->
2549 [action item for item in *arr]
2550
2551filter = (arr, cond) ->
2552 [item for item in *arr when cond item]
2553
2554reduce = (arr, init, action): init ->
2555 init = action init, item for item in *arr
2556
2557-- 管道操作符
2558[1, 2, 3]
2559 |> map (x) -> x * 2
2560 |> filter (x) -> x > 4
2561 |> reduce 0, (a, b) -> a + b
2562 |> print
2563
2564-- 元表操作
2565apple =
2566 size: 15
2567 <index>:
2568 color: 0x00ffff
2569
2570with apple
2571 p .size, .color, .<index> if .<>?
2572
2573-- 类似js的导出语法
2574export 🌛 = "月之脚本"
2575```
2576
2577</YueDisplay>
2578
2579## 关于 Dora SSR 1327## 关于 Dora SSR
2580 1328
2581月之脚本是与开源游戏引擎 [Dora SSR](https://github.com/Dora-SSR/Dora-SSR) 一起开发和维护的。它已被用于创建引擎工具、游戏原型和演示,在实际的游戏项目中验证其能力,同时它也帮助增强了 Dora SSR 游戏引擎的开发体验。 1329月之脚本是与开源游戏引擎 [Dora SSR](https://github.com/Dora-SSR/Dora-SSR) 一起开发和维护的。它已被用于创建引擎工具、游戏原型和演示,在实际的游戏项目中验证其能力,同时它也帮助增强了 Dora SSR 游戏引擎的开发体验。
@@ -2634,18 +1382,6 @@ else
2634 print "没有硬币" 1382 print "没有硬币"
2635``` 1383```
2636 1384
2637<YueDisplay>
2638
2639```yue
2640have_coins = false
2641if have_coins
2642 print "有硬币"
2643else
2644 print "没有硬币"
2645```
2646
2647</YueDisplay>
2648
2649&emsp;&emsp;对于简单的语句,也可以使用简短的语法: 1385&emsp;&emsp;对于简单的语句,也可以使用简短的语法:
2650 1386
2651```yuescript 1387```yuescript
@@ -2653,15 +1389,6 @@ have_coins = false
2653if have_coins then print "有硬币" else print "没有硬币" 1389if have_coins then print "有硬币" else print "没有硬币"
2654``` 1390```
2655 1391
2656<YueDisplay>
2657
2658```yue
2659have_coins = false
2660if have_coins then print "有硬币" else print "没有硬币"
2661```
2662
2663</YueDisplay>
2664
2665&emsp;&emsp;因为 if 语句可以用作表达式,所以也可以这样写: 1392&emsp;&emsp;因为 if 语句可以用作表达式,所以也可以这样写:
2666 1393
2667```yuescript 1394```yuescript
@@ -2669,15 +1396,6 @@ have_coins = false
2669print if have_coins then "有硬币" else "没有硬币" 1396print if have_coins then "有硬币" else "没有硬币"
2670``` 1397```
2671 1398
2672<YueDisplay>
2673
2674```yue
2675have_coins = false
2676print if have_coins then "有硬币" else "没有硬币"
2677```
2678
2679</YueDisplay>
2680
2681&emsp;&emsp;条件语句也可以作为表达式用在返回语句和赋值语句中: 1399&emsp;&emsp;条件语句也可以作为表达式用在返回语句和赋值语句中:
2682 1400
2683```yuescript 1401```yuescript
@@ -2695,25 +1413,6 @@ else
2695print message -- 打印: 我很高 1413print message -- 打印: 我很高
2696``` 1414```
2697 1415
2698<YueDisplay>
2699
2700```yue
2701is_tall = (name) ->
2702 if name == "Rob"
2703 true
2704 else
2705 false
2706
2707message = if is_tall "Rob"
2708 "我很高"
2709else
2710 "我不是很高"
2711
2712print message -- 打印: 我很高
2713```
2714
2715</YueDisplay>
2716
2717&emsp;&emsp;if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”): 1416&emsp;&emsp;if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”):
2718 1417
2719```yuescript 1418```yuescript
@@ -2721,27 +1420,10 @@ unless os.date("%A") == "Monday"
2721 print "今天不是星期一!" 1420 print "今天不是星期一!"
2722``` 1421```
2723 1422
2724<YueDisplay>
2725
2726```yue
2727unless os.date("%A") == "Monday"
2728 print "今天不是星期一!"
2729```
2730
2731</YueDisplay>
2732
2733```yuescript 1423```yuescript
2734print "你真幸运!" unless math.random! > 0.1 1424print "你真幸运!" unless math.random! > 0.1
2735``` 1425```
2736 1426
2737<YueDisplay>
2738
2739```yue
2740print "你真幸运!" unless math.random! > 0.1
2741```
2742
2743</YueDisplay>
2744
2745## 范围表达式 1427## 范围表达式
2746 1428
2747&emsp;&emsp;你可以使用范围表达式来编写进行范围检查的代码。 1429&emsp;&emsp;你可以使用范围表达式来编写进行范围检查的代码。
@@ -2756,20 +1438,6 @@ if a in list
2756 print "检查`a`是否在列表中" 1438 print "检查`a`是否在列表中"
2757``` 1439```
2758 1440
2759<YueDisplay>
2760
2761```yue
2762a = 5
2763
2764if a in [1, 3, 5, 7]
2765 print "检查离散值的相等性"
2766
2767if a in list
2768 print "检查`a`是否在列表中"
2769```
2770
2771</YueDisplay>
2772
2773`in` 运算符也可以用于表,并支持 `not in` 变体来进行否定检查: 1441`in` 运算符也可以用于表,并支持 `not in` 变体来进行否定检查:
2774 1442
2775```yuescript 1443```yuescript
@@ -2783,21 +1451,6 @@ not_exist = item not in list
2783check = -> value not in table 1451check = -> value not in table
2784``` 1452```
2785 1453
2786<YueDisplay>
2787
2788```yue
2789has = "foo" in {"bar", "foo"}
2790
2791if a in {1, 2, 3}
2792 print "a 在表中"
2793
2794not_exist = item not in list
2795
2796check = -> value not in table
2797```
2798
2799</YueDisplay>
2800
2801单元素列表或表会检查与该元素的相等性: 1454单元素列表或表会检查与该元素的相等性:
2802 1455
2803```yuescript 1456```yuescript
@@ -2812,22 +1465,6 @@ with tb
2812 c = a in [1] 1465 c = a in [1]
2813``` 1466```
2814 1467
2815<YueDisplay>
2816
2817```yue
2818-- [1,] 检查 value == 1
2819c = a in [1,]
2820
2821-- {1} 也是检查 value == 1
2822c = a in {1}
2823
2824-- 没有逗号,[1] 是索引访问(tb[1])
2825with tb
2826 c = a in [1]
2827```
2828
2829</YueDisplay>
2830
2831# for 循环 1468# for 循环
2832 1469
2833&emsp;&emsp;Lua 中有两种 for 循环形式,数字型和通用型: 1470&emsp;&emsp;Lua 中有两种 for 循环形式,数字型和通用型:
@@ -2843,21 +1480,6 @@ for key, value in pairs object
2843 print key, value 1480 print key, value
2844``` 1481```
2845 1482
2846<YueDisplay>
2847
2848```yue
2849for i = 10, 20
2850 print i
2851
2852for k = 1, 15, 2 -- 提供了一个遍历的步长
2853 print k
2854
2855for key, value in pairs object
2856 print key, value
2857```
2858
2859</YueDisplay>
2860
2861&emsp;&emsp;可以使用切片和 **\*** 操作符,就像在列表推导中一样: 1483&emsp;&emsp;可以使用切片和 **\*** 操作符,就像在列表推导中一样:
2862 1484
2863```yuescript 1485```yuescript
@@ -2865,15 +1487,6 @@ for item in *items[2, 4]
2865 print item 1487 print item
2866``` 1488```
2867 1489
2868<YueDisplay>
2869
2870```yue
2871for item in *items[2, 4]
2872 print item
2873```
2874
2875</YueDisplay>
2876
2877&emsp;&emsp;当代码语句只有一行时,循环语句也都可以写作更短的语法: 1490&emsp;&emsp;当代码语句只有一行时,循环语句也都可以写作更短的语法:
2878 1491
2879```yuescript 1492```yuescript
@@ -2882,16 +1495,6 @@ for item in *items do print item
2882for j = 1, 10, 3 do print j 1495for j = 1, 10, 3 do print j
2883``` 1496```
2884 1497
2885<YueDisplay>
2886
2887```yue
2888for item in *items do print item
2889
2890for j = 1, 10, 3 do print j
2891```
2892
2893</YueDisplay>
2894
2895&emsp;&emsp;for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。 1498&emsp;&emsp;for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。
2896 1499
2897&emsp;&emsp;将每个偶数加倍: 1500&emsp;&emsp;将每个偶数加倍:
@@ -2904,18 +1507,6 @@ doubled_evens = for i = 1, 20
2904 i 1507 i
2905``` 1508```
2906 1509
2907<YueDisplay>
2908
2909```yue
2910doubled_evens = for i = 1, 20
2911 if i % 2 == 0
2912 i * 2
2913 else
2914 i
2915```
2916
2917</YueDisplay>
2918
2919&emsp;&emsp;此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。for 循环表达式支持 `break` 返回多个值。 1510&emsp;&emsp;此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。for 循环表达式支持 `break` 返回多个值。
2920 1511
2921&emsp;&emsp;例如,查找第一个大于 10 的数字: 1512&emsp;&emsp;例如,查找第一个大于 10 的数字:
@@ -2925,29 +1516,11 @@ first_large = for n in *numbers
2925 break n if n > 10 1516 break n if n > 10
2926``` 1517```
2927 1518
2928<YueDisplay>
2929
2930```yue
2931first_large = for n in *numbers
2932 break n if n > 10
2933```
2934
2935</YueDisplay>
2936
2937```yuescript 1519```yuescript
2938key, score = for k, v in pairs data 1520key, score = for k, v in pairs data
2939 break k, v * 10 if k == "target" 1521 break k, v * 10 if k == "target"
2940``` 1522```
2941 1523
2942<YueDisplay>
2943
2944```yue
2945key, score = for k, v in pairs data
2946 break k, v * 10 if k == "target"
2947```
2948
2949</YueDisplay>
2950
2951&emsp;&emsp;你还可以结合 for 循环表达式与 continue 语句来过滤值。 1524&emsp;&emsp;你还可以结合 for 循环表达式与 continue 语句来过滤值。
2952 1525
2953&emsp;&emsp;注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。 1526&emsp;&emsp;注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。
@@ -2960,18 +1533,6 @@ print func_a! -- 打印 nil
2960print func_b! -- 打印 table 对象 1533print func_b! -- 打印 table 对象
2961``` 1534```
2962 1535
2963<YueDisplay>
2964
2965```yue
2966func_a = -> for i = 1, 10 do print i
2967func_b = -> return for i = 1, 10 do i
2968
2969print func_a! -- 打印 nil
2970print func_b! -- 打印 table 对象
2971```
2972
2973</YueDisplay>
2974
2975&emsp;&emsp;这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。 1536&emsp;&emsp;这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。
2976 1537
2977# continue 语句 1538# continue 语句
@@ -2986,18 +1547,6 @@ while i < 10
2986 print i 1547 print i
2987``` 1548```
2988 1549
2989<YueDisplay>
2990
2991```yue
2992i = 0
2993while i < 10
2994 i += 1
2995 continue if i % 2 == 0
2996 print i
2997```
2998
2999</YueDisplay>
3000
3001&emsp;&emsp;继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组: 1550&emsp;&emsp;继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组:
3002 1551
3003```yuescript 1552```yuescript
@@ -3007,17 +1556,6 @@ odds = for x in *my_numbers
3007 x 1556 x
3008``` 1557```
3009 1558
3010<YueDisplay>
3011
3012```yue
3013my_numbers = [1, 2, 3, 4, 5, 6]
3014odds = for x in *my_numbers
3015 continue if x % 2 == 1
3016 x
3017```
3018
3019</YueDisplay>
3020
3021# switch 语句 1559# switch 语句
3022 1560
3023&emsp;&emsp;switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。 1561&emsp;&emsp;switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。
@@ -3032,20 +1570,6 @@ switch name := "Dan"
3032 print "我不认识你,你的名字是#{name}" 1570 print "我不认识你,你的名字是#{name}"
3033``` 1571```
3034 1572
3035<YueDisplay>
3036
3037```yue
3038switch name := "Dan"
3039 when "Robert"
3040 print "你是Robert"
3041 when "Dan", "Daniel"
3042 print "你的名字是Dan"
3043 else
3044 print "我不认识你,你的名字是#{name}"
3045```
3046
3047</YueDisplay>
3048
3049&emsp;&emsp;switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。 1573&emsp;&emsp;switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。
3050 1574
3051&emsp;&emsp;switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量: 1575&emsp;&emsp;switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量:
@@ -3061,21 +1585,6 @@ next_number = switch b
3061 error "数字数得太大了!" 1585 error "数字数得太大了!"
3062``` 1586```
3063 1587
3064<YueDisplay>
3065
3066```yue
3067b = 1
3068next_number = switch b
3069 when 1
3070 2
3071 when 2
3072 3
3073 else
3074 error "数字数得太大了!"
3075```
3076
3077</YueDisplay>
3078
3079&emsp;&emsp;我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。 1588&emsp;&emsp;我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。
3080 1589
3081```yuescript 1590```yuescript
@@ -3085,17 +1594,6 @@ msg = switch math.random(1, 5)
3085 else "不太幸运" 1594 else "不太幸运"
3086``` 1595```
3087 1596
3088<YueDisplay>
3089
3090```yue
3091msg = switch math.random(1, 5)
3092 when 1 then "你很幸运"
3093 when 2 then "你差点很幸运"
3094 else "不太幸运"
3095```
3096
3097</YueDisplay>
3098
3099&emsp;&emsp;如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。 1597&emsp;&emsp;如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。
3100 1598
3101```yuescript 1599```yuescript
@@ -3111,23 +1609,6 @@ else
3111 print "不太幸运" 1609 print "不太幸运"
3112``` 1610```
3113 1611
3114<YueDisplay>
3115
3116```yue
3117switch math.random(1, 5)
3118 when 1
3119 print "你很幸运" -- 两个缩进级别
3120 else
3121 print "不太幸运"
3122
3123switch math.random(1, 5) when 1
3124 print "你很幸运" -- 一个缩进级别
3125else
3126 print "不太幸运"
3127```
3128
3129</YueDisplay>
3130
3131&emsp;&emsp;值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。 1612&emsp;&emsp;值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。
3132 1613
3133## 表格匹配 1614## 表格匹配
@@ -3149,25 +1630,6 @@ for item in *items
3149 print "尺寸 #{width}, #{height}" 1630 print "尺寸 #{width}, #{height}"
3150``` 1631```
3151 1632
3152<YueDisplay>
3153
3154```yue
3155items =
3156 * x: 100
3157 y: 200
3158 * width: 300
3159 height: 400
3160
3161for item in *items
3162 switch item
3163 when :x, :y
3164 print "Vec2 #{x}, #{y}"
3165 when :width, :height
3166 print "尺寸 #{width}, #{height}"
3167```
3168
3169</YueDisplay>
3170
3171&emsp;&emsp;你可以使用默认值来选择性地解构表格的某些字段。 1633&emsp;&emsp;你可以使用默认值来选择性地解构表格的某些字段。
3172 1634
3173```yuescript 1635```yuescript
@@ -3180,20 +1642,6 @@ switch item
3180 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过 1642 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3181``` 1643```
3182 1644
3183<YueDisplay>
3184
3185```yue
3186item = {}
3187
3188{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
3189
3190switch item
3191 when {pos: {:x = 50, :y = 200}}
3192 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3193```
3194
3195</YueDisplay>
3196
3197&emsp;&emsp;你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。 1645&emsp;&emsp;你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3198 1646
3199&emsp;&emsp;匹配数组元素。 1647&emsp;&emsp;匹配数组元素。
@@ -3208,20 +1656,6 @@ switch tb
3208 print "1, 2, #{b}" 1656 print "1, 2, #{b}"
3209``` 1657```
3210 1658
3211<YueDisplay>
3212
3213```yue
3214switch tb
3215 when [1, 2, 3]
3216 print "1, 2, 3"
3217 when [1, b, 3]
3218 print "1, #{b}, 3"
3219 when [1, 2, b = 3] -- 变量b有默认值
3220 print "1, 2, #{b}"
3221```
3222
3223</YueDisplay>
3224
3225&emsp;&emsp;匹配表格字段。 1659&emsp;&emsp;匹配表格字段。
3226 1660
3227```yuescript 1661```yuescript
@@ -3234,20 +1668,6 @@ switch tb
3234 print "无效值" 1668 print "无效值"
3235``` 1669```
3236 1670
3237<YueDisplay>
3238
3239```yue
3240switch tb
3241 when success: true, :result
3242 print "成功", result
3243 when success: false
3244 print "失败", result
3245 else
3246 print "无效值"
3247```
3248
3249</YueDisplay>
3250
3251&emsp;&emsp;匹配嵌套的表格结构。 1671&emsp;&emsp;匹配嵌套的表格结构。
3252 1672
3253```yuescript 1673```yuescript
@@ -3260,20 +1680,6 @@ switch tb
3260 print "无效值" 1680 print "无效值"
3261``` 1681```
3262 1682
3263<YueDisplay>
3264
3265```yue
3266switch tb
3267 when data: {type: "success", :content}
3268 print "成功", content
3269 when data: {type: "error", :content}
3270 print "失败", content
3271 else
3272 print "无效值"
3273```
3274
3275</YueDisplay>
3276
3277&emsp;&emsp;匹配表格数组。 1683&emsp;&emsp;匹配表格数组。
3278 1684
3279```yuescript 1685```yuescript
@@ -3287,21 +1693,6 @@ switch tb
3287 print "匹配成功", fourth 1693 print "匹配成功", fourth
3288``` 1694```
3289 1695
3290<YueDisplay>
3291
3292```yue
3293switch tb
3294 when [
3295 {a: 1, b: 2}
3296 {a: 3, b: 4}
3297 {a: 5, b: 6}
3298 fourth
3299 ]
3300 print "匹配成功", fourth
3301```
3302
3303</YueDisplay>
3304
3305&emsp;&emsp;匹配一个列表并捕获特定范围内的元素。 1696&emsp;&emsp;匹配一个列表并捕获特定范围内的元素。
3306 1697
3307```yuescript 1698```yuescript
@@ -3313,19 +1704,6 @@ switch segments
3313 print "Action:", action -- 打印: "view" 1704 print "Action:", action -- 打印: "view"
3314``` 1705```
3315 1706
3316<YueDisplay>
3317
3318```yue
3319segments = ["admin", "users", "logs", "view"]
3320switch segments
3321 when [...groups, resource, action]
3322 print "Group:", groups -- 打印: {"admin", "users"}
3323 print "Resource:", resource -- 打印: "logs"
3324 print "Action:", action -- 打印: "view"
3325```
3326
3327</YueDisplay>
3328
3329# while 循环 1707# while 循环
3330 1708
3331&emsp;&emsp;在月之脚本中的 while 循环支持几种不同的写法: 1709&emsp;&emsp;在月之脚本中的 while 循环支持几种不同的写法:
@@ -3339,19 +1717,6 @@ while i > 0
3339while running == true do my_function! 1717while running == true do my_function!
3340``` 1718```
3341 1719
3342<YueDisplay>
3343
3344```yue
3345i = 10
3346while i > 0
3347 print i
3348 i -= 1
3349
3350while running == true do my_function!
3351```
3352
3353</YueDisplay>
3354
3355```yuescript 1720```yuescript
3356i = 10 1721i = 10
3357until i == 0 1722until i == 0
@@ -3361,18 +1726,6 @@ until i == 0
3361until running == false do my_function! 1726until running == false do my_function!
3362``` 1727```
3363 1728
3364<YueDisplay>
3365
3366```yue
3367i = 10
3368until i == 0
3369 print i
3370 i -= 1
3371until running == false do my_function!
3372```
3373
3374</YueDisplay>
3375
3376&emsp;&emsp;像 for 循环的语法一样,while 循环也可以作为一个表达式使用。while / until 循环表达式支持 `break` 返回多个值。 1729&emsp;&emsp;像 for 循环的语法一样,while 循环也可以作为一个表达式使用。while / until 循环表达式支持 `break` 返回多个值。
3377 1730
3378```yuescript 1731```yuescript
@@ -3381,16 +1734,6 @@ value, doubled = while true
3381 break n, n * 2 if n > 10 1734 break n, n * 2 if n > 10
3382``` 1735```
3383 1736
3384<YueDisplay>
3385
3386```yue
3387value, doubled = while true
3388 n = get_next!
3389 break n, n * 2 if n > 10
3390```
3391
3392</YueDisplay>
3393
3394&emsp;&emsp;为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。 1737&emsp;&emsp;为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。
3395 1738
3396## repeat 循环 1739## repeat 循环
@@ -3405,18 +1748,6 @@ repeat
3405until i == 0 1748until i == 0
3406``` 1749```
3407 1750
3408<YueDisplay>
3409
3410```yue
3411i = 10
3412repeat
3413 print i
3414 i -= 1
3415until i == 0
3416```
3417
3418</YueDisplay>
3419
3420&emsp;&emsp;repeat 循环表达式同样支持 `break` 返回多个值: 1751&emsp;&emsp;repeat 循环表达式同样支持 `break` 返回多个值:
3421 1752
3422```yuescript 1753```yuescript
@@ -3427,18 +1758,6 @@ value, scaled = repeat
3427until false 1758until false
3428``` 1759```
3429 1760
3430<YueDisplay>
3431
3432```yue
3433i = 1
3434value, scaled = repeat
3435 break i, i * 100 if i > 3
3436 i += 1
3437until false
3438```
3439
3440</YueDisplay>
3441
3442# 函数存根 1761# 函数存根
3443 1762
3444&emsp;&emsp;在编程中,将对象的方法作为函数类型的值进行传递是一种常见做法,尤其是在将实例方法作为回调函数传递给其他函数的情形中。当目标函数需要将该对象作为其第一个参数时,我们需要找到一种方式将对象和函数绑定在一起,以便能够正确地调用该函数。 1763&emsp;&emsp;在编程中,将对象的方法作为函数类型的值进行传递是一种常见做法,尤其是在将实例方法作为回调函数传递给其他函数的情形中。当目标函数需要将该对象作为其第一个参数时,我们需要找到一种方式将对象和函数绑定在一起,以便能够正确地调用该函数。
@@ -3466,29 +1785,6 @@ run_callback my_object.write
3466run_callback my_object\write 1785run_callback my_object\write
3467``` 1786```
3468 1787
3469<YueDisplay>
3470
3471```yue
3472my_object = {
3473 value: 1000
3474 write: => print "值为:", @value
3475}
3476
3477run_callback = (func) ->
3478 print "运行回调..."
3479 func!
3480
3481-- 这样写不起作用:
3482-- 函数没有引用my_object
3483run_callback my_object.write
3484
3485-- 函数存根语法
3486-- 让我们把对象捆绑到一个新函数中
3487run_callback my_object\write
3488```
3489
3490</YueDisplay>
3491
3492# 反向回调 1788# 反向回调
3493 1789
3494&emsp;&emsp;反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。 1790&emsp;&emsp;反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。
@@ -3498,15 +1794,6 @@ x <- f
3498print "hello" .. x 1794print "hello" .. x
3499``` 1795```
3500 1796
3501<YueDisplay>
3502
3503```yue
3504x <- f
3505print "hello" .. x
3506```
3507
3508</YueDisplay>
3509
3510&emsp;&emsp;月之脚本也提供了粗箭头反向回调函数。 1797&emsp;&emsp;月之脚本也提供了粗箭头反向回调函数。
3511 1798
3512```yuescript 1799```yuescript
@@ -3514,15 +1801,6 @@ print "hello" .. x
3514print @value 1801print @value
3515``` 1802```
3516 1803
3517<YueDisplay>
3518
3519```yue
3520<= f
3521print @value
3522```
3523
3524</YueDisplay>
3525
3526&emsp;&emsp;你可以通过一个占位符指定回调函数的传参位置。 1804&emsp;&emsp;你可以通过一个占位符指定回调函数的传参位置。
3527 1805
3528```yuescript 1806```yuescript
@@ -3530,15 +1808,6 @@ print @value
3530x * 2 1808x * 2
3531``` 1809```
3532 1810
3533<YueDisplay>
3534
3535```yue
3536(x) <- map _, [1, 2, 3]
3537x * 2
3538```
3539
3540</YueDisplay>
3541
3542&emsp;&emsp;如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。 1811&emsp;&emsp;如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
3543 1812
3544```yuescript 1813```yuescript
@@ -3550,19 +1819,6 @@ result, msg = do
3550print result, msg 1819print result, msg
3551``` 1820```
3552 1821
3553<YueDisplay>
3554
3555```yue
3556result, msg = do
3557 data <- readAsync "文件名.txt"
3558 print data
3559 info <- processAsync data
3560 check info
3561print result, msg
3562```
3563
3564</YueDisplay>
3565
3566# 函数字面量 1822# 函数字面量
3567 1823
3568&emsp;&emsp;所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。 1824&emsp;&emsp;所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。
@@ -3572,15 +1828,6 @@ my_function = ->
3572my_function() -- 调用空函数 1828my_function() -- 调用空函数
3573``` 1829```
3574 1830
3575<YueDisplay>
3576
3577```yue
3578my_function = ->
3579my_function() -- 调用空函数
3580```
3581
3582</YueDisplay>
3583
3584&emsp;&emsp;函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句: 1831&emsp;&emsp;函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句:
3585 1832
3586```yuescript 1833```yuescript
@@ -3591,18 +1838,6 @@ func_b = ->
3591 print "这个值是:", value 1838 print "这个值是:", value
3592``` 1839```
3593 1840
3594<YueDisplay>
3595
3596```yue
3597func_a = -> print "你好,世界"
3598
3599func_b = ->
3600 value = 100
3601 print "这个值是:", value
3602```
3603
3604</YueDisplay>
3605
3606&emsp;&emsp;如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。 1841&emsp;&emsp;如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。
3607 1842
3608```yuescript 1843```yuescript
@@ -3610,29 +1845,12 @@ func_a!
3610func_b() 1845func_b()
3611``` 1846```
3612 1847
3613<YueDisplay>
3614
3615```yue
3616func_a!
3617func_b()
3618```
3619
3620</YueDisplay>
3621
3622&emsp;&emsp;带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建: 1848&emsp;&emsp;带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建:
3623 1849
3624```yuescript 1850```yuescript
3625sum = (x, y) -> print "数字的和", x + y 1851sum = (x, y) -> print "数字的和", x + y
3626``` 1852```
3627 1853
3628<YueDisplay>
3629
3630```yue
3631sum = (x, y) -> print "数字的和", x + y
3632```
3633
3634</YueDisplay>
3635
3636&emsp;&emsp;函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。 1854&emsp;&emsp;函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。
3637 1855
3638```yuescript 1856```yuescript
@@ -3642,31 +1860,12 @@ print sum 10, 20
3642a b c "a", "b", "c" 1860a b c "a", "b", "c"
3643``` 1861```
3644 1862
3645<YueDisplay>
3646
3647```yue
3648sum 10, 20
3649print sum 10, 20
3650
3651a b c "a", "b", "c"
3652```
3653
3654</YueDisplay>
3655
3656&emsp;&emsp;为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。 1863&emsp;&emsp;为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。
3657 1864
3658```yuescript 1865```yuescript
3659print "x:", sum(10, 20), "y:", sum(30, 40) 1866print "x:", sum(10, 20), "y:", sum(30, 40)
3660``` 1867```
3661 1868
3662<YueDisplay>
3663
3664```yue
3665print "x:", sum(10, 20), "y:", sum(30, 40)
3666```
3667
3668</YueDisplay>
3669
3670&emsp;&emsp;注意:函数名与开始括号之间不能有任何空格。 1869&emsp;&emsp;注意:函数名与开始括号之间不能有任何空格。
3671 1870
3672&emsp;&emsp;函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回: 1871&emsp;&emsp;函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回:
@@ -3676,29 +1875,12 @@ sum = (x, y) -> x + y
3676print "数字的和是", sum 10, 20 1875print "数字的和是", sum 10, 20
3677``` 1876```
3678 1877
3679<YueDisplay>
3680
3681```yue
3682sum = (x, y) -> x + y
3683print "数字的和是", sum 10, 20
3684```
3685
3686</YueDisplay>
3687
3688&emsp;&emsp;如果你需要做显式返回,可以使用 return 关键字: 1878&emsp;&emsp;如果你需要做显式返回,可以使用 return 关键字:
3689 1879
3690```yuescript 1880```yuescript
3691sum = (x, y) -> return x + y 1881sum = (x, y) -> return x + y
3692``` 1882```
3693 1883
3694<YueDisplay>
3695
3696```yue
3697sum = (x, y) -> return x + y
3698```
3699
3700</YueDisplay>
3701
3702&emsp;&emsp;就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表: 1884&emsp;&emsp;就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表:
3703 1885
3704```yuescript 1886```yuescript
@@ -3706,15 +1888,6 @@ mystery = (x, y) -> x + y, x - y
3706a, b = mystery 10, 20 1888a, b = mystery 10, 20
3707``` 1889```
3708 1890
3709<YueDisplay>
3710
3711```yue
3712mystery = (x, y) -> x + y, x - y
3713a, b = mystery 10, 20
3714```
3715
3716</YueDisplay>
3717
3718## 粗箭头 1891## 粗箭头
3719 1892
3720&emsp;&emsp;因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。 1893&emsp;&emsp;因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。
@@ -3723,14 +1896,6 @@ a, b = mystery 10, 20
3723func = (num) => @value + num 1896func = (num) => @value + num
3724``` 1897```
3725 1898
3726<YueDisplay>
3727
3728```yue
3729func = (num) => @value + num
3730```
3731
3732</YueDisplay>
3733
3734## 参数默认值 1899## 参数默认值
3735 1900
3736&emsp;&emsp;可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。 1901&emsp;&emsp;可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。
@@ -3741,16 +1906,6 @@ my_function = (name = "某物", height = 100) ->
3741 print "我的高度是", height 1906 print "我的高度是", height
3742``` 1907```
3743 1908
3744<YueDisplay>
3745
3746```yue
3747my_function = (name = "某物", height = 100) ->
3748 print "你好,我是", name
3749 print "我的高度是", height
3750```
3751
3752</YueDisplay>
3753
3754&emsp;&emsp;函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。 1909&emsp;&emsp;函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。
3755 1910
3756```yuescript 1911```yuescript
@@ -3758,15 +1913,6 @@ some_args = (x = 100, y = x + 1000) ->
3758 print x + y 1913 print x + y
3759``` 1914```
3760 1915
3761<YueDisplay>
3762
3763```yue
3764some_args = (x = 100, y = x + 1000) ->
3765 print x + y
3766```
3767
3768</YueDisplay>
3769
3770## 注意事项 1916## 注意事项
3771 1917
3772&emsp;&emsp;由于月之脚本支持无需括号的表达式式函数调用,因此为了避免因空白字符造成的解析歧义,需要进行一些限制。 1918&emsp;&emsp;由于月之脚本支持无需括号的表达式式函数调用,因此为了避免因空白字符造成的解析歧义,需要进行一些限制。
@@ -3780,17 +1926,6 @@ c = x -y
3780d = x- z 1926d = x- z
3781``` 1927```
3782 1928
3783<YueDisplay>
3784
3785```yue
3786a = x - 10
3787b = x-10
3788c = x -y
3789d = x- z
3790```
3791
3792</YueDisplay>
3793
3794&emsp;&emsp;当函数调用的第一个参数是字符串字面量时,可以通过空白控制其优先级。在 Lua 中,常见的写法是调用仅有一个字符串或表字面量参数的函数时省略括号。 1929&emsp;&emsp;当函数调用的第一个参数是字符串字面量时,可以通过空白控制其优先级。在 Lua 中,常见的写法是调用仅有一个字符串或表字面量参数的函数时省略括号。
3795 1930
3796&emsp;&emsp;当变量名和字符串字面量之间没有空格时,函数的调用优先级高于后续表达式,因此此时无法再传入其他参数。 1931&emsp;&emsp;当变量名和字符串字面量之间没有空格时,函数的调用优先级高于后续表达式,因此此时无法再传入其他参数。
@@ -3802,15 +1937,6 @@ x = func"hello" + 100
3802y = func "hello" + 100 1937y = func "hello" + 100
3803``` 1938```
3804 1939
3805<YueDisplay>
3806
3807```yue
3808x = func"hello" + 100
3809y = func "hello" + 100
3810```
3811
3812</YueDisplay>
3813
3814## 多行参数 1940## 多行参数
3815 1941
3816&emsp;&emsp;当调用接收大量参数的函数时,将参数列表分成多行是很方便的。由于月之脚本语言对空白字符的敏感性,做参数列表的分割时务必要小心。 1942&emsp;&emsp;当调用接收大量参数的函数时,将参数列表分成多行是很方便的。由于月之脚本语言对空白字符的敏感性,做参数列表的分割时务必要小心。
@@ -3827,20 +1953,6 @@ cool_func 1, 2,
3827 7, 8 1953 7, 8
3828``` 1954```
3829 1955
3830<YueDisplay>
3831
3832```yue
3833my_func 5, 4, 3,
3834 8, 9, 10
3835
3836cool_func 1, 2,
3837 3, 4,
3838 5, 6,
3839 7, 8
3840```
3841
3842</YueDisplay>
3843
3844&emsp;&emsp;这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。 1956&emsp;&emsp;这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。
3845 1957
3846```yuescript 1958```yuescript
@@ -3850,17 +1962,6 @@ my_func 5, 6, 7,
3850 5, 4 1962 5, 4
3851``` 1963```
3852 1964
3853<YueDisplay>
3854
3855```yue
3856my_func 5, 6, 7,
3857 6, another_func 6, 7, 8,
3858 9, 1, 2,
3859 5, 4
3860```
3861
3862</YueDisplay>
3863
3864&emsp;&emsp;因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。 1965&emsp;&emsp;因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。
3865 1966
3866```yuescript 1967```yuescript
@@ -3871,18 +1972,6 @@ x = [
3871] 1972]
3872``` 1973```
3873 1974
3874<YueDisplay>
3875
3876```yue
3877x = [
3878 1, 2, 3, 4, a_func 4, 5,
3879 5, 6,
3880 8, 9, 10
3881]
3882```
3883
3884</YueDisplay>
3885
3886&emsp;&emsp;有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。 1975&emsp;&emsp;有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。
3887 1976
3888```yuescript 1977```yuescript
@@ -3892,17 +1981,6 @@ y = [ my_func 1, 2, 3,
3892] 1981]
3893``` 1982```
3894 1983
3895<YueDisplay>
3896
3897```yue
3898y = [ my_func 1, 2, 3,
3899 4, 5,
3900 5, 6, 7
3901]
3902```
3903
3904</YueDisplay>
3905
3906&emsp;&emsp;对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句: 1984&emsp;&emsp;对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句:
3907 1985
3908```yuescript 1986```yuescript
@@ -3919,24 +1997,6 @@ if func 1, 2, 3,
3919 print "我在if内部" 1997 print "我在if内部"
3920``` 1998```
3921 1999
3922<YueDisplay>
3923
3924```yue
3925if func 1, 2, 3,
3926 "你好",
3927 "世界"
3928 print "你好"
3929 print "我在if内部"
3930
3931if func 1, 2, 3,
3932 "你好",
3933 "世界"
3934 print "你好"
3935 print "我在if内部"
3936```
3937
3938</YueDisplay>
3939
3940## 参数解构 2000## 参数解构
3941 2001
3942&emsp;&emsp;月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量: 2002&emsp;&emsp;月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量:
@@ -3958,23 +2018,6 @@ arg1 = {a: 0}
3958f2 arg1, arg2 2018f2 arg1, arg2
3959``` 2019```
3960 2020
3961<YueDisplay>
3962
3963```yue
3964f1 = (:a, :b, :c) ->
3965 print a, b, c
3966
3967f1 a: 1, b: "2", c: {}
3968
3969f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
3970 print a1, b, c
3971
3972arg1 = {a: 0}
3973f2 arg1, arg2
3974```
3975
3976</YueDisplay>
3977
3978## 前置返回表达式 2021## 前置返回表达式
3979 2022
3980&emsp;&emsp;在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下: 2023&emsp;&emsp;在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
@@ -3988,19 +2031,6 @@ findFirstEven = (list): nil ->
3988 return sub 2031 return sub
3989``` 2032```
3990 2033
3991<YueDisplay>
3992
3993```yue
3994findFirstEven = (list): nil ->
3995 for item in *list
3996 if type(item) == "table"
3997 for sub in *item
3998 if sub % 2 == 0
3999 return sub
4000```
4001
4002</YueDisplay>
4003
4004&emsp;&emsp;这个写法等价于: 2034&emsp;&emsp;这个写法等价于:
4005 2035
4006```yuescript 2036```yuescript
@@ -4013,20 +2043,6 @@ findFirstEven = (list) ->
4013 nil 2043 nil
4014``` 2044```
4015 2045
4016<YueDisplay>
4017
4018```yue
4019findFirstEven = (list) ->
4020 for item in *list
4021 if type(item) == "table"
4022 for sub in *item
4023 if sub % 2 == 0
4024 return sub
4025 nil
4026```
4027
4028</YueDisplay>
4029
4030&emsp;&emsp;唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。 2046&emsp;&emsp;唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。
4031 2047
4032## 命名变长参数 2048## 命名变长参数
@@ -4055,32 +2071,6 @@ process = (...args) ->
4055process 1, nil, 3, nil, 5 2071process 1, nil, 3, nil, 5
4056``` 2072```
4057 2073
4058<YueDisplay>
4059
4060```yue
4061f = (...t) ->
4062 print "参数个数:", t.n
4063 print "表长度:", #t
4064 for i = 1, t.n
4065 print t[i]
4066
4067f 1, 2, 3
4068f "a", "b", "c", "d"
4069f!
4070
4071-- 处理包含 nil 的情况
4072process = (...args) ->
4073 sum = 0
4074 for i = 1, args.n
4075 if args[i] != nil and type(args[i]) == "number"
4076 sum += args[i]
4077 sum
4078
4079process 1, nil, 3, nil, 5
4080```
4081
4082</YueDisplay>
4083
4084# 空白 2074# 空白
4085 2075
4086&emsp;&emsp;月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 2076&emsp;&emsp;月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
@@ -4093,14 +2083,6 @@ process 1, nil, 3, nil, 5
4093a = 1; b = 2; print a + b 2083a = 1; b = 2; print a + b
4094``` 2084```
4095 2085
4096<YueDisplay>
4097
4098```yue
4099a = 1; b = 2; print a + b
4100```
4101
4102</YueDisplay>
4103
4104## 多行链式调用 2086## 多行链式调用
4105 2087
4106&emsp;&emsp;你可以使用相同的缩进来编写多行链式函数调用。 2088&emsp;&emsp;你可以使用相同的缩进来编写多行链式函数调用。
@@ -4114,19 +2096,6 @@ Rx.Observable
4114 \subscribe print 2096 \subscribe print
4115``` 2097```
4116 2098
4117<YueDisplay>
4118
4119```yue
4120Rx.Observable
4121 .fromRange 1, 8
4122 \filter (x) -> x % 2 == 0
4123 \concat Rx.Observable.of 'who do we appreciate'
4124 \map (value) -> value .. '!'
4125 \subscribe print
4126```
4127
4128</YueDisplay>
4129
4130# 注释 2099# 注释
4131 2100
4132```yuescript 2101```yuescript
@@ -4142,23 +2111,6 @@ str = --[[
4142func --[[端口]] 3000, --[[ip]] "192.168.1.1" 2111func --[[端口]] 3000, --[[ip]] "192.168.1.1"
4143``` 2112```
4144 2113
4145<YueDisplay>
4146
4147```yue
4148-- 我是一个注释
4149
4150str = --[[
4151这是一个多行注释。
4152没问题。
4153]] strA \ -- 注释 1
4154 .. strB \ -- 注释 2
4155 .. strC
4156
4157func --[[端口]] 3000, --[[ip]] "192.168.1.1"
4158```
4159
4160</YueDisplay>
4161
4162# 属性 2114# 属性
4163 2115
4164&emsp;&emsp;月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。 2116&emsp;&emsp;月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。
@@ -4168,15 +2120,6 @@ const a = 123
4168close _ = <close>: -> print "超出范围。" 2120close _ = <close>: -> print "超出范围。"
4169``` 2121```
4170 2122
4171<YueDisplay>
4172
4173```yue
4174const a = 123
4175close _ = <close>: -> print "超出范围。"
4176```
4177
4178</YueDisplay>
4179
4180&emsp;&emsp;你可以对进行解构得到的变量标记为常量。 2123&emsp;&emsp;你可以对进行解构得到的变量标记为常量。
4181 2124
4182```yuescript 2125```yuescript
@@ -4184,15 +2127,6 @@ const {:a, :b, c, d} = tb
4184-- a = 1 2127-- a = 1
4185``` 2128```
4186 2129
4187<YueDisplay>
4188
4189```yue
4190const {:a, :b, c, d} = tb
4191-- a = 1
4192```
4193
4194</YueDisplay>
4195
4196&emsp;&emsp;你也可以声明全局变量为常量。 2130&emsp;&emsp;你也可以声明全局变量为常量。
4197 2131
4198```yuescript 2132```yuescript
@@ -4200,15 +2134,6 @@ global const Constant = 123
4200-- Constant = 1 2134-- Constant = 1
4201``` 2135```
4202 2136
4203<YueDisplay>
4204
4205```yue
4206global const Constant = 123
4207-- Constant = 1
4208```
4209
4210</YueDisplay>
4211
4212# 操作符 2137# 操作符
4213 2138
4214&emsp;&emsp;Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 2139&emsp;&emsp;Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
@@ -4218,15 +2143,6 @@ tb\func! if tb ~= nil
4218tb::func! if tb != nil 2143tb::func! if tb != nil
4219``` 2144```
4220 2145
4221<YueDisplay>
4222
4223```yue
4224tb\func! if tb ~= nil
4225tb::func! if tb != nil
4226```
4227
4228</YueDisplay>
4229
4230## 链式比较 2146## 链式比较
4231 2147
4232&emsp;&emsp;你可以在月之脚本中进行比较表达式的链式书写: 2148&emsp;&emsp;你可以在月之脚本中进行比较表达式的链式书写:
@@ -4240,19 +2156,6 @@ print 1 <= a <= 10
4240-- 输出:true 2156-- 输出:true
4241``` 2157```
4242 2158
4243<YueDisplay>
4244
4245```yue
4246print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
4247-- 输出:true
4248
4249a = 5
4250print 1 <= a <= 10
4251-- 输出:true
4252```
4253
4254</YueDisplay>
4255
4256&emsp;&emsp;可以注意一下链式比较表达式的求值行为: 2159&emsp;&emsp;可以注意一下链式比较表达式的求值行为:
4257 2160
4258```yuescript 2161```yuescript
@@ -4278,33 +2181,6 @@ print v(1) > v(2) <= v(3)
4278]] 2181]]
4279``` 2182```
4280 2183
4281<YueDisplay>
4282
4283```yue
4284v = (x) ->
4285 print x
4286 x
4287
4288print v(1) < v(2) <= v(3)
4289--[[
4290 输出:
4291 2
4292 1
4293 3
4294 true
4295]]
4296
4297print v(1) > v(2) <= v(3)
4298--[[
4299 输出:
4300 2
4301 1
4302 false
4303]]
4304```
4305
4306</YueDisplay>
4307
4308&emsp;&emsp;在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。 2184&emsp;&emsp;在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。
4309 2185
4310## 表追加 2186## 表追加
@@ -4316,15 +2192,6 @@ tab = []
4316tab[] = "Value" 2192tab[] = "Value"
4317``` 2193```
4318 2194
4319<YueDisplay>
4320
4321```yue
4322tab = []
4323tab[] = "Value"
4324```
4325
4326</YueDisplay>
4327
4328&emsp;&emsp;你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中: 2195&emsp;&emsp;你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
4329 2196
4330```yuescript 2197```yuescript
@@ -4334,17 +2201,6 @@ tbA[] = ...tbB
4334-- tbA 现在为 [1, 2, 3, 4, 5, 6] 2201-- tbA 现在为 [1, 2, 3, 4, 5, 6]
4335``` 2202```
4336 2203
4337<YueDisplay>
4338
4339```yue
4340tbA = [1, 2, 3]
4341tbB = [4, 5, 6]
4342tbA[] = ...tbB
4343-- tbA 现在为 [1, 2, 3, 4, 5, 6]
4344```
4345
4346</YueDisplay>
4347
4348## 表扩展 2204## 表扩展
4349 2205
4350&emsp;&emsp;你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。 2206&emsp;&emsp;你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。
@@ -4366,27 +2222,6 @@ b = {4, 5, y: 1}
4366merge = {...a, ...b} 2222merge = {...a, ...b}
4367``` 2223```
4368 2224
4369<YueDisplay>
4370
4371```yue
4372parts =
4373 * "shoulders"
4374 * "knees"
4375lyrics =
4376 * "head"
4377 * ...parts
4378 * "and"
4379 * "toes"
4380
4381copy = {...other}
4382
4383a = {1, 2, 3, x: 1}
4384b = {4, 5, y: 1}
4385merge = {...a, ...b}
4386```
4387
4388</YueDisplay>
4389
4390## 表反向索引 2225## 表反向索引
4391 2226
4392&emsp;&emsp;你可以使用 **#** 操作符来反向索引表中的元素。 2227&emsp;&emsp;你可以使用 **#** 操作符来反向索引表中的元素。
@@ -4397,16 +2232,6 @@ second_last = data.items[#-1]
4397data.items[#] = 1 2232data.items[#] = 1
4398``` 2233```
4399 2234
4400<YueDisplay>
4401
4402```yue
4403last = data.items[#]
4404second_last = data.items[#-1]
4405data.items[#] = 1
4406```
4407
4408</YueDisplay>
4409
4410## 元表 2235## 元表
4411 2236
4412&emsp;&emsp;**<>** 操作符可提供元表操作的快捷方式。 2237&emsp;&emsp;**<>** 操作符可提供元表操作的快捷方式。
@@ -4431,26 +2256,6 @@ print d.value
4431close _ = <close>: -> print "超出范围" 2256close _ = <close>: -> print "超出范围"
4432``` 2257```
4433 2258
4434<YueDisplay>
4435
4436```yue
4437mt = {}
4438add = (right) => <>: mt, value: @value + right.value
4439mt.__add = add
4440
4441a = <>: mt, value: 1
4442-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
4443b = :<add>, value: 2
4444c = <add>: mt.__add, value: 3
4445
4446d = a + b + c
4447print d.value
4448
4449close _ = <close>: -> print "超出范围"
4450```
4451
4452</YueDisplay>
4453
4454### 元表访问 2259### 元表访问
4455 2260
4456&emsp;&emsp;使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 2261&emsp;&emsp;使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
@@ -4465,19 +2270,6 @@ tb.<> = __index: {item: "hello"}
4465print tb.item 2270print tb.item
4466``` 2271```
4467 2272
4468<YueDisplay>
4469
4470```yue
4471-- 使用包含字段 "value" 的元表创建
4472tb = <"value">: 123
4473tb.<index> = tb.<>
4474print tb.value
4475tb.<> = __index: {item: "hello"}
4476print tb.item
4477```
4478
4479</YueDisplay>
4480
4481### 元表解构 2273### 元表解构
4482 2274
4483&emsp;&emsp;使用被 **<>** 包围的元方法键解构元表。 2275&emsp;&emsp;使用被 **<>** 包围的元方法键解构元表。
@@ -4487,15 +2279,6 @@ print tb.item
4487print item, new, close, getter 2279print item, new, close, getter
4488``` 2280```
4489 2281
4490<YueDisplay>
4491
4492```yue
4493{item, :new, :<close>, <index>: getter} = tb
4494print item, new, close, getter
4495```
4496
4497</YueDisplay>
4498
4499## 存在性 2282## 存在性
4500 2283
4501&emsp;&emsp;**?** 运算符可以在多种上下文中用来检查存在性。 2284&emsp;&emsp;**?** 运算符可以在多种上下文中用来检查存在性。
@@ -4515,25 +2298,6 @@ with? io.open "test.txt", "w"
4515 \close! 2298 \close!
4516``` 2299```
4517 2300
4518<YueDisplay>
4519
4520```yue
4521func?!
4522print abc?["你好 世界"]?.xyz
4523
4524x = tab?.value
4525len = utf8?.len or string?.len or (o) -> #o
4526
4527if print and x?
4528 print x
4529
4530with? io.open "test.txt", "w"
4531 \write "你好"
4532 \close!
4533```
4534
4535</YueDisplay>
4536
4537## 管道 2301## 管道
4538 2302
4539&emsp;&emsp;与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。 2303&emsp;&emsp;与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。
@@ -4552,24 +2316,6 @@ readFile "example.txt"
4552 |> print 2316 |> print
4553``` 2317```
4554 2318
4555<YueDisplay>
4556
4557```yue
4558"你好" |> print
45591 |> print 2 -- 将管道项作为第一个参数插入
45602 |> print 1, _, 3 -- 带有占位符的管道
4561
4562-- 多行的管道表达式
4563readFile "example.txt"
4564 |> extract language, {}
4565 |> parse language
4566 |> emit
4567 |> render
4568 |> print
4569```
4570
4571</YueDisplay>
4572
4573## 空值合并 2319## 空值合并
4574 2320
4575&emsp;&emsp;如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。 2321&emsp;&emsp;如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。
@@ -4582,17 +2328,6 @@ func a ?? {}
4582a ??= false 2328a ??= false
4583``` 2329```
4584 2330
4585<YueDisplay>
4586
4587```yue
4588local a, b, c, d
4589a = b ?? c ?? d
4590func a ?? {}
4591a ??= false
4592```
4593
4594</YueDisplay>
4595
4596## 隐式对象 2331## 隐式对象
4597 2332
4598&emsp;&emsp;你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。 2333&emsp;&emsp;你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
@@ -4639,52 +2374,6 @@ tb =
4639 tb: { } 2374 tb: { }
4640``` 2375```
4641 2376
4642<YueDisplay>
4643
4644```yue
4645-- 赋值时使用隐式对象
4646list =
4647 * 1
4648 * 2
4649 * 3
4650
4651-- 函数调用时使用隐式对象
4652func
4653 * 1
4654 * 2
4655 * 3
4656
4657-- 返回时使用隐式对象
4658f = ->
4659 return
4660 * 1
4661 * 2
4662 * 3
4663
4664-- 表格时使用隐式对象
4665tb =
4666 name: "abc"
4667
4668 values:
4669 - "a"
4670 - "b"
4671 - "c"
4672
4673 objects:
4674 - name: "a"
4675 value: 1
4676 func: => @value + 1
4677 tb:
4678 fieldA: 1
4679
4680 - name: "b"
4681 value: 2
4682 func: => @value + 2
4683 tb: { }
4684```
4685
4686</YueDisplay>
4687
4688# 字面量 2377# 字面量
4689 2378
4690&emsp;&emsp;Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。 2379&emsp;&emsp;Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。
@@ -4700,19 +2389,6 @@ some_string = "这是一个字符串
4700print "我有#{math.random! * 100}%的把握。" 2389print "我有#{math.random! * 100}%的把握。"
4701``` 2390```
4702 2391
4703<YueDisplay>
4704
4705```yue
4706some_string = "这是一个字符串
4707 并包括一个换行。"
4708
4709-- 使用#{}语法可以将表达式插入到字符串字面量中。
4710-- 字符串插值只在双引号字符串中可用。
4711print "我有#{math.random! * 100}%的把握。"
4712```
4713
4714</YueDisplay>
4715
4716## 数字字面量 2392## 数字字面量
4717 2393
4718&emsp;&emsp;你可以在数字字面量中使用下划线来增加可读性。 2394&emsp;&emsp;你可以在数字字面量中使用下划线来增加可读性。
@@ -4723,16 +2399,6 @@ hex = 0xEF_BB_BF
4723binary = 0B10011 2399binary = 0B10011
4724``` 2400```
4725 2401
4726<YueDisplay>
4727
4728```yue
4729integer = 1_000_000
4730hex = 0xEF_BB_BF
4731binary = 0B10011
4732```
4733
4734</YueDisplay>
4735
4736## YAML 风格字符串 2402## YAML 风格字符串
4737 2403
4738&emsp;&emsp;使用 `|` 前缀标记一个多行 YAML 风格字符串: 2404&emsp;&emsp;使用 `|` 前缀标记一个多行 YAML 风格字符串:
@@ -4745,18 +2411,6 @@ str = |
4745 - #{expr} 2411 - #{expr}
4746``` 2412```
4747 2413
4748<YueDisplay>
4749
4750```yue
4751str = |
4752 key: value
4753 list:
4754 - item1
4755 - #{expr}
4756```
4757
4758</YueDisplay>
4759
4760&emsp;&emsp;其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。 2414&emsp;&emsp;其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
4761 2415
4762&emsp;&emsp;YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。 2416&emsp;&emsp;YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
@@ -4769,18 +2423,6 @@ fn = ->
4769 return str 2423 return str
4770``` 2424```
4771 2425
4772<YueDisplay>
4773
4774```yue
4775fn = ->
4776 str = |
4777 foo:
4778 bar: baz
4779 return str
4780```
4781
4782</YueDisplay>
4783
4784&emsp;&emsp;输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。 2426&emsp;&emsp;输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
4785 2427
4786&emsp;&emsp;支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义: 2428&emsp;&emsp;支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
@@ -4791,16 +2433,6 @@ str = |
4791 note: 'He said: "#{Hello}!"' 2433 note: 'He said: "#{Hello}!"'
4792``` 2434```
4793 2435
4794<YueDisplay>
4795
4796```yue
4797str = |
4798 path: "C:\Program Files\App"
4799 note: 'He said: "#{Hello}!"'
4800```
4801
4802</YueDisplay>
4803
4804# 模块 2436# 模块
4805 2437
4806## 导入 2438## 导入
@@ -4832,35 +2464,6 @@ do
4832 import "export" as {one, two, Something:{umm:{ch}}} 2464 import "export" as {one, two, Something:{umm:{ch}}}
4833``` 2465```
4834 2466
4835<YueDisplay>
4836
4837```yue
4838-- 用作表解构
4839do
4840 import insert, concat from table
4841 -- 当给 insert, concat 变量赋值时,编译器会报告错误
4842 import C, Ct, Cmt from require "lpeg"
4843 -- 快捷写法引入模块的子项
4844 import x, y, z from 'mymodule'
4845 -- 使用Python风格的导入
4846 from 'module' import a, b, c
4847
4848-- 快捷地导入一个模块
4849do
4850 import 'module'
4851 import 'module_x'
4852 import "d-a-s-h-e-s"
4853 import "module.part"
4854
4855-- 导入模块后起一个别名使用,或是进行导入模块表的解构
4856do
4857 import "player" as PlayerModule
4858 import "lpeg" as :C, :Ct, :Cmt
4859 import "export" as {one, two, Something:{umm:{ch}}}
4860```
4861
4862</YueDisplay>
4863
4864## 导入全局变量 2467## 导入全局变量
4865 2468
4866&emsp;&emsp;你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。 2469&emsp;&emsp;你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。
@@ -4872,17 +2475,6 @@ do
4872 print concat ["a", tostring 1] 2475 print concat ["a", tostring 1]
4873``` 2476```
4874 2477
4875<YueDisplay>
4876
4877```yue
4878do
4879 import tostring
4880 import table.concat
4881 print concat ["a", tostring 1]
4882```
4883
4884</YueDisplay>
4885
4886### 自动全局变量导入 2478### 自动全局变量导入
4887 2479
4888&emsp;&emsp;在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。 2480&emsp;&emsp;在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。
@@ -4904,25 +2496,6 @@ do
4904 FLAG = 123 2496 FLAG = 123
4905``` 2497```
4906 2498
4907<YueDisplay>
4908
4909```yue
4910do
4911 import global
4912 print "hello"
4913 math.random 3
4914 -- print = nil -- 报错:自动导入的全局变量是常量
4915
4916do
4917 -- 被显式声明为全局的变量不会被自动导入
4918 import global
4919 global FLAG
4920 print FLAG
4921 FLAG = 123
4922```
4923
4924</YueDisplay>
4925
4926## 导出 2499## 导出
4927 2500
4928&emsp;&emsp;导出语句提供了一种简洁的方式来定义当前的模块。 2501&emsp;&emsp;导出语句提供了一种简洁的方式来定义当前的模块。
@@ -4947,26 +2520,6 @@ export class Something
4947 umm: "cool" 2520 umm: "cool"
4948``` 2521```
4949 2522
4950<YueDisplay>
4951
4952```yue
4953export a, b, c = 1, 2, 3
4954export cool = "cat"
4955
4956export What = if this
4957 "abc"
4958else
4959 "def"
4960
4961export y = ->
4962 hallo = 3434
4963
4964export class Something
4965 umm: "cool"
4966```
4967
4968</YueDisplay>
4969
4970&emsp;&emsp;使用解构进行命名导出。 2523&emsp;&emsp;使用解构进行命名导出。
4971 2524
4972```yuescript 2525```yuescript
@@ -4974,15 +2527,6 @@ export :loadstring, to_lua: tolua = yue
4974export {itemA: {:fieldA = '默认值'}} = tb 2527export {itemA: {:fieldA = '默认值'}} = tb
4975``` 2528```
4976 2529
4977<YueDisplay>
4978
4979```yue
4980export :loadstring, to_lua: tolua = yue
4981export {itemA: {:fieldA = '默认值'}} = tb
4982```
4983
4984</YueDisplay>
4985
4986&emsp;&emsp;从模块导出命名项目时,可以不用创建局部变量。 2530&emsp;&emsp;从模块导出命名项目时,可以不用创建局部变量。
4987 2531
4988```yuescript 2532```yuescript
@@ -4991,16 +2535,6 @@ export.<index> = items
4991export["a-b-c"] = 123 2535export["a-b-c"] = 123
4992``` 2536```
4993 2537
4994<YueDisplay>
4995
4996```yue
4997export.itemA = tb
4998export.<index> = items
4999export["a-b-c"] = 123
5000```
5001
5002</YueDisplay>
5003
5004### 未命名导出 2538### 未命名导出
5005 2539
5006&emsp;&emsp;未命名导出会将要导出的目标项目添加到导出表的数组部分。 2540&emsp;&emsp;未命名导出会将要导出的目标项目添加到导出表的数组部分。
@@ -5018,23 +2552,6 @@ export with tmp
5018 j = 2000 2552 j = 2000
5019``` 2553```
5020 2554
5021<YueDisplay>
5022
5023```yue
5024d, e, f = 3, 2, 1
5025export d, e, f
5026
5027export if this
5028 123
5029else
5030 456
5031
5032export with tmp
5033 j = 2000
5034```
5035
5036</YueDisplay>
5037
5038### 默认导出 2555### 默认导出
5039 2556
5040&emsp;&emsp;在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 2557&emsp;&emsp;在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
@@ -5045,16 +2562,6 @@ export default ->
5045 123 2562 123
5046``` 2563```
5047 2564
5048<YueDisplay>
5049
5050```yue
5051export default ->
5052 print "你好"
5053 123
5054```
5055
5056</YueDisplay>
5057
5058# MIT 许可证 2565# MIT 许可证
5059 2566
5060版权 (c) 2017-2026 李瑾 \<dragon-fly@qq.com\> 2567版权 (c) 2017-2026 李瑾 \<dragon-fly@qq.com\>