aboutsummaryrefslogtreecommitdiff
path: root/doc/docs/zh/doc/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/docs/zh/doc/README.md')
-rwxr-xr-xdoc/docs/zh/doc/README.md608
1 files changed, 526 insertions, 82 deletions
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 1a2da96..15f4768 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -16,19 +16,29 @@ Yue(月)是中文中“月亮”的名称。
16### 月之脚本概览 16### 月之脚本概览
17```moonscript 17```moonscript
18-- 导入语法 18-- 导入语法
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- 隐式对象 21-- 隐式对象
22inventory = 22inventory =
23 equipment: 23 equipment:
24 * "sword" 24 - "sword"
25 * "shield" 25 - "shield"
26 items: 26 items:
27 * name: "potion" 27 - name: "potion"
28 count: 10 28 count: 10
29 * name: "bread" 29 - name: "bread"
30 count: 3 30 count: 3
31 31
32-- 列表推导
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (arr, init, action): init ->
40 init = action init, item for item in *arr
41
32-- 管道操作符 42-- 管道操作符
33[1, 2, 3] 43[1, 2, 3]
34 |> map (x) -> x * 2 44 |> map (x) -> x * 2
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本"
51<YueDisplay> 61<YueDisplay>
52<pre> 62<pre>
53-- 导入语法 63-- 导入语法
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- 隐式对象 66-- 隐式对象
57inventory = 67inventory =
58 equipment: 68 equipment:
59 * "sword" 69 - "sword"
60 * "shield" 70 - "shield"
61 items: 71 items:
62 * name: "potion" 72 - name: "potion"
63 count: 10 73 count: 10
64 * name: "bread" 74 - name: "bread"
65 count: 3 75 count: 3
66 76
77-- 列表推导
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (arr, init, action): init ->
85 init = action init, item for item in *arr
86
67-- 管道操作符 87-- 管道操作符
68[1, 2, 3] 88[1, 2, 3]
69 |> map (x) -> x * 2 89 |> map (x) -> x * 2
@@ -122,7 +142,7 @@ export 🌛 = "月之脚本"
122 142
123* **下载预编译的二进制程序** 143* **下载预编译的二进制程序**
124 144
125&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。 145&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。
126 146
127&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。 147&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。
128 148
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本"
132 152
133在Lua中使用月之脚本模块: 153在Lua中使用月之脚本模块:
134 154
135* **用法 1** 155* **用法 1**
136在Lua中引入 "你的脚本入口文件.yue"。 156在Lua中引入 "你的脚本入口文件.yue"。
137```Lua 157```Lua
138require("yue")("你的脚本入口文件") 158require("yue")("你的脚本入口文件")
139``` 159```
140当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import**进行脚本引用即可。错误消息中的代码行号也会被正确处理。 160当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import**进行脚本引用即可。错误消息中的代码行号也会被正确处理。
141 161
142* **用法 2** 162* **用法 2**
143手动引入月之脚本模块并重写错误消息来帮助调试。 163手动引入月之脚本模块并重写错误消息来帮助调试。
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **用法 3** 174* **用法 3**
155在Lua中使用月之脚本编译器功能。 175在Lua中使用月之脚本编译器功能。
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
@@ -202,12 +222,12 @@ f!
202 不添加任何选项执行命令可以进入REPL模式, 222 不添加任何选项执行命令可以进入REPL模式,
203 在单行输入符号 '$' 并换行后,可以开始或是停止多行输入模式 223 在单行输入符号 '$' 并换行后,可以开始或是停止多行输入模式
204``` 224```
205&emsp;&emsp;使用案例: 225&emsp;&emsp;使用案例:
206&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .** 226&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .**
207&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .** 227&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .**
208&emsp;&emsp;编译并保留调试信息: **yue -l .** 228&emsp;&emsp;编译并保留调试信息: **yue -l .**
209&emsp;&emsp;编译并生成压缩代码: **yue -m .** 229&emsp;&emsp;编译并生成压缩代码: **yue -m .**
210&emsp;&emsp;直接执行代码: **yue -e 'print 123'** 230&emsp;&emsp;直接执行代码: **yue -e 'print 123'**
211&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue** 231&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue**
212 232
213## 宏 233## 宏
@@ -333,7 +353,7 @@ end
333 353
334### 导出宏 354### 导出宏
335 355
336宏函数可以从一个模块中导出,并在另一个模块中导入。您必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 356宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
337```moonscript 357```moonscript
338-- 文件: utils.yue 358-- 文件: utils.yue
339export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 359export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
@@ -422,6 +442,54 @@ print "有效的枚举类型:", $BodyType Static
422</pre> 442</pre>
423</YueDisplay> 443</YueDisplay>
424 444
445### 宏参数检查
446
447可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
448
449```moonscript
450macro printNumAndStr = (num `Num, str `String) -> |
451 print(
452 #{num}
453 #{str}
454 )
455
456$printNumAndStr 123, "hello"
457```
458<YueDisplay>
459<pre>
460macro printNumAndStr = (num `Num, str `String) -> |
461 print(
462 #{num}
463 #{str}
464 )
465
466$printNumAndStr 123, "hello"
467</pre>
468</YueDisplay>
469
470如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
471
472```moonscript
473macro printNumAndStr = (num, str) ->
474 error "expected Num as first argument" unless $is_ast Num, num
475 error "expected String as second argument" unless $is_ast String, str
476 "print(#{num}, #{str})"
477
478$printNumAndStr 123, "hello"
479```
480<YueDisplay>
481<pre>
482macro printNumAndStr = (num, str) ->
483 error "expected Num as first argument" unless $is_ast Num, num
484 error "expected String as second argument" unless $is_ast String, str
485 "print(#{num}, #{str})"
486
487$printNumAndStr 123, "hello"
488</pre>
489</YueDisplay>
490
491更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
492
425## 操作符 493## 操作符
426 494
427Lua的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 495Lua的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
@@ -439,7 +507,7 @@ tb::func! if tb != nil
439 507
440### 链式比较 508### 链式比较
441 509
442可以在月之脚本中进行比较表达式的链式书写: 510可以在月之脚本中进行比较表达式的链式书写:
443 511
444```moonscript 512```moonscript
445print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 513print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
@@ -528,7 +596,7 @@ tab[] = "Value"
528 596
529### 表扩展 597### 表扩展
530 598
531可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。 599可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。
532 600
533```moonscript 601```moonscript
534parts = 602parts =
@@ -565,11 +633,26 @@ merge = {...a, ...b}
565</pre> 633</pre>
566</YueDisplay> 634</YueDisplay>
567 635
636### 表反向索引
637
638你可以使用 **#** 操作符来反向索引表中的元素。
639
640```moonscript
641last = data.items[#]
642second_last = data.items[#-1]
643```
644<YueDisplay>
645<pre>
646last = data.items[#]
647second_last = data.items[#-1]
648</pre>
649</YueDisplay>
650
568### 元表 651### 元表
569 652
570**<>** 操作符可提供元表操作的快捷方式。 653**<>** 操作符可提供元表操作的快捷方式。
571 654
572* **元表创建** 655* **元表创建**
573使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 656使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。
574 657
575```moonscript 658```moonscript
@@ -605,7 +688,7 @@ close _ = &lt;close&gt;: -> print "超出范围"
605</pre> 688</pre>
606</YueDisplay> 689</YueDisplay>
607 690
608* **元表访问** 691* **元表访问**
609使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 692使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
610 693
611```moonscript 694```moonscript
@@ -629,7 +712,7 @@ print tb.item
629</pre> 712</pre>
630</YueDisplay> 713</YueDisplay>
631 714
632* **元表解构** 715* **元表解构**
633使用被 **<>** 包围的元方法键解构元表。 716使用被 **<>** 包围的元方法键解构元表。
634 717
635```moonscript 718```moonscript
@@ -680,7 +763,7 @@ with? io.open "test.txt", "w"
680 763
681### 管道 764### 管道
682 765
683与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。 766与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。
684 767
685```moonscript 768```moonscript
686"你好" |> print 769"你好" |> print
@@ -731,67 +814,87 @@ a ??= false
731 814
732### 隐式对象 815### 隐式对象
733 816
734您可以在表格块内使用符号 **\*** 开始编写一系列隐式结构。如果您正在创建隐式对象,对象的字段必须具有相同的缩进。 817你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
818
735```moonscript 819```moonscript
820-- 赋值时使用隐式对象
736list = 821list =
737 * 1 822 * 1
738 * 2 823 * 2
739 * 3 824 * 3
740 825
826-- 函数调用时使用隐式对象
741func 827func
742 * 1 828 * 1
743 * 2 829 * 2
744 * 3 830 * 3
745 831
832-- 返回时使用隐式对象
833f = ->
834 return
835 * 1
836 * 2
837 * 3
838
839-- 表格时使用隐式对象
746tb = 840tb =
747 name: "abc" 841 name: "abc"
748 842
749 values: 843 values:
750 * "a" 844 - "a"
751 * "b" 845 - "b"
752 * "c" 846 - "c"
753 847
754 objects: 848 objects:
755 * name: "a" 849 - name: "a"
756 value: 1 850 value: 1
757 func: => @value + 1 851 func: => @value + 1
758 tb: 852 tb:
759 fieldA: 1 853 fieldA: 1
760 854
761 * name: "b" 855 - name: "b"
762 value: 2 856 value: 2
763 func: => @value + 2 857 func: => @value + 2
764 tb: { } 858 tb: { }
765
766``` 859```
767<YueDisplay> 860<YueDisplay>
768<pre> 861<pre>
862-- 赋值时使用隐式对象
769list = 863list =
770 * 1 864 * 1
771 * 2 865 * 2
772 * 3 866 * 3
773 867
868-- 函数调用时使用隐式对象
774func 869func
775 * 1 870 * 1
776 * 2 871 * 2
777 * 3 872 * 3
778 873
874-- 返回时使用隐式对象
875f = ->
876 return
877 * 1
878 * 2
879 * 3
880
881-- 表格时使用隐式对象
779tb = 882tb =
780 name: "abc" 883 name: "abc"
781 884
782 values: 885 values:
783 * "a" 886 - "a"
784 * "b" 887 - "b"
785 * "c" 888 - "c"
786 889
787 objects: 890 objects:
788 * name: "a" 891 - name: "a"
789 value: 1 892 value: 1
790 func: => @value + 1 893 func: => @value + 1
791 tb: 894 tb:
792 fieldA: 1 895 fieldA: 1
793 896
794 * name: "b" 897 - name: "b"
795 value: 2 898 value: 2
796 func: => @value + 2 899 func: => @value + 2
797 tb: { } 900 tb: { }
@@ -859,7 +962,7 @@ do
859 962
860导出语句提供了一种简洁的方式来定义当前的模块。 963导出语句提供了一种简洁的方式来定义当前的模块。
861 964
862* **命名导出** 965* **命名导出**
863带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。 966带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
864 967
865```moonscript 968```moonscript
@@ -923,7 +1026,7 @@ export["a-b-c"] = 123
923</pre> 1026</pre>
924</YueDisplay> 1027</YueDisplay>
925 1028
926* **未命名导出** 1029* **未命名导出**
927未命名导出会将要导出的目标项目添加到导出表的数组部分。 1030未命名导出会将要导出的目标项目添加到导出表的数组部分。
928 1031
929```moonscript 1032```moonscript
@@ -953,7 +1056,7 @@ export with tmp
953</pre> 1056</pre>
954</YueDisplay> 1057</YueDisplay>
955 1058
956* **默认导出** 1059* **默认导出**
957在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 1060在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
958 1061
959```moonscript 1062```moonscript
@@ -1223,7 +1326,7 @@ print first, second, color
1223</pre> 1326</pre>
1224</YueDisplay> 1327</YueDisplay>
1225 1328
1226在进行解构时,可以指定默认值,如: 1329在进行解构时,可以指定默认值,如:
1227 1330
1228```moonscript 1331```moonscript
1229{:name = "nameless", :job = "jobless"} = person 1332{:name = "nameless", :job = "jobless"} = person
@@ -1234,7 +1337,7 @@ print first, second, color
1234</pre> 1337</pre>
1235</YueDisplay> 1338</YueDisplay>
1236 1339
1237在进行列表解构时,可以使用`_`作为占位符: 1340在进行列表解构时,可以使用`_`作为占位符:
1238 1341
1239```moonscript 1342```moonscript
1240[_, two, _, four] = items 1343[_, two, _, four] = items
@@ -1245,9 +1348,55 @@ print first, second, color
1245</pre> 1348</pre>
1246</YueDisplay> 1349</YueDisplay>
1247 1350
1248### 在其它地方的解构 1351### 范围解构
1352
1353你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
1354
1355```moonscript
1356orders = ["first", "second", "third", "fourth", "last"]
1357[first, ...bulk, last] = orders
1358print first -- 打印: first
1359print bulk -- 打印: {"second", "third", "fourth"}
1360print last -- 打印: last
1361```
1362<YueDisplay>
1363<pre>
1364orders = ["first", "second", "third", "fourth", "last"]
1365[first, ...bulk, last] = orders
1366print first -- 打印: first
1367print bulk -- 打印: {"second", "third", "fourth"}
1368print last -- 打印: last
1369</pre>
1370</YueDisplay>
1371
1372展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
1373
1374```moonscript
1375-- 捕获第一个元素之后的所有元素
1376[first, ...rest] = orders
1377
1378-- 捕获最后一个元素之前的所有元素
1379[...start, last] = orders
1380
1381-- 跳过中间的元素,只捕获第一个和最后一个元素
1382[first, ..._, last] = orders
1383```
1384<YueDisplay>
1385<pre>
1386-- 捕获第一个元素之后的所有元素
1387[first, ...rest] = orders
1388
1389-- 捕获最后一个元素之前的所有元素
1390[...start, last] = orders
1391
1392-- 跳过中间的元素,只捕获第一个和最后一个元素
1393[first, ..._, last] = orders
1394</pre>
1395</YueDisplay>
1396
1397### 在其它地方的解构赋值
1249 1398
1250解构也可以出现在其它隐式进行赋值的地方。一个例子是用在for循环: 1399解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在for循环
1251 1400
1252```moonscript 1401```moonscript
1253tuples = [ 1402tuples = [
@@ -1322,7 +1471,7 @@ print "好的"
1322 1471
1323### While 赋值 1472### While 赋值
1324 1473
1325可以在 while 循环中同样使用赋值来获取循环条件的值。 1474可以在 while 循环中同样使用赋值来获取循环条件的值。
1326```moonscript 1475```moonscript
1327while byte := stream\read_one! 1476while byte := stream\read_one!
1328 -- 对 byte 做一些操作 1477 -- 对 byte 做一些操作
@@ -1338,7 +1487,7 @@ while byte := stream\read_one!
1338 1487
1339## 可变参数赋值 1488## 可变参数赋值
1340 1489
1341可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。 1490可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。
1342```moonscript 1491```moonscript
1343list = [1, 2, 3, 4, 5] 1492list = [1, 2, 3, 4, 5]
1344fn = (ok) -> ok, table.unpack list 1493fn = (ok) -> ok, table.unpack list
@@ -1360,7 +1509,7 @@ print ok, count, first
1360 1509
1361## 空白 1510## 空白
1362 1511
1363月之脚本是一个对空白敏感的语言。您必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 1512月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
1364 1513
1365### 多行链式调用 1514### 多行链式调用
1366 1515
@@ -1474,6 +1623,47 @@ catch err
1474</pre> 1623</pre>
1475</YueDisplay> 1624</YueDisplay>
1476 1625
1626### 错误处理简化
1627
1628`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1629
1630```moonscript
1631a, b, c = try? func!
1632
1633-- 与空值合并运算符一起使用
1634a = (try? func!) ?? "default"
1635
1636-- 作为函数参数
1637f try? func!
1638
1639-- 带 catch 块的 try!
1640f try?
1641 print 123
1642 func!
1643catch e
1644 print e
1645 e
1646```
1647<YueDisplay>
1648<pre>
1649a, b, c = try? func!
1650
1651-- 与空值合并运算符一起使用
1652a = (try? func!) ?? "default"
1653
1654-- 作为函数参数
1655f try? func!
1656
1657-- 带 catch 块的 try!
1658f try?
1659 print 123
1660 func!
1661catch e
1662 print e
1663 e
1664</pre>
1665</YueDisplay>
1666
1477## 属性 1667## 属性
1478 1668
1479月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。 1669月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。
@@ -1502,6 +1692,19 @@ const {:a, :b, c, d} = tb
1502</pre> 1692</pre>
1503</YueDisplay> 1693</YueDisplay>
1504 1694
1695你也可以声明全局变量为常量。
1696
1697```moonscript
1698global const Constant = 123
1699-- Constant = 1
1700```
1701<YueDisplay>
1702<pre>
1703global const Constant = 123
1704-- Constant = 1
1705</pre>
1706</YueDisplay>
1707
1505## 字面量 1708## 字面量
1506 1709
1507Lua中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和**nil**。 1710Lua中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和**nil**。
@@ -1529,17 +1732,78 @@ print "我有#{math.random! * 100}%的把握。"
1529 1732
1530### 数字字面量 1733### 数字字面量
1531 1734
1532可以在数字字面量中使用下划线来增加可读性。 1735可以在数字字面量中使用下划线来增加可读性。
1533 1736
1534```moonscript 1737```moonscript
1535integer = 1_000_000 1738integer = 1_000_000
1536hex = 0xEF_BB_BF 1739hex = 0xEF_BB_BF
1740binary = 0B10011
1537``` 1741```
1538<YueDisplay> 1742<YueDisplay>
1539 1743
1540<pre> 1744<pre>
1541integer = 1_000_000 1745integer = 1_000_000
1542hex = 0xEF_BB_BF 1746hex = 0xEF_BB_BF
1747binary = 0B10011
1748</pre>
1749</YueDisplay>
1750
1751### YAML 风格字符串
1752
1753使用 `|` 前缀标记一个多行 YAML 风格字符串:
1754
1755```moonscript
1756str = |
1757 key: value
1758 list:
1759 - item1
1760 - #{expr}
1761```
1762<YueDisplay>
1763<pre>
1764str = |
1765 key: value
1766 list:
1767 - item1
1768 - #{expr}
1769</pre>
1770</YueDisplay>
1771
1772其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
1773
1774YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
1775
1776```moonscript
1777fn = ->
1778 str = |
1779 foo:
1780 bar: baz
1781 return str
1782```
1783<YueDisplay>
1784<pre>
1785fn = ->
1786 str = |
1787 foo:
1788 bar: baz
1789 return str
1790</pre>
1791</YueDisplay>
1792
1793输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
1794
1795支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
1796
1797```moonscript
1798str = |
1799 path: "C:\Program Files\App"
1800 note: 'He said: "#{Hello}!"'
1801```
1802<YueDisplay>
1803<pre>
1804str = |
1805 path: "C:\Program Files\App"
1806 note: 'He said: "#{Hello}!"'
1543</pre> 1807</pre>
1544</YueDisplay> 1808</YueDisplay>
1545 1809
@@ -1644,7 +1908,7 @@ print "数字的和是", sum 10, 20
1644</pre> 1908</pre>
1645</YueDisplay> 1909</YueDisplay>
1646 1910
1647如果需要做显式返回,可以使用return关键字: 1911如果需要做显式返回,可以使用return关键字:
1648 1912
1649```moonscript 1913```moonscript
1650sum = (x, y) -> return x + y 1914sum = (x, y) -> return x + y
@@ -1850,7 +2114,7 @@ print @value
1850</pre> 2114</pre>
1851</YueDisplay> 2115</YueDisplay>
1852 2116
1853可以通过一个占位符指定回调函数的传参位置。 2117可以通过一个占位符指定回调函数的传参位置。
1854 2118
1855```moonscript 2119```moonscript
1856(x) <- map _, [1, 2, 3] 2120(x) <- map _, [1, 2, 3]
@@ -1863,22 +2127,22 @@ x * 2
1863</pre> 2127</pre>
1864</YueDisplay> 2128</YueDisplay>
1865 2129
1866如果您希望在反向回调处理后继续编写更多其它的代码,您可以使用do语句将不归属反向回调的代码分开。 2130如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
1867 2131
1868```moonscript 2132```moonscript
1869result, msg = do 2133result, msg = do
1870 (data) <- readAsync "文件名.txt" 2134 data <- readAsync "文件名.txt"
1871 print data 2135 print data
1872 (info) <- processAsync data 2136 info <- processAsync data
1873 check info 2137 check info
1874print result, msg 2138print result, msg
1875``` 2139```
1876<YueDisplay> 2140<YueDisplay>
1877<pre> 2141<pre>
1878result, msg = do 2142result, msg = do
1879 (data) <- readAsync "文件名.txt" 2143 data <- readAsync "文件名.txt"
1880 print data 2144 print data
1881 (info) <- processAsync data 2145 info <- processAsync data
1882 check info 2146 check info
1883print result, msg 2147print result, msg
1884</pre> 2148</pre>
@@ -2037,7 +2301,7 @@ list_with_one_element = [ 1, ]
2037 2301
2038## 推导式 2302## 推导式
2039 2303
2040推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生Lua表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许您在每次遍历时设置新表格的键和值。 2304推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生Lua表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。
2041 2305
2042### 列表推导式 2306### 列表推导式
2043 2307
@@ -2057,13 +2321,11 @@ doubled = [item * 2 for i, item in ipairs items]
2057可以使用when子句筛选新表中包含的项目: 2321可以使用when子句筛选新表中包含的项目:
2058 2322
2059```moonscript 2323```moonscript
2060iter = ipairs items 2324slice = [item for i, item in ipairs items when i > 1 and i < 3]
2061slice = [item for i, item in iter when i > 1 and i < 3]
2062``` 2325```
2063<YueDisplay> 2326<YueDisplay>
2064<pre> 2327<pre>
2065iter = ipairs items 2328slice = [item for i, item in ipairs items when i > 1 and i < 3]
2066slice = [item for i, item in iter when i > 1 and i < 3]
2067</pre> 2329</pre>
2068</YueDisplay> 2330</YueDisplay>
2069 2331
@@ -2212,6 +2474,45 @@ slice = [item for item in *items[,,2]]
2212</pre> 2474</pre>
2213</YueDisplay> 2475</YueDisplay>
2214 2476
2477最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
2478
2479```moonscript
2480-- 取最后4个元素
2481slice = [item for item in *items[-4,-1]]
2482```
2483<YueDisplay>
2484<pre>
2485-- 取最后4个元素
2486slice = [item for item in *items[-4,-1]]
2487</pre>
2488</YueDisplay>
2489
2490切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
2491
2492```moonscript
2493reverse_slice = [item for item in *items[-1,1,-1]]
2494```
2495<YueDisplay>
2496<pre>
2497reverse_slice = [item for item in *items[-1,1,-1]]
2498</pre>
2499</YueDisplay>
2500
2501#### 切片表达式
2502
2503切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
2504
2505```moonscript
2506-- 取第2和第4个元素作为新的列表
2507sub_list = items[2, 4]
2508```
2509<YueDisplay>
2510<pre>
2511-- 取第2和第4个元素作为新的列表
2512sub_list = items[2, 4]
2513</pre>
2514</YueDisplay>
2515
2215## for 循环 2516## for 循环
2216 2517
2217Lua中有两种for循环形式,数字型和通用型: 2518Lua中有两种for循环形式,数字型和通用型:
@@ -2288,9 +2589,24 @@ doubled_evens = for i = 1, 20
2288</pre> 2589</pre>
2289</YueDisplay> 2590</YueDisplay>
2290 2591
2291您还可以结合for循环表达式与continue语句来过滤值。 2592此外,for循环还支持带返回值的break语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
2292 2593
2293注意出现在函数体末尾的for循环,不会被当作是一个表达式,并将循环结果累积到一个列表中作为返回值(相反,函数将返回nil)。如果要函数末尾的循环转换为列表表达式,可以使用返回语句加for循环表达式。 2594例如,查找第一个大于10的数字:
2595
2596```moonscript
2597first_large = for n in *numbers
2598 break n if n > 10
2599```
2600<YueDisplay>
2601<pre>
2602first_large = for n in *numbers
2603 break n if n > 10
2604</pre>
2605</YueDisplay>
2606
2607你还可以结合for循环表达式与continue语句来过滤值。
2608
2609注意出现在函数体末尾的for循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加for循环表达式。
2294 2610
2295```moonscript 2611```moonscript
2296func_a = -> for i = 1, 10 do print i 2612func_a = -> for i = 1, 10 do print i
@@ -2515,7 +2831,7 @@ print "你真幸运!" unless math.random! > 0.1
2515 2831
2516### 范围表达式 2832### 范围表达式
2517 2833
2518可以使用范围表达式来编写进行范围检查的代码。 2834可以使用范围表达式来编写进行范围检查的代码。
2519 2835
2520```moonscript 2836```moonscript
2521a = 5 2837a = 5
@@ -2588,28 +2904,26 @@ reader\parse_line! until reader\eof!
2588 2904
2589## switch 语句 2905## switch 语句
2590 2906
2591switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。 2907switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。switch语句中也可以使用赋值表达式来储存临时变量值。
2592 2908
2593```moonscript 2909```moonscript
2594name = "Dan" 2910switch name := "Dan"
2595switch name
2596 when "Robert" 2911 when "Robert"
2597 print "你是Robert" 2912 print "你是Robert"
2598 when "Dan", "Daniel" 2913 when "Dan", "Daniel"
2599 print "你的名字是Dan" 2914 print "你的名字是Dan"
2600 else 2915 else
2601 print "我不知道你的名字" 2916 print "我不认识,你的名字是#{name}"
2602``` 2917```
2603<YueDisplay> 2918<YueDisplay>
2604<pre> 2919<pre>
2605name = "Dan" 2920switch name := "Dan"
2606switch name
2607 when "Robert" 2921 when "Robert"
2608 print "你是Robert" 2922 print "你是Robert"
2609 when "Dan", "Daniel" 2923 when "Dan", "Daniel"
2610 print "你的名字是Dan" 2924 print "你的名字是Dan"
2611 else 2925 else
2612 print "我不知道你的名字" 2926 print "我不认识,你的名字是#{name}"
2613</pre> 2927</pre>
2614</YueDisplay> 2928</YueDisplay>
2615 2929
@@ -2686,7 +3000,7 @@ else
2686</pre> 3000</pre>
2687</YueDisplay> 3001</YueDisplay>
2688 3002
2689值得注意的是,在生成Lua代码时,我们要做检查的目标变量会放在==表达式的右侧。当您希望给when子句的比较对象定义一个\_\_eq元方法来重载判断逻辑时,可能会有用。 3003值得注意的是,在生成Lua代码时,我们要做检查的目标变量会放在==表达式的右侧。当你希望给when子句的比较对象定义一个\_\_eq元方法来重载判断逻辑时,可能会有用。
2690 3004
2691### 表格匹配 3005### 表格匹配
2692 3006
@@ -2746,9 +3060,126 @@ switch item
2746</pre> 3060</pre>
2747</YueDisplay> 3061</YueDisplay>
2748 3062
3063你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3064
3065匹配数组元素。
3066
3067```moonscript
3068switch tb
3069 when [1, 2, 3]
3070 print "1, 2, 3"
3071 when [1, b, 3]
3072 print "1, #{b}, 3"
3073 when [1, 2, b = 3] -- 变量b有默认值
3074 print "1, 2, #{b}"
3075```
3076<YueDisplay>
3077<pre>
3078switch tb
3079 when [1, 2, 3]
3080 print "1, 2, 3"
3081 when [1, b, 3]
3082 print "1, #{b}, 3"
3083 when [1, 2, b = 3] -- 变量b有默认值
3084 print "1, 2, #{b}"
3085</pre>
3086</YueDisplay>
3087
3088匹配表格字段。
3089
3090```moonscript
3091switch tb
3092 when success: true, :result
3093 print "成功", result
3094 when success: false
3095 print "失败", result
3096 else
3097 print "无效值"
3098```
3099<YueDisplay>
3100<pre>
3101switch tb
3102 when success: true, :result
3103 print "成功", result
3104 when success: false
3105 print "失败", result
3106 else
3107 print "无效值"
3108</pre>
3109</YueDisplay>
3110
3111匹配嵌套的表格结构。
3112
3113```moonscript
3114switch tb
3115 when data: {type: "success", :content}
3116 print "成功", content
3117 when data: {type: "error", :content}
3118 print "失败", content
3119 else
3120 print "无效值"
3121```
3122<YueDisplay>
3123<pre>
3124switch tb
3125 when data: {type: "success", :content}
3126 print "成功", content
3127 when data: {type: "error", :content}
3128 print "失败", content
3129 else
3130 print "无效值"
3131</pre>
3132</YueDisplay>
3133
3134匹配表格数组。
3135
3136```moonscript
3137switch tb
3138 when [
3139 {a: 1, b: 2}
3140 {a: 3, b: 4}
3141 {a: 5, b: 6}
3142 fourth
3143 ]
3144 print "匹配成功", fourth
3145```
3146<YueDisplay>
3147<pre>
3148switch tb
3149 when [
3150 {a: 1, b: 2}
3151 {a: 3, b: 4}
3152 {a: 5, b: 6}
3153 fourth
3154 ]
3155 print "匹配成功", fourth
3156</pre>
3157</YueDisplay>
3158
3159匹配一个列表并捕获特定范围内的元素。
3160
3161```moonscript
3162segments = ["admin", "users", "logs", "view"]
3163switch segments
3164 when [...groups, resource, action]
3165 print "Group:", groups -- 打印: {"admin", "users"}
3166 print "Resource:", resource -- 打印: "logs"
3167 print "Action:", action -- 打印: "view"
3168```
3169<YueDisplay>
3170<pre>
3171segments = ["admin", "users", "logs", "view"]
3172switch segments
3173 when [...groups, resource, action]
3174 print "Group:", groups -- 打印: {"admin", "users"}
3175 print "Resource:", resource -- 打印: "logs"
3176 print "Action:", action -- 打印: "view"
3177</pre>
3178</YueDisplay>
3179
2749## 面向对象编程 3180## 面向对象编程
2750 3181
2751在以下的示例中,月之脚本生成的Lua代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果您想知道关于面向对象功能的实现细节,再查看Lua代码。 3182在以下的示例中,月之脚本生成的Lua代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看Lua代码。
2752 3183
2753一个简单的类: 3184一个简单的类:
2754 3185
@@ -3216,7 +3647,7 @@ x = class
3216 3647
3217### 类混合 3648### 类混合
3218 3649
3219您可以通过使用 `using` 关键字来实现类混合。这意味着您可以从一个普通 Lua 表格或已定义的类对象中,复制函数到您创建的新类中。当您使用普通 Lua 表格进行类混合时,您有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当您从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 3650你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
3220 3651
3221```moonscript 3652```moonscript
3222MyIndex = __index: var: 1 3653MyIndex = __index: var: 1
@@ -3318,22 +3749,22 @@ me = create_person "Leaf", [dad, mother, sister]
3318 3749
3319在此用法中,with可以被视为K组合子(k-combinator)的一种特殊形式。 3750在此用法中,with可以被视为K组合子(k-combinator)的一种特殊形式。
3320 3751
3321如果给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。 3752如果想给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。
3322 3753
3323```moonscript 3754```moonscript
3324with str = "你好" 3755with str := "你好"
3325 print "原始:", str 3756 print "原始:", str
3326 print "大写:", \upper! 3757 print "大写:", \upper!
3327``` 3758```
3328<YueDisplay> 3759<YueDisplay>
3329<pre> 3760<pre>
3330with str = "你好" 3761with str := "你好"
3331 print "原始:", str 3762 print "原始:", str
3332 print "大写:", \upper! 3763 print "大写:", \upper!
3333</pre> 3764</pre>
3334</YueDisplay> 3765</YueDisplay>
3335 3766
3336在with语句中用`[]`访问特殊键。 3767 `with` 语句中使用 `[]` 访问特殊键。
3337 3768
3338```moonscript 3769```moonscript
3339with tb 3770with tb
@@ -3356,6 +3787,19 @@ with tb
3356</pre> 3787</pre>
3357</YueDisplay> 3788</YueDisplay>
3358 3789
3790`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
3791
3792```moonscript
3793with? obj
3794 print obj.name
3795```
3796<YueDisplay>
3797<pre>
3798with? obj
3799 print obj.name
3800</pre>
3801</YueDisplay>
3802
3359## do 语句 3803## do 语句
3360 3804
3361当用作语句时,do语句的作用就像在Lua中差不多。 3805当用作语句时,do语句的作用就像在Lua中差不多。
@@ -3375,7 +3819,7 @@ print var -- 这里是nil
3375</pre> 3819</pre>
3376</YueDisplay> 3820</YueDisplay>
3377 3821
3378月之脚本的 **do** 也可以用作表达式。允许您将多行代码的处理合并为一个表达式,并将do语句代码块的最后一个语句作为表达式返回的结果。 3822月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将do语句代码块的最后一个语句作为表达式返回的结果。
3379 3823
3380```moonscript 3824```moonscript
3381counter = do 3825counter = do
@@ -4334,8 +4778,8 @@ simplified: boolean
4334 4778
4335版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\> 4779版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\>
4336 4780
4337特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下: 4781特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下:
4338上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。 4782上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
4339本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。 4783本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
4340 4784
4341<CompilerModal /> 4785<CompilerModal />