aboutsummaryrefslogtreecommitdiff
path: root/doc/docs/zh
diff options
context:
space:
mode:
Diffstat (limited to 'doc/docs/zh')
-rwxr-xr-xdoc/docs/zh/README.md14
-rwxr-xr-xdoc/docs/zh/doc/index.md (renamed from doc/docs/zh/doc/README.md)1514
-rw-r--r--doc/docs/zh/index.md25
-rwxr-xr-xdoc/docs/zh/try/index.md (renamed from doc/docs/zh/try/README.md)0
4 files changed, 964 insertions, 589 deletions
diff --git a/doc/docs/zh/README.md b/doc/docs/zh/README.md
deleted file mode 100755
index e76a477..0000000
--- a/doc/docs/zh/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
1---
2layout: home
3hero:
4 name: 月之脚本
5 text: 一门编译到 Lua 的语言
6 image:
7 src: /image/yuescript.svg
8 alt: 月之脚本
9 actions:
10 - theme: brand
11 text: 快速上手 →
12 link: /zh/doc/
13footer: MIT Licensed | Copyright © 2017-2026 Li Jin
14---
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/index.md
index a3ff7cb..dff51a9 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/index.md
@@ -5,7 +5,7 @@ title: 参考手册
5 5
6# 月之脚本 6# 月之脚本
7 7
8<img src="/image/yuescript.svg" width="300px" height="300px" alt="logo"/> 8<img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;"/>
9 9
10## 介绍 10## 介绍
11 11
@@ -14,7 +14,7 @@ title: 参考手册
14Yue(月)是中文中“月亮”的名称。 14Yue(月)是中文中“月亮”的名称。
15 15
16### 月之脚本概览 16### 月之脚本概览
17```moonscript 17```yuescript
18-- 导入语法 18-- 导入语法
19import p, to_lua from "yue" 19import p, to_lua from "yue"
20 20
@@ -59,7 +59,8 @@ with apple
59export 🌛 = "月之脚本" 59export 🌛 = "月之脚本"
60``` 60```
61<YueDisplay> 61<YueDisplay>
62<pre> 62
63```yue
63-- 导入语法 64-- 导入语法
64import p, to_lua from "yue" 65import p, to_lua from "yue"
65 66
@@ -94,15 +95,16 @@ reduce = (arr, init, action): init ->
94-- 元表操作 95-- 元表操作
95apple = 96apple =
96 size: 15 97 size: 15
97 &lt;index&gt;: 98 <index>:
98 color: 0x00ffff 99 color: 0x00ffff
99 100
100with apple 101with apple
101 p .size, .color, .&lt;index&gt; if .&lt;&gt;? 102 p .size, .color, .<index> if .<>?
102 103
103-- 类似js的导出语法 104-- 类似js的导出语法
104export 🌛 = "月之脚本" 105export 🌛 = "月之脚本"
105</pre> 106```
107
106</YueDisplay> 108</YueDisplay>
107 109
108## 安装 110## 安装
@@ -194,7 +196,7 @@ f!
194### 月之脚本编译工具 196### 月之脚本编译工具
195 197
196使用月之脚本编译工具: 198使用月之脚本编译工具:
197``` 199```sh
198命令行用法: yue 200命令行用法: yue
199 [选项] [<文件/目录>] ... 201 [选项] [<文件/目录>] ...
200 yue -e <代码或文件> [参数...] 202 yue -e <代码或文件> [参数...]
@@ -235,12 +237,12 @@ f!
235 不带选项直接运行可进入交互模式(REPL),在交互模式里输入单独的符号 '$' 237 不带选项直接运行可进入交互模式(REPL),在交互模式里输入单独的符号 '$'
236 可用于开始或结束多行模式。 238 可用于开始或结束多行模式。
237``` 239```
238&emsp;&emsp;使用案例: 240&emsp;&emsp;使用案例:
239&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .** 241&emsp;&emsp;递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .**
240&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .** 242&emsp;&emsp;编译并将结果保存到目标路径: **yue -t /target/path/ .**
241&emsp;&emsp;编译并保留调试信息: **yue -l .** 243&emsp;&emsp;编译并保留调试信息: **yue -l .**
242&emsp;&emsp;编译并生成压缩代码: **yue -m .** 244&emsp;&emsp;编译并生成压缩代码: **yue -m .**
243&emsp;&emsp;直接执行代码: **yue -e 'print 123'** 245&emsp;&emsp;直接执行代码: **yue -e 'print 123'**
244&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue** 246&emsp;&emsp;执行一个月之脚本文件: **yue -e main.yue**
245 247
246## 宏 248## 宏
@@ -249,7 +251,7 @@ f!
249 251
250宏函数用于在编译时执行一段代码来生成新的代码,并将生成的代码插入到最终编译结果中。 252宏函数用于在编译时执行一段代码来生成新的代码,并将生成的代码插入到最终编译结果中。
251 253
252```moonscript 254```yuescript
253macro PI2 = -> math.pi * 2 255macro PI2 = -> math.pi * 2
254area = $PI2 * 5 256area = $PI2 * 5
255 257
@@ -278,7 +280,8 @@ if $and f1!, f2!, f3!
278 print "OK" 280 print "OK"
279``` 281```
280<YueDisplay> 282<YueDisplay>
281<pre> 283
284```yue
282macro PI2 = -> math.pi * 2 285macro PI2 = -> math.pi * 2
283area = $PI2 * 5 286area = $PI2 * 5
284 287
@@ -305,13 +308,14 @@ value = $assert item
305macro and = (...) -> "#{ table.concat {...}, ' and ' }" 308macro and = (...) -> "#{ table.concat {...}, ' and ' }"
306if $and f1!, f2!, f3! 309if $and f1!, f2!, f3!
307 print "OK" 310 print "OK"
308</pre> 311```
312
309</YueDisplay> 313</YueDisplay>
310 314
311### 直接插入代码 315### 直接插入代码
312 316
313宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。 317宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。
314```moonscript 318```yuescript
315macro yueFunc = (var) -> "local #{var} = ->" 319macro yueFunc = (var) -> "local #{var} = ->"
316$yueFunc funcA 320$yueFunc funcA
317funcA = -> "无法访问宏生成月之脚本里定义的变量" 321funcA = -> "无法访问宏生成月之脚本里定义的变量"
@@ -337,7 +341,8 @@ end
337]==] 341]==]
338``` 342```
339<YueDisplay> 343<YueDisplay>
340<pre> 344
345```yue
341macro yueFunc = (var) -> "local #{var} = ->" 346macro yueFunc = (var) -> "local #{var} = ->"
342$yueFunc funcA 347$yueFunc funcA
343funcA = -> "无法访问宏生成月之脚本里定义的变量" 348funcA = -> "无法访问宏生成月之脚本里定义的变量"
@@ -361,13 +366,14 @@ if cond then
361 print("输出") 366 print("输出")
362end 367end
363]==] 368]==]
364</pre> 369```
370
365</YueDisplay> 371</YueDisplay>
366 372
367### 导出宏 373### 导出宏
368 374
369宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 375宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
370```moonscript 376```yuescript
371-- 文件: utils.yue 377-- 文件: utils.yue
372export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 378export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
373export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" 379export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
@@ -382,7 +388,8 @@ import "utils" as {
382[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ 388[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
383``` 389```
384<YueDisplay> 390<YueDisplay>
385<pre> 391
392```yue
386-- 文件: utils.yue 393-- 文件: utils.yue
387export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 394export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
388export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" 395export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]"
@@ -397,28 +404,31 @@ import "utils" as {
397} 404}
398[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ 405[1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
399]] 406]]
400</pre> 407```
408
401</YueDisplay> 409</YueDisplay>
402 410
403### 内置宏 411### 内置宏
404 412
405月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。 413月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。
406```moonscript 414```yuescript
407print $FILE -- 获取当前模块名称的字符串 415print $FILE -- 获取当前模块名称的字符串
408print $LINE -- 获取当前代码行数:2 416print $LINE -- 获取当前代码行数:2
409``` 417```
410<YueDisplay> 418<YueDisplay>
411<pre> 419
420```yue
412print $FILE -- 获取当前模块名称的字符串 421print $FILE -- 获取当前模块名称的字符串
413print $LINE -- 获取当前代码行数:2 422print $LINE -- 获取当前代码行数:2
414</pre> 423```
424
415</YueDisplay> 425</YueDisplay>
416 426
417### 用宏生成宏 427### 用宏生成宏
418 428
419在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。 429在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。
420 430
421```moonscript 431```yuescript
422macro Enum = (...) -> 432macro Enum = (...) ->
423 items = {...} 433 items = {...}
424 itemSet = {item, true for item in *items} 434 itemSet = {item, true for item in *items}
@@ -436,7 +446,8 @@ print "有效的枚举类型:", $BodyType Static
436-- print "编译报错的枚举类型:", $BodyType Unknown 446-- print "编译报错的枚举类型:", $BodyType Unknown
437``` 447```
438<YueDisplay> 448<YueDisplay>
439<pre> 449
450```yue
440macro Enum = (...) -> 451macro Enum = (...) ->
441 items = {...} 452 items = {...}
442 itemSet = {item, true for item in *items} 453 itemSet = {item, true for item in *items}
@@ -452,14 +463,15 @@ macro BodyType = $Enum(
452 463
453print "有效的枚举类型:", $BodyType Static 464print "有效的枚举类型:", $BodyType Static
454-- print "编译报错的枚举类型:", $BodyType Unknown 465-- print "编译报错的枚举类型:", $BodyType Unknown
455</pre> 466```
467
456</YueDisplay> 468</YueDisplay>
457 469
458### 宏参数检查 470### 宏参数检查
459 471
460可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。 472可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
461 473
462```moonscript 474```yuescript
463macro printNumAndStr = (num `Num, str `String) -> | 475macro printNumAndStr = (num `Num, str `String) -> |
464 print( 476 print(
465 #{num} 477 #{num}
@@ -469,7 +481,8 @@ macro printNumAndStr = (num `Num, str `String) -> |
469$printNumAndStr 123, "hello" 481$printNumAndStr 123, "hello"
470``` 482```
471<YueDisplay> 483<YueDisplay>
472<pre> 484
485```yue
473macro printNumAndStr = (num `Num, str `String) -> | 486macro printNumAndStr = (num `Num, str `String) -> |
474 print( 487 print(
475 #{num} 488 #{num}
@@ -477,12 +490,13 @@ macro printNumAndStr = (num `Num, str `String) -> |
477 ) 490 )
478 491
479$printNumAndStr 123, "hello" 492$printNumAndStr 123, "hello"
480</pre> 493```
494
481</YueDisplay> 495</YueDisplay>
482 496
483如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。 497如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
484 498
485```moonscript 499```yuescript
486macro printNumAndStr = (num, str) -> 500macro printNumAndStr = (num, str) ->
487 error "expected Num as first argument" unless $is_ast Num, num 501 error "expected Num as first argument" unless $is_ast Num, num
488 error "expected String as second argument" unless $is_ast String, str 502 error "expected String as second argument" unless $is_ast String, str
@@ -491,14 +505,16 @@ macro printNumAndStr = (num, str) ->
491$printNumAndStr 123, "hello" 505$printNumAndStr 123, "hello"
492``` 506```
493<YueDisplay> 507<YueDisplay>
494<pre> 508
509```yue
495macro printNumAndStr = (num, str) -> 510macro printNumAndStr = (num, str) ->
496 error "expected Num as first argument" unless $is_ast Num, num 511 error "expected Num as first argument" unless $is_ast Num, num
497 error "expected String as second argument" unless $is_ast String, str 512 error "expected String as second argument" unless $is_ast String, str
498 "print(#{num}, #{str})" 513 "print(#{num}, #{str})"
499 514
500$printNumAndStr 123, "hello" 515$printNumAndStr 123, "hello"
501</pre> 516```
517
502</YueDisplay> 518</YueDisplay>
503 519
504更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。 520更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
@@ -507,22 +523,24 @@ $printNumAndStr 123, "hello"
507 523
508Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 524Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
509 525
510```moonscript 526```yuescript
511tb\func! if tb ~= nil 527tb\func! if tb ~= nil
512tb::func! if tb != nil 528tb::func! if tb != nil
513``` 529```
514<YueDisplay> 530<YueDisplay>
515<pre> 531
532```yue
516tb\func! if tb ~= nil 533tb\func! if tb ~= nil
517tb::func! if tb != nil 534tb::func! if tb != nil
518</pre> 535```
536
519</YueDisplay> 537</YueDisplay>
520 538
521### 链式比较 539### 链式比较
522 540
523你可以在月之脚本中进行比较表达式的链式书写: 541你可以在月之脚本中进行比较表达式的链式书写:
524 542
525```moonscript 543```yuescript
526print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 544print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
527-- 输出:true 545-- 输出:true
528 546
@@ -531,19 +549,21 @@ print 1 <= a <= 10
531-- 输出:true 549-- 输出:true
532``` 550```
533<YueDisplay> 551<YueDisplay>
534<pre> 552
553```yue
535print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 554print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
536-- 输出:true 555-- 输出:true
537 556
538a = 5 557a = 5
539print 1 <= a <= 10 558print 1 <= a <= 10
540-- 输出:true 559-- 输出:true
541</pre> 560```
561
542</YueDisplay> 562</YueDisplay>
543 563
544可以注意一下链式比较表达式的求值行为: 564可以注意一下链式比较表达式的求值行为:
545 565
546```moonscript 566```yuescript
547v = (x) -> 567v = (x) ->
548 print x 568 print x
549 x 569 x
@@ -566,7 +586,8 @@ print v(1) > v(2) <= v(3)
566]] 586]]
567``` 587```
568<YueDisplay> 588<YueDisplay>
569<pre> 589
590```yue
570v = (x) -> 591v = (x) ->
571 print x 592 print x
572 x 593 x
@@ -587,7 +608,8 @@ print v(1) > v(2) <= v(3)
587 1 608 1
588 false 609 false
589]] 610]]
590</pre> 611```
612
591</YueDisplay> 613</YueDisplay>
592 614
593在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。 615在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。
@@ -596,39 +618,43 @@ print v(1) > v(2) <= v(3)
596 618
597**[] =** 操作符用于向 Lua 表的最后插入值。 619**[] =** 操作符用于向 Lua 表的最后插入值。
598 620
599```moonscript 621```yuescript
600tab = [] 622tab = []
601tab[] = "Value" 623tab[] = "Value"
602``` 624```
603<YueDisplay> 625<YueDisplay>
604<pre> 626
627```yue
605tab = [] 628tab = []
606tab[] = "Value" 629tab[] = "Value"
607</pre> 630```
631
608</YueDisplay> 632</YueDisplay>
609 633
610你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中: 634你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
611 635
612```moonscript 636```yuescript
613tbA = [1, 2, 3] 637tbA = [1, 2, 3]
614tbB = [4, 5, 6] 638tbB = [4, 5, 6]
615tbA[] = ...tbB 639tbA[] = ...tbB
616-- tbA 现在为 [1, 2, 3, 4, 5, 6] 640-- tbA 现在为 [1, 2, 3, 4, 5, 6]
617``` 641```
618<YueDisplay> 642<YueDisplay>
619<pre> 643
644```yue
620tbA = [1, 2, 3] 645tbA = [1, 2, 3]
621tbB = [4, 5, 6] 646tbB = [4, 5, 6]
622tbA[] = ...tbB 647tbA[] = ...tbB
623-- tbA 现在为 [1, 2, 3, 4, 5, 6] 648-- tbA 现在为 [1, 2, 3, 4, 5, 6]
624</pre> 649```
650
625</YueDisplay> 651</YueDisplay>
626 652
627### 表扩展 653### 表扩展
628 654
629你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。 655你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。
630 656
631```moonscript 657```yuescript
632parts = 658parts =
633 * "shoulders" 659 * "shoulders"
634 * "knees" 660 * "knees"
@@ -645,7 +671,8 @@ b = {4, 5, y: 1}
645merge = {...a, ...b} 671merge = {...a, ...b}
646``` 672```
647<YueDisplay> 673<YueDisplay>
648<pre> 674
675```yue
649parts = 676parts =
650 * "shoulders" 677 * "shoulders"
651 * "knees" 678 * "knees"
@@ -660,24 +687,27 @@ copy = {...other}
660a = {1, 2, 3, x: 1} 687a = {1, 2, 3, x: 1}
661b = {4, 5, y: 1} 688b = {4, 5, y: 1}
662merge = {...a, ...b} 689merge = {...a, ...b}
663</pre> 690```
691
664</YueDisplay> 692</YueDisplay>
665 693
666### 表反向索引 694### 表反向索引
667 695
668你可以使用 **#** 操作符来反向索引表中的元素。 696你可以使用 **#** 操作符来反向索引表中的元素。
669 697
670```moonscript 698```yuescript
671last = data.items[#] 699last = data.items[#]
672second_last = data.items[#-1] 700second_last = data.items[#-1]
673data.items[#] = 1 701data.items[#] = 1
674``` 702```
675<YueDisplay> 703<YueDisplay>
676<pre> 704
705```yue
677last = data.items[#] 706last = data.items[#]
678second_last = data.items[#-1] 707second_last = data.items[#-1]
679data.items[#] = 1 708data.items[#] = 1
680</pre> 709```
710
681</YueDisplay> 711</YueDisplay>
682 712
683### 元表 713### 元表
@@ -687,7 +717,7 @@ data.items[#] = 1
687* **元表创建** 717* **元表创建**
688使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。 718使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。
689 719
690```moonscript 720```yuescript
691mt = {} 721mt = {}
692add = (right) => <>: mt, value: @value + right.value 722add = (right) => <>: mt, value: @value + right.value
693mt.__add = add 723mt.__add = add
@@ -703,27 +733,29 @@ print d.value
703close _ = <close>: -> print "超出范围" 733close _ = <close>: -> print "超出范围"
704``` 734```
705<YueDisplay> 735<YueDisplay>
706<pre> 736
737```yue
707mt = {} 738mt = {}
708add = (right) => &lt;&gt;: mt, value: @value + right.value 739add = (right) => <>: mt, value: @value + right.value
709mt.__add = add 740mt.__add = add
710 741
711a = &lt;&gt;: mt, value: 1 742a = <>: mt, value: 1
712-- 使用与临时变量名相同的字段名,将临时变量赋值给元表 743-- 使用与临时变量名相同的字段名,将临时变量赋值给元表
713b = :&lt;add&gt;, value: 2 744b = :<add>, value: 2
714c = &lt;add&gt;: mt.__add, value: 3 745c = <add>: mt.__add, value: 3
715 746
716d = a + b + c 747d = a + b + c
717print d.value 748print d.value
718 749
719close _ = &lt;close&gt;: -> print "超出范围" 750close _ = <close>: -> print "超出范围"
720</pre> 751```
752
721</YueDisplay> 753</YueDisplay>
722 754
723* **元表访问** 755* **元表访问**
724使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 756使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
725 757
726```moonscript 758```yuescript
727-- 使用包含字段 "value" 的元表创建 759-- 使用包含字段 "value" 的元表创建
728tb = <"value">: 123 760tb = <"value">: 123
729tb.<index> = tb.<> 761tb.<index> = tb.<>
@@ -734,35 +766,39 @@ print tb.item
734``` 766```
735<YueDisplay> 767<YueDisplay>
736 768
737<pre> 769
770```yue
738-- 使用包含字段 "value" 的元表创建 771-- 使用包含字段 "value" 的元表创建
739tb = &lt;"value"&gt;: 123 772tb = <"value">: 123
740tb.&lt;index&gt; = tb.&lt;&gt; 773tb.<index> = tb.<>
741print tb.value 774print tb.value
742tb.&lt;&gt; = __index: {item: "hello"} 775tb.<> = __index: {item: "hello"}
743print tb.item 776print tb.item
744</pre> 777```
778
745</YueDisplay> 779</YueDisplay>
746 780
747* **元表解构** 781* **元表解构**
748使用被 **<>** 包围的元方法键解构元表。 782使用被 **<>** 包围的元方法键解构元表。
749 783
750```moonscript 784```yuescript
751{item, :new, :<close>, <index>: getter} = tb 785{item, :new, :<close>, <index>: getter} = tb
752print item, new, close, getter 786print item, new, close, getter
753``` 787```
754<YueDisplay> 788<YueDisplay>
755<pre> 789
756{item, :new, :&lt;close&gt;, &lt;index&gt;: getter} = tb 790```yue
791{item, :new, :<close>, <index>: getter} = tb
757print item, new, close, getter 792print item, new, close, getter
758</pre> 793```
794
759</YueDisplay> 795</YueDisplay>
760 796
761### 存在性 797### 存在性
762 798
763**?** 运算符可以在多种上下文中用来检查存在性。 799**?** 运算符可以在多种上下文中用来检查存在性。
764 800
765```moonscript 801```yuescript
766func?! 802func?!
767print abc?["你好 世界"]?.xyz 803print abc?["你好 世界"]?.xyz
768 804
@@ -777,7 +813,8 @@ with? io.open "test.txt", "w"
777 \close! 813 \close!
778``` 814```
779<YueDisplay> 815<YueDisplay>
780<pre> 816
817```yue
781func?! 818func?!
782print abc?["你好 世界"]?.xyz 819print abc?["你好 世界"]?.xyz
783 820
@@ -790,14 +827,15 @@ if print and x?
790with? io.open "test.txt", "w" 827with? io.open "test.txt", "w"
791 \write "你好" 828 \write "你好"
792 \close! 829 \close!
793</pre> 830```
831
794</YueDisplay> 832</YueDisplay>
795 833
796### 管道 834### 管道
797 835
798与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。 836与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。
799 837
800```moonscript 838```yuescript
801"你好" |> print 839"你好" |> print
8021 |> print 2 -- 将管道项作为第一个参数插入 8401 |> print 2 -- 将管道项作为第一个参数插入
8032 |> print 1, _, 3 -- 带有占位符的管道 8412 |> print 1, _, 3 -- 带有占位符的管道
@@ -811,7 +849,8 @@ readFile "example.txt"
811 |> print 849 |> print
812``` 850```
813<YueDisplay> 851<YueDisplay>
814<pre> 852
853```yue
815"你好" |> print 854"你好" |> print
8161 |> print 2 -- 将管道项作为第一个参数插入 8551 |> print 2 -- 将管道项作为第一个参数插入
8172 |> print 1, _, 3 -- 带有占位符的管道 8562 |> print 1, _, 3 -- 带有占位符的管道
@@ -822,13 +861,14 @@ readFile "example.txt"
822 |> emit 861 |> emit
823 |> render 862 |> render
824 |> print 863 |> print
825</pre> 864```
865
826</YueDisplay> 866</YueDisplay>
827 867
828### 空值合并 868### 空值合并
829 869
830如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。 870如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。
831```moonscript 871```yuescript
832local a, b, c, d 872local a, b, c, d
833a = b ?? c ?? d 873a = b ?? c ?? d
834func a ?? {} 874func a ?? {}
@@ -836,19 +876,21 @@ func a ?? {}
836a ??= false 876a ??= false
837``` 877```
838<YueDisplay> 878<YueDisplay>
839<pre> 879
880```yue
840local a, b, c, d 881local a, b, c, d
841a = b ?? c ?? d 882a = b ?? c ?? d
842func a ?? {} 883func a ?? {}
843a ??= false 884a ??= false
844</pre> 885```
886
845</YueDisplay> 887</YueDisplay>
846 888
847### 隐式对象 889### 隐式对象
848 890
849你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。 891你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
850 892
851```moonscript 893```yuescript
852-- 赋值时使用隐式对象 894-- 赋值时使用隐式对象
853list = 895list =
854 * 1 896 * 1
@@ -890,7 +932,8 @@ tb =
890 tb: { } 932 tb: { }
891``` 933```
892<YueDisplay> 934<YueDisplay>
893<pre> 935
936```yue
894-- 赋值时使用隐式对象 937-- 赋值时使用隐式对象
895list = 938list =
896 * 1 939 * 1
@@ -930,7 +973,8 @@ tb =
930 value: 2 973 value: 2
931 func: => @value + 2 974 func: => @value + 2
932 tb: { } 975 tb: { }
933</pre> 976```
977
934</YueDisplay> 978</YueDisplay>
935 979
936## 模块 980## 模块
@@ -939,7 +983,7 @@ tb =
939 983
940导入语句是一个语法糖,用于需要引入一个模块或者从已导入的模块中提取子项目。从模块导入的变量默认为不可修改的常量。 984导入语句是一个语法糖,用于需要引入一个模块或者从已导入的模块中提取子项目。从模块导入的变量默认为不可修改的常量。
941 985
942```moonscript 986```yuescript
943-- 用作表解构 987-- 用作表解构
944do 988do
945 import insert, concat from table 989 import insert, concat from table
@@ -964,7 +1008,8 @@ do
964 import "export" as {one, two, Something:{umm:{ch}}} 1008 import "export" as {one, two, Something:{umm:{ch}}}
965``` 1009```
966<YueDisplay> 1010<YueDisplay>
967<pre> 1011
1012```yue
968-- 用作表解构 1013-- 用作表解构
969do 1014do
970 import insert, concat from table 1015 import insert, concat from table
@@ -987,26 +1032,29 @@ do
987 import "player" as PlayerModule 1032 import "player" as PlayerModule
988 import "lpeg" as :C, :Ct, :Cmt 1033 import "lpeg" as :C, :Ct, :Cmt
989 import "export" as {one, two, Something:{umm:{ch}}} 1034 import "export" as {one, two, Something:{umm:{ch}}}
990</pre> 1035```
1036
991</YueDisplay> 1037</YueDisplay>
992 1038
993### 导入全局变量 1039### 导入全局变量
994 1040
995你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。 1041你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。
996 1042
997```moonscript 1043```yuescript
998do 1044do
999 import tostring 1045 import tostring
1000 import table.concat 1046 import table.concat
1001 print concat ["a", tostring 1] 1047 print concat ["a", tostring 1]
1002``` 1048```
1003<YueDisplay> 1049<YueDisplay>
1004<pre> 1050
1051```yue
1005do 1052do
1006 import tostring 1053 import tostring
1007 import table.concat 1054 import table.concat
1008 print concat ["a", tostring 1] 1055 print concat ["a", tostring 1]
1009</pre> 1056```
1057
1010</YueDisplay> 1058</YueDisplay>
1011 1059
1012#### 自动导入 1060#### 自动导入
@@ -1015,7 +1063,7 @@ do
1015 1063
1016但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。 1064但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。
1017 1065
1018```moonscript 1066```yuescript
1019do 1067do
1020 import global 1068 import global
1021 print "hello" 1069 print "hello"
@@ -1030,7 +1078,8 @@ do
1030 FLAG = 123 1078 FLAG = 123
1031``` 1079```
1032<YueDisplay> 1080<YueDisplay>
1033<pre> 1081
1082```yue
1034do 1083do
1035 import global 1084 import global
1036 print "hello" 1085 print "hello"
@@ -1043,7 +1092,8 @@ do
1043 global FLAG 1092 global FLAG
1044 print FLAG 1093 print FLAG
1045 FLAG = 123 1094 FLAG = 123
1046</pre> 1095```
1096
1047</YueDisplay> 1097</YueDisplay>
1048 1098
1049### 导出 1099### 导出
@@ -1053,7 +1103,7 @@ do
1053* **命名导出** 1103* **命名导出**
1054带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。 1104带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
1055 1105
1056```moonscript 1106```yuescript
1057export a, b, c = 1, 2, 3 1107export a, b, c = 1, 2, 3
1058export cool = "cat" 1108export cool = "cat"
1059 1109
@@ -1069,7 +1119,8 @@ export class Something
1069 umm: "cool" 1119 umm: "cool"
1070``` 1120```
1071<YueDisplay> 1121<YueDisplay>
1072<pre> 1122
1123```yue
1073export a, b, c = 1, 2, 3 1124export a, b, c = 1, 2, 3
1074export cool = "cat" 1125export cool = "cat"
1075 1126
@@ -1083,41 +1134,46 @@ export y = ->
1083 1134
1084export class Something 1135export class Something
1085 umm: "cool" 1136 umm: "cool"
1086</pre> 1137```
1138
1087</YueDisplay> 1139</YueDisplay>
1088 1140
1089使用解构进行命名导出。 1141使用解构进行命名导出。
1090 1142
1091```moonscript 1143```yuescript
1092export :loadstring, to_lua: tolua = yue 1144export :loadstring, to_lua: tolua = yue
1093export {itemA: {:fieldA = '默认值'}} = tb 1145export {itemA: {:fieldA = '默认值'}} = tb
1094``` 1146```
1095<YueDisplay> 1147<YueDisplay>
1096<pre> 1148
1149```yue
1097export :loadstring, to_lua: tolua = yue 1150export :loadstring, to_lua: tolua = yue
1098export {itemA: {:fieldA = '默认值'}} = tb 1151export {itemA: {:fieldA = '默认值'}} = tb
1099</pre> 1152```
1153
1100</YueDisplay> 1154</YueDisplay>
1101 1155
1102从模块导出命名项目时,可以不用创建局部变量。 1156从模块导出命名项目时,可以不用创建局部变量。
1103 1157
1104```moonscript 1158```yuescript
1105export.itemA = tb 1159export.itemA = tb
1106export.<index> = items 1160export.<index> = items
1107export["a-b-c"] = 123 1161export["a-b-c"] = 123
1108``` 1162```
1109<YueDisplay> 1163<YueDisplay>
1110<pre> 1164
1165```yue
1111export.itemA = tb 1166export.itemA = tb
1112export.&lt;index&gt; = items 1167export.<index> = items
1113export["a-b-c"] = 123 1168export["a-b-c"] = 123
1114</pre> 1169```
1170
1115</YueDisplay> 1171</YueDisplay>
1116 1172
1117* **未命名导出** 1173* **未命名导出**
1118未命名导出会将要导出的目标项目添加到导出表的数组部分。 1174未命名导出会将要导出的目标项目添加到导出表的数组部分。
1119 1175
1120```moonscript 1176```yuescript
1121d, e, f = 3, 2, 1 1177d, e, f = 3, 2, 1
1122export d, e, f 1178export d, e, f
1123 1179
@@ -1130,7 +1186,8 @@ export with tmp
1130 j = 2000 1186 j = 2000
1131``` 1187```
1132<YueDisplay> 1188<YueDisplay>
1133<pre> 1189
1190```yue
1134d, e, f = 3, 2, 1 1191d, e, f = 3, 2, 1
1135export d, e, f 1192export d, e, f
1136 1193
@@ -1141,46 +1198,51 @@ else
1141 1198
1142export with tmp 1199export with tmp
1143 j = 2000 1200 j = 2000
1144</pre> 1201```
1202
1145</YueDisplay> 1203</YueDisplay>
1146 1204
1147* **默认导出** 1205* **默认导出**
1148在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 1206在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
1149 1207
1150```moonscript 1208```yuescript
1151export default -> 1209export default ->
1152 print "你好" 1210 print "你好"
1153 123 1211 123
1154``` 1212```
1155<YueDisplay> 1213<YueDisplay>
1156<pre> 1214
1215```yue
1157export default -> 1216export default ->
1158 print "你好" 1217 print "你好"
1159 123 1218 123
1160</pre> 1219```
1220
1161</YueDisplay> 1221</YueDisplay>
1162 1222
1163## 赋值 1223## 赋值
1164 1224
1165月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。 1225月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。
1166 1226
1167```moonscript 1227```yuescript
1168hello = "world" 1228hello = "world"
1169a, b, c = 1, 2, 3 1229a, b, c = 1, 2, 3
1170hello = 123 -- 访问现有的变量 1230hello = 123 -- 访问现有的变量
1171``` 1231```
1172<YueDisplay> 1232<YueDisplay>
1173<pre> 1233
1234```yue
1174hello = "world" 1235hello = "world"
1175a, b, c = 1, 2, 3 1236a, b, c = 1, 2, 3
1176hello = 123 -- 访问现有的变量 1237hello = 123 -- 访问现有的变量
1177</pre> 1238```
1239
1178</YueDisplay> 1240</YueDisplay>
1179 1241
1180### 执行更新 1242### 执行更新
1181 1243
1182你可以使用各式二进制运算符执行更新赋值。 1244你可以使用各式二进制运算符执行更新赋值。
1183```moonscript 1245```yuescript
1184x = 1 1246x = 1
1185x += 1 1247x += 1
1186x -= 1 1248x -= 1
@@ -1191,7 +1253,8 @@ s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局
1191arg or= "默认值" 1253arg or= "默认值"
1192``` 1254```
1193<YueDisplay> 1255<YueDisplay>
1194<pre> 1256
1257```yue
1195x = 1 1258x = 1
1196x += 1 1259x += 1
1197x -= 1 1260x -= 1
@@ -1200,25 +1263,28 @@ x /= 10
1200x %= 10 1263x %= 10
1201s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量 1264s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量
1202arg or= "默认值" 1265arg or= "默认值"
1203</pre> 1266```
1267
1204</YueDisplay> 1268</YueDisplay>
1205 1269
1206### 链式赋值 1270### 链式赋值
1207 1271
1208你可以进行链式赋值,将多个项目赋予相同的值。 1272你可以进行链式赋值,将多个项目赋予相同的值。
1209```moonscript 1273```yuescript
1210a = b = c = d = e = 0 1274a = b = c = d = e = 0
1211x = y = z = f! 1275x = y = z = f!
1212``` 1276```
1213<YueDisplay> 1277<YueDisplay>
1214<pre> 1278
1279```yue
1215a = b = c = d = e = 0 1280a = b = c = d = e = 0
1216x = y = z = f! 1281x = y = z = f!
1217</pre> 1282```
1283
1218</YueDisplay> 1284</YueDisplay>
1219 1285
1220### 显式声明局部变量 1286### 显式声明局部变量
1221```moonscript 1287```yuescript
1222do 1288do
1223 local a = 1 1289 local a = 1
1224 local * 1290 local *
@@ -1235,7 +1301,8 @@ do
1235 B = 2 1301 B = 2
1236``` 1302```
1237<YueDisplay> 1303<YueDisplay>
1238<pre> 1304
1305```yue
1239do 1306do
1240 local a = 1 1307 local a = 1
1241 local * 1308 local *
@@ -1250,11 +1317,12 @@ do
1250 print "只预先声明后续大写的变量为局部变量" 1317 print "只预先声明后续大写的变量为局部变量"
1251 a = 1 1318 a = 1
1252 B = 2 1319 B = 2
1253</pre> 1320```
1321
1254</YueDisplay> 1322</YueDisplay>
1255 1323
1256### 显式声明全局变量 1324### 显式声明全局变量
1257```moonscript 1325```yuescript
1258do 1326do
1259 global a = 1 1327 global a = 1
1260 global * 1328 global *
@@ -1271,7 +1339,8 @@ do
1271 local Temp = "一个局部值" 1339 local Temp = "一个局部值"
1272``` 1340```
1273<YueDisplay> 1341<YueDisplay>
1274<pre> 1342
1343```yue
1275do 1344do
1276 global a = 1 1345 global a = 1
1277 global * 1346 global *
@@ -1286,7 +1355,8 @@ do
1286 a = 1 1355 a = 1
1287 B = 2 1356 B = 2
1288 local Temp = "一个局部值" 1357 local Temp = "一个局部值"
1289</pre> 1358```
1359
1290</YueDisplay> 1360</YueDisplay>
1291 1361
1292## 解构赋值 1362## 解构赋值
@@ -1297,7 +1367,7 @@ do
1297 1367
1298最好是通过示例来解释。以下是如何从表格中解包前两个值的方法: 1368最好是通过示例来解释。以下是如何从表格中解包前两个值的方法:
1299 1369
1300```moonscript 1370```yuescript
1301thing = [1, 2] 1371thing = [1, 2]
1302 1372
1303[a, b] = thing 1373[a, b] = thing
@@ -1305,17 +1375,19 @@ print a, b
1305``` 1375```
1306<YueDisplay> 1376<YueDisplay>
1307 1377
1308<pre> 1378
1379```yue
1309thing = [1, 2] 1380thing = [1, 2]
1310 1381
1311[a, b] = thing 1382[a, b] = thing
1312print a, b 1383print a, b
1313</pre> 1384```
1385
1314</YueDisplay> 1386</YueDisplay>
1315 1387
1316在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。 1388在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。
1317 1389
1318```moonscript 1390```yuescript
1319obj = { 1391obj = {
1320 hello: "world" 1392 hello: "world"
1321 day: "tuesday" 1393 day: "tuesday"
@@ -1328,7 +1400,8 @@ print hello, the_day
1328:day = obj -- 可以不带大括号进行简单的解构 1400:day = obj -- 可以不带大括号进行简单的解构
1329``` 1401```
1330<YueDisplay> 1402<YueDisplay>
1331<pre> 1403
1404```yue
1332obj = { 1405obj = {
1333 hello: "world" 1406 hello: "world"
1334 day: "tuesday" 1407 day: "tuesday"
@@ -1339,12 +1412,13 @@ obj = {
1339print hello, the_day 1412print hello, the_day
1340 1413
1341:day = obj -- 可以不带大括号进行简单的解构 1414:day = obj -- 可以不带大括号进行简单的解构
1342</pre> 1415```
1416
1343</YueDisplay> 1417</YueDisplay>
1344 1418
1345这也适用于嵌套的数据结构: 1419这也适用于嵌套的数据结构:
1346 1420
1347```moonscript 1421```yuescript
1348obj2 = { 1422obj2 = {
1349 numbers: [1,2,3,4] 1423 numbers: [1,2,3,4]
1350 properties: { 1424 properties: {
@@ -1357,7 +1431,8 @@ obj2 = {
1357print first, second, color 1431print first, second, color
1358``` 1432```
1359<YueDisplay> 1433<YueDisplay>
1360<pre> 1434
1435```yue
1361obj2 = { 1436obj2 = {
1362 numbers: [1,2,3,4] 1437 numbers: [1,2,3,4]
1363 properties: { 1438 properties: {
@@ -1368,12 +1443,13 @@ obj2 = {
1368 1443
1369{numbers: [first, second]} = obj2 1444{numbers: [first, second]} = obj2
1370print first, second, color 1445print first, second, color
1371</pre> 1446```
1447
1372</YueDisplay> 1448</YueDisplay>
1373 1449
1374如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例: 1450如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例:
1375 1451
1376```moonscript 1452```yuescript
1377{ 1453{
1378 numbers: [first, second] 1454 numbers: [first, second]
1379 properties: { 1455 properties: {
@@ -1382,65 +1458,75 @@ print first, second, color
1382} = obj2 1458} = obj2
1383``` 1459```
1384<YueDisplay> 1460<YueDisplay>
1385<pre> 1461
1462```yue
1386{ 1463{
1387 numbers: [first, second] 1464 numbers: [first, second]
1388 properties: { 1465 properties: {
1389 color: color 1466 color: color
1390 } 1467 }
1391} = obj2 1468} = obj2
1392</pre> 1469```
1470
1393</YueDisplay> 1471</YueDisplay>
1394 1472
1395有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符: 1473有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符:
1396 1474
1397```moonscript 1475```yuescript
1398{:concat, :insert} = table 1476{:concat, :insert} = table
1399``` 1477```
1400<YueDisplay> 1478<YueDisplay>
1401<pre> 1479
1480```yue
1402{:concat, :insert} = table 1481{:concat, :insert} = table
1403</pre> 1482```
1483
1404</YueDisplay> 1484</YueDisplay>
1405 1485
1406这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段: 1486这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段:
1407 1487
1408```moonscript 1488```yuescript
1409{:mix, :max, random: rand} = math 1489{:mix, :max, random: rand} = math
1410``` 1490```
1411<YueDisplay> 1491<YueDisplay>
1412<pre> 1492
1493```yue
1413{:mix, :max, random: rand} = math 1494{:mix, :max, random: rand} = math
1414</pre> 1495```
1496
1415</YueDisplay> 1497</YueDisplay>
1416 1498
1417在进行解构时,你可以指定默认值,如: 1499在进行解构时,你可以指定默认值,如:
1418 1500
1419```moonscript 1501```yuescript
1420{:name = "nameless", :job = "jobless"} = person 1502{:name = "nameless", :job = "jobless"} = person
1421``` 1503```
1422<YueDisplay> 1504<YueDisplay>
1423<pre> 1505
1506```yue
1424{:name = "nameless", :job = "jobless"} = person 1507{:name = "nameless", :job = "jobless"} = person
1425</pre> 1508```
1509
1426</YueDisplay> 1510</YueDisplay>
1427 1511
1428在进行列表解构时,你可以使用`_`作为占位符: 1512在进行列表解构时,你可以使用`_`作为占位符:
1429 1513
1430```moonscript 1514```yuescript
1431[_, two, _, four] = items 1515[_, two, _, four] = items
1432``` 1516```
1433<YueDisplay> 1517<YueDisplay>
1434<pre> 1518
1519```yue
1435[_, two, _, four] = items 1520[_, two, _, four] = items
1436</pre> 1521```
1522
1437</YueDisplay> 1523</YueDisplay>
1438 1524
1439### 范围解构 1525### 范围解构
1440 1526
1441你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。 1527你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
1442 1528
1443```moonscript 1529```yuescript
1444orders = ["first", "second", "third", "fourth", "last"] 1530orders = ["first", "second", "third", "fourth", "last"]
1445[first, ...bulk, last] = orders 1531[first, ...bulk, last] = orders
1446print first -- 打印: first 1532print first -- 打印: first
@@ -1448,18 +1534,20 @@ print bulk -- 打印: {"second", "third", "fourth"}
1448print last -- 打印: last 1534print last -- 打印: last
1449``` 1535```
1450<YueDisplay> 1536<YueDisplay>
1451<pre> 1537
1538```yue
1452orders = ["first", "second", "third", "fourth", "last"] 1539orders = ["first", "second", "third", "fourth", "last"]
1453[first, ...bulk, last] = orders 1540[first, ...bulk, last] = orders
1454print first -- 打印: first 1541print first -- 打印: first
1455print bulk -- 打印: {"second", "third", "fourth"} 1542print bulk -- 打印: {"second", "third", "fourth"}
1456print last -- 打印: last 1543print last -- 打印: last
1457</pre> 1544```
1545
1458</YueDisplay> 1546</YueDisplay>
1459 1547
1460展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获: 1548展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
1461 1549
1462```moonscript 1550```yuescript
1463-- 捕获第一个元素之后的所有元素 1551-- 捕获第一个元素之后的所有元素
1464[first, ...rest] = orders 1552[first, ...rest] = orders
1465 1553
@@ -1470,7 +1558,8 @@ print last -- 打印: last
1470[first, ..._, last] = orders 1558[first, ..._, last] = orders
1471``` 1559```
1472<YueDisplay> 1560<YueDisplay>
1473<pre> 1561
1562```yue
1474-- 捕获第一个元素之后的所有元素 1563-- 捕获第一个元素之后的所有元素
1475[first, ...rest] = orders 1564[first, ...rest] = orders
1476 1565
@@ -1479,14 +1568,15 @@ print last -- 打印: last
1479 1568
1480-- 跳过中间的元素,只捕获第一个和最后一个元素 1569-- 跳过中间的元素,只捕获第一个和最后一个元素
1481[first, ..._, last] = orders 1570[first, ..._, last] = orders
1482</pre> 1571```
1572
1483</YueDisplay> 1573</YueDisplay>
1484 1574
1485### 在其它地方的解构赋值 1575### 在其它地方的解构赋值
1486 1576
1487解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中: 1577解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中:
1488 1578
1489```moonscript 1579```yuescript
1490tuples = [ 1580tuples = [
1491 ["hello", "world"] 1581 ["hello", "world"]
1492 ["egg", "head"] 1582 ["egg", "head"]
@@ -1496,7 +1586,8 @@ for [left, right] in *tuples
1496 print left, right 1586 print left, right
1497``` 1587```
1498<YueDisplay> 1588<YueDisplay>
1499<pre> 1589
1590```yue
1500tuples = [ 1591tuples = [
1501 ["hello", "world"] 1592 ["hello", "world"]
1502 ["egg", "head"] 1593 ["egg", "head"]
@@ -1504,7 +1595,8 @@ tuples = [
1504 1595
1505for [left, right] in *tuples 1596for [left, right] in *tuples
1506 print left, right 1597 print left, right
1507</pre> 1598```
1599
1508</YueDisplay> 1600</YueDisplay>
1509 1601
1510我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。 1602我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。
@@ -1513,18 +1605,20 @@ for [left, right] in *tuples
1513 1605
1514`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。 1606`if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。
1515 1607
1516```moonscript 1608```yuescript
1517if user := database.find_user "moon" 1609if user := database.find_user "moon"
1518 print user.name 1610 print user.name
1519``` 1611```
1520<YueDisplay> 1612<YueDisplay>
1521<pre> 1613
1614```yue
1522if user := database.find_user "moon" 1615if user := database.find_user "moon"
1523 print user.name 1616 print user.name
1524</pre> 1617```
1618
1525</YueDisplay> 1619</YueDisplay>
1526 1620
1527```moonscript 1621```yuescript
1528if hello := os.getenv "hello" 1622if hello := os.getenv "hello"
1529 print "你有 hello", hello 1623 print "你有 hello", hello
1530elseif world := os.getenv "world" 1624elseif world := os.getenv "world"
@@ -1533,50 +1627,56 @@ else
1533 print "什么都没有 :(" 1627 print "什么都没有 :("
1534``` 1628```
1535<YueDisplay> 1629<YueDisplay>
1536<pre> 1630
1631```yue
1537if hello := os.getenv "hello" 1632if hello := os.getenv "hello"
1538 print "你有 hello", hello 1633 print "你有 hello", hello
1539elseif world := os.getenv "world" 1634elseif world := os.getenv "world"
1540 print "你有 world", world 1635 print "你有 world", world
1541else 1636else
1542 print "什么都没有 :(" 1637 print "什么都没有 :("
1543</pre> 1638```
1639
1544</YueDisplay> 1640</YueDisplay>
1545 1641
1546使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。 1642使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。
1547```moonscript 1643```yuescript
1548if success, result := pcall -> "无报错地获取结果" 1644if success, result := pcall -> "无报错地获取结果"
1549 print result -- 变量 result 是有作用域的 1645 print result -- 变量 result 是有作用域的
1550print "好的" 1646print "好的"
1551``` 1647```
1552<YueDisplay> 1648<YueDisplay>
1553<pre> 1649
1650```yue
1554if success, result := pcall -> "无报错地获取结果" 1651if success, result := pcall -> "无报错地获取结果"
1555 print result -- 变量 result 是有作用域的 1652 print result -- 变量 result 是有作用域的
1556print "好的" 1653print "好的"
1557</pre> 1654```
1655
1558</YueDisplay> 1656</YueDisplay>
1559 1657
1560### While 赋值 1658### While 赋值
1561 1659
1562你可以在 while 循环中同样使用赋值来获取循环条件的值。 1660你可以在 while 循环中同样使用赋值来获取循环条件的值。
1563```moonscript 1661```yuescript
1564while byte := stream\read_one! 1662while byte := stream\read_one!
1565 -- 对 byte 做一些操作 1663 -- 对 byte 做一些操作
1566 print byte 1664 print byte
1567``` 1665```
1568<YueDisplay> 1666<YueDisplay>
1569<pre> 1667
1668```yue
1570while byte := stream\read_one! 1669while byte := stream\read_one!
1571 -- 对 byte 做一些操作 1670 -- 对 byte 做一些操作
1572 print byte 1671 print byte
1573</pre> 1672```
1673
1574</YueDisplay> 1674</YueDisplay>
1575 1675
1576## 可变参数赋值 1676## 可变参数赋值
1577 1677
1578你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。 1678你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。
1579```moonscript 1679```yuescript
1580list = [1, 2, 3, 4, 5] 1680list = [1, 2, 3, 4, 5]
1581fn = (ok) -> ok, table.unpack list 1681fn = (ok) -> ok, table.unpack list
1582ok, ... = fn true 1682ok, ... = fn true
@@ -1585,14 +1685,16 @@ first = select 1, ...
1585print ok, count, first 1685print ok, count, first
1586``` 1686```
1587<YueDisplay> 1687<YueDisplay>
1588<pre> 1688
1689```yue
1589list = [1, 2, 3, 4, 5] 1690list = [1, 2, 3, 4, 5]
1590fn = (ok) -> ok, table.unpack list 1691fn = (ok) -> ok, table.unpack list
1591ok, ... = fn true 1692ok, ... = fn true
1592count = select '#', ... 1693count = select '#', ...
1593first = select 1, ... 1694first = select 1, ...
1594print ok, count, first 1695print ok, count, first
1595</pre> 1696```
1697
1596</YueDisplay> 1698</YueDisplay>
1597 1699
1598## 空白 1700## 空白
@@ -1603,19 +1705,21 @@ print ok, count, first
1603 1705
1604一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句: 1706一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句:
1605 1707
1606```moonscript 1708```yuescript
1607a = 1; b = 2; print a + b 1709a = 1; b = 2; print a + b
1608``` 1710```
1609<YueDisplay> 1711<YueDisplay>
1610<pre> 1712
1713```yue
1611a = 1; b = 2; print a + b 1714a = 1; b = 2; print a + b
1612</pre> 1715```
1716
1613</YueDisplay> 1717</YueDisplay>
1614 1718
1615### 多行链式调用 1719### 多行链式调用
1616 1720
1617你可以使用相同的缩进来编写多行链式函数调用。 1721你可以使用相同的缩进来编写多行链式函数调用。
1618```moonscript 1722```yuescript
1619Rx.Observable 1723Rx.Observable
1620 .fromRange 1, 8 1724 .fromRange 1, 8
1621 \filter (x) -> x % 2 == 0 1725 \filter (x) -> x % 2 == 0
@@ -1624,19 +1728,21 @@ Rx.Observable
1624 \subscribe print 1728 \subscribe print
1625``` 1729```
1626<YueDisplay> 1730<YueDisplay>
1627<pre> 1731
1732```yue
1628Rx.Observable 1733Rx.Observable
1629 .fromRange 1, 8 1734 .fromRange 1, 8
1630 \filter (x) -> x % 2 == 0 1735 \filter (x) -> x % 2 == 0
1631 \concat Rx.Observable.of 'who do we appreciate' 1736 \concat Rx.Observable.of 'who do we appreciate'
1632 \map (value) -> value .. '!' 1737 \map (value) -> value .. '!'
1633 \subscribe print 1738 \subscribe print
1634</pre> 1739```
1740
1635</YueDisplay> 1741</YueDisplay>
1636 1742
1637## 注释 1743## 注释
1638 1744
1639```moonscript 1745```yuescript
1640-- 我是一个注释 1746-- 我是一个注释
1641 1747
1642str = --[[ 1748str = --[[
@@ -1649,7 +1755,8 @@ str = --[[
1649func --[[端口]] 3000, --[[ip]] "192.168.1.1" 1755func --[[端口]] 3000, --[[ip]] "192.168.1.1"
1650``` 1756```
1651<YueDisplay> 1757<YueDisplay>
1652<pre> 1758
1759```yue
1653-- 我是一个注释 1760-- 我是一个注释
1654 1761
1655str = --[[ 1762str = --[[
@@ -1660,14 +1767,15 @@ str = --[[
1660 .. strC 1767 .. strC
1661 1768
1662func --[[端口]] 3000, --[[ip]] "192.168.1.1" 1769func --[[端口]] 3000, --[[ip]] "192.168.1.1"
1663</pre> 1770```
1771
1664</YueDisplay> 1772</YueDisplay>
1665 1773
1666## 错误处理 1774## 错误处理
1667 1775
1668用于统一进行 Lua 错误处理的便捷语法。 1776用于统一进行 Lua 错误处理的便捷语法。
1669 1777
1670```moonscript 1778```yuescript
1671try 1779try
1672 func 1, 2, 3 1780 func 1, 2, 3
1673catch err 1781catch err
@@ -1695,7 +1803,8 @@ catch err
1695 print result 1803 print result
1696``` 1804```
1697<YueDisplay> 1805<YueDisplay>
1698<pre> 1806
1807```yue
1699try 1808try
1700 func 1, 2, 3 1809 func 1, 2, 3
1701catch err 1810catch err
@@ -1721,14 +1830,15 @@ if success, result := try func 1, 2, 3
1721catch err 1830catch err
1722 print yue.traceback err 1831 print yue.traceback err
1723 print result 1832 print result
1724</pre> 1833```
1834
1725</YueDisplay> 1835</YueDisplay>
1726 1836
1727### 错误处理简化 1837### 错误处理简化
1728 1838
1729`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。 1839`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1730 1840
1731```moonscript 1841```yuescript
1732a, b, c = try? func! 1842a, b, c = try? func!
1733 1843
1734-- 与空值合并运算符一起使用 1844-- 与空值合并运算符一起使用
@@ -1746,7 +1856,8 @@ catch e
1746 e 1856 e
1747``` 1857```
1748<YueDisplay> 1858<YueDisplay>
1749<pre> 1859
1860```yue
1750a, b, c = try? func! 1861a, b, c = try? func!
1751 1862
1752-- 与空值合并运算符一起使用 1863-- 与空值合并运算符一起使用
@@ -1762,48 +1873,55 @@ f try?
1762catch e 1873catch e
1763 print e 1874 print e
1764 e 1875 e
1765</pre> 1876```
1877
1766</YueDisplay> 1878</YueDisplay>
1767 1879
1768## 属性 1880## 属性
1769 1881
1770月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。 1882月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。
1771 1883
1772```moonscript 1884```yuescript
1773const a = 123 1885const a = 123
1774close _ = <close>: -> print "超出范围。" 1886close _ = <close>: -> print "超出范围。"
1775``` 1887```
1776<YueDisplay> 1888<YueDisplay>
1777<pre> 1889
1890```yue
1778const a = 123 1891const a = 123
1779close _ = &lt;close&gt;: -> print "超出范围。" 1892close _ = <close>: -> print "超出范围。"
1780</pre> 1893```
1894
1781</YueDisplay> 1895</YueDisplay>
1782 1896
1783你可以对进行解构得到的变量标记为常量。 1897你可以对进行解构得到的变量标记为常量。
1784 1898
1785```moonscript 1899```yuescript
1786const {:a, :b, c, d} = tb 1900const {:a, :b, c, d} = tb
1787-- a = 1 1901-- a = 1
1788``` 1902```
1789<YueDisplay> 1903<YueDisplay>
1790<pre> 1904
1905```yue
1791const {:a, :b, c, d} = tb 1906const {:a, :b, c, d} = tb
1792-- a = 1 1907-- a = 1
1793</pre> 1908```
1909
1794</YueDisplay> 1910</YueDisplay>
1795 1911
1796你也可以声明全局变量为常量。 1912你也可以声明全局变量为常量。
1797 1913
1798```moonscript 1914```yuescript
1799global const Constant = 123 1915global const Constant = 123
1800-- Constant = 1 1916-- Constant = 1
1801``` 1917```
1802<YueDisplay> 1918<YueDisplay>
1803<pre> 1919
1920```yue
1804global const Constant = 123 1921global const Constant = 123
1805-- Constant = 1 1922-- Constant = 1
1806</pre> 1923```
1924
1807</YueDisplay> 1925</YueDisplay>
1808 1926
1809## 字面量 1927## 字面量
@@ -1812,7 +1930,7 @@ Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字
1812 1930
1813但与 Lua 不同的是,单引号和双引号字符串内部允许有换行: 1931但与 Lua 不同的是,单引号和双引号字符串内部允许有换行:
1814 1932
1815```moonscript 1933```yuescript
1816some_string = "这是一个字符串 1934some_string = "这是一个字符串
1817 并包括一个换行。" 1935 并包括一个换行。"
1818 1936
@@ -1821,39 +1939,43 @@ some_string = "这是一个字符串
1821print "我有#{math.random! * 100}%的把握。" 1939print "我有#{math.random! * 100}%的把握。"
1822``` 1940```
1823<YueDisplay> 1941<YueDisplay>
1824<pre> 1942
1943```yue
1825some_string = "这是一个字符串 1944some_string = "这是一个字符串
1826 并包括一个换行。" 1945 并包括一个换行。"
1827 1946
1828-- 使用#{}语法可以将表达式插入到字符串字面量中。 1947-- 使用#{}语法可以将表达式插入到字符串字面量中。
1829-- 字符串插值只在双引号字符串中可用。 1948-- 字符串插值只在双引号字符串中可用。
1830print "我有#{math.random! * 100}%的把握。" 1949print "我有#{math.random! * 100}%的把握。"
1831</pre> 1950```
1951
1832</YueDisplay> 1952</YueDisplay>
1833 1953
1834### 数字字面量 1954### 数字字面量
1835 1955
1836你可以在数字字面量中使用下划线来增加可读性。 1956你可以在数字字面量中使用下划线来增加可读性。
1837 1957
1838```moonscript 1958```yuescript
1839integer = 1_000_000 1959integer = 1_000_000
1840hex = 0xEF_BB_BF 1960hex = 0xEF_BB_BF
1841binary = 0B10011 1961binary = 0B10011
1842``` 1962```
1843<YueDisplay> 1963<YueDisplay>
1844 1964
1845<pre> 1965
1966```yue
1846integer = 1_000_000 1967integer = 1_000_000
1847hex = 0xEF_BB_BF 1968hex = 0xEF_BB_BF
1848binary = 0B10011 1969binary = 0B10011
1849</pre> 1970```
1971
1850</YueDisplay> 1972</YueDisplay>
1851 1973
1852### YAML 风格字符串 1974### YAML 风格字符串
1853 1975
1854使用 `|` 前缀标记一个多行 YAML 风格字符串: 1976使用 `|` 前缀标记一个多行 YAML 风格字符串:
1855 1977
1856```moonscript 1978```yuescript
1857str = | 1979str = |
1858 key: value 1980 key: value
1859 list: 1981 list:
@@ -1861,20 +1983,22 @@ str = |
1861 - #{expr} 1983 - #{expr}
1862``` 1984```
1863<YueDisplay> 1985<YueDisplay>
1864<pre> 1986
1987```yue
1865str = | 1988str = |
1866 key: value 1989 key: value
1867 list: 1990 list:
1868 - item1 1991 - item1
1869 - #{expr} 1992 - #{expr}
1870</pre> 1993```
1994
1871</YueDisplay> 1995</YueDisplay>
1872 1996
1873其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。 1997其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
1874 1998
1875YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。 1999YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
1876 2000
1877```moonscript 2001```yuescript
1878fn = -> 2002fn = ->
1879 str = | 2003 str = |
1880 foo: 2004 foo:
@@ -1882,50 +2006,56 @@ fn = ->
1882 return str 2006 return str
1883``` 2007```
1884<YueDisplay> 2008<YueDisplay>
1885<pre> 2009
2010```yue
1886fn = -> 2011fn = ->
1887 str = | 2012 str = |
1888 foo: 2013 foo:
1889 bar: baz 2014 bar: baz
1890 return str 2015 return str
1891</pre> 2016```
2017
1892</YueDisplay> 2018</YueDisplay>
1893 2019
1894输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。 2020输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
1895 2021
1896支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义: 2022支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
1897 2023
1898```moonscript 2024```yuescript
1899str = | 2025str = |
1900 path: "C:\Program Files\App" 2026 path: "C:\Program Files\App"
1901 note: 'He said: "#{Hello}!"' 2027 note: 'He said: "#{Hello}!"'
1902``` 2028```
1903<YueDisplay> 2029<YueDisplay>
1904<pre> 2030
2031```yue
1905str = | 2032str = |
1906 path: "C:\Program Files\App" 2033 path: "C:\Program Files\App"
1907 note: 'He said: "#{Hello}!"' 2034 note: 'He said: "#{Hello}!"'
1908</pre> 2035```
2036
1909</YueDisplay> 2037</YueDisplay>
1910 2038
1911## 函数字面量 2039## 函数字面量
1912 2040
1913所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。 2041所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。
1914 2042
1915```moonscript 2043```yuescript
1916my_function = -> 2044my_function = ->
1917my_function() -- 调用空函数 2045my_function() -- 调用空函数
1918``` 2046```
1919<YueDisplay> 2047<YueDisplay>
1920<pre> 2048
2049```yue
1921my_function = -> 2050my_function = ->
1922my_function() -- 调用空函数 2051my_function() -- 调用空函数
1923</pre> 2052```
2053
1924</YueDisplay> 2054</YueDisplay>
1925 2055
1926函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句: 2056函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句:
1927 2057
1928```moonscript 2058```yuescript
1929func_a = -> print "你好,世界" 2059func_a = -> print "你好,世界"
1930 2060
1931func_b = -> 2061func_b = ->
@@ -1933,147 +2063,169 @@ func_b = ->
1933 print "这个值是:", value 2063 print "这个值是:", value
1934``` 2064```
1935<YueDisplay> 2065<YueDisplay>
1936<pre> 2066
2067```yue
1937func_a = -> print "你好,世界" 2068func_a = -> print "你好,世界"
1938 2069
1939func_b = -> 2070func_b = ->
1940 value = 100 2071 value = 100
1941 print "这个值是:", value 2072 print "这个值是:", value
1942</pre> 2073```
2074
1943</YueDisplay> 2075</YueDisplay>
1944 2076
1945如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。 2077如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。
1946 2078
1947```moonscript 2079```yuescript
1948func_a! 2080func_a!
1949func_b() 2081func_b()
1950``` 2082```
1951<YueDisplay> 2083<YueDisplay>
1952<pre> 2084
2085```yue
1953func_a! 2086func_a!
1954func_b() 2087func_b()
1955</pre> 2088```
2089
1956</YueDisplay> 2090</YueDisplay>
1957 2091
1958带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建: 2092带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建:
1959 2093
1960```moonscript 2094```yuescript
1961sum = (x, y) -> print "数字的和", x + y 2095sum = (x, y) -> print "数字的和", x + y
1962``` 2096```
1963<YueDisplay> 2097<YueDisplay>
1964<pre> 2098
2099```yue
1965sum = (x, y) -> print "数字的和", x + y 2100sum = (x, y) -> print "数字的和", x + y
1966</pre> 2101```
2102
1967</YueDisplay> 2103</YueDisplay>
1968 2104
1969函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。 2105函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。
1970 2106
1971```moonscript 2107```yuescript
1972sum 10, 20 2108sum 10, 20
1973print sum 10, 20 2109print sum 10, 20
1974 2110
1975a b c "a", "b", "c" 2111a b c "a", "b", "c"
1976``` 2112```
1977<YueDisplay> 2113<YueDisplay>
1978<pre> 2114
2115```yue
1979sum 10, 20 2116sum 10, 20
1980print sum 10, 20 2117print sum 10, 20
1981 2118
1982a b c "a", "b", "c" 2119a b c "a", "b", "c"
1983</pre> 2120```
2121
1984</YueDisplay> 2122</YueDisplay>
1985 2123
1986为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。 2124为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。
1987 2125
1988```moonscript 2126```yuescript
1989print "x:", sum(10, 20), "y:", sum(30, 40) 2127print "x:", sum(10, 20), "y:", sum(30, 40)
1990``` 2128```
1991<YueDisplay> 2129<YueDisplay>
1992<pre> 2130
2131```yue
1993print "x:", sum(10, 20), "y:", sum(30, 40) 2132print "x:", sum(10, 20), "y:", sum(30, 40)
1994</pre> 2133```
2134
1995</YueDisplay> 2135</YueDisplay>
1996 2136
1997注意:函数名与开始括号之间不能有任何空格。 2137注意:函数名与开始括号之间不能有任何空格。
1998 2138
1999函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回: 2139函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回:
2000 2140
2001```moonscript 2141```yuescript
2002sum = (x, y) -> x + y 2142sum = (x, y) -> x + y
2003print "数字的和是", sum 10, 20 2143print "数字的和是", sum 10, 20
2004``` 2144```
2005<YueDisplay> 2145<YueDisplay>
2006<pre> 2146
2147```yue
2007sum = (x, y) -> x + y 2148sum = (x, y) -> x + y
2008print "数字的和是", sum 10, 20 2149print "数字的和是", sum 10, 20
2009</pre> 2150```
2151
2010</YueDisplay> 2152</YueDisplay>
2011 2153
2012如果你需要做显式返回,可以使用 return 关键字: 2154如果你需要做显式返回,可以使用 return 关键字:
2013 2155
2014```moonscript 2156```yuescript
2015sum = (x, y) -> return x + y 2157sum = (x, y) -> return x + y
2016``` 2158```
2017<YueDisplay> 2159<YueDisplay>
2018<pre> 2160
2161```yue
2019sum = (x, y) -> return x + y 2162sum = (x, y) -> return x + y
2020</pre> 2163```
2164
2021</YueDisplay> 2165</YueDisplay>
2022 2166
2023就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表: 2167就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表:
2024 2168
2025```moonscript 2169```yuescript
2026mystery = (x, y) -> x + y, x - y 2170mystery = (x, y) -> x + y, x - y
2027a, b = mystery 10, 20 2171a, b = mystery 10, 20
2028``` 2172```
2029<YueDisplay> 2173<YueDisplay>
2030<pre> 2174
2175```yue
2031mystery = (x, y) -> x + y, x - y 2176mystery = (x, y) -> x + y, x - y
2032a, b = mystery 10, 20 2177a, b = mystery 10, 20
2033</pre> 2178```
2179
2034</YueDisplay> 2180</YueDisplay>
2035 2181
2036### 粗箭头 2182### 粗箭头
2037 2183
2038因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。 2184因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。
2039 2185
2040```moonscript 2186```yuescript
2041func = (num) => @value + num 2187func = (num) => @value + num
2042``` 2188```
2043<YueDisplay> 2189<YueDisplay>
2044<pre> 2190
2191```yue
2045func = (num) => @value + num 2192func = (num) => @value + num
2046</pre> 2193```
2194
2047</YueDisplay> 2195</YueDisplay>
2048 2196
2049### 参数默认值 2197### 参数默认值
2050 2198
2051可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。 2199可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。
2052 2200
2053```moonscript 2201```yuescript
2054my_function = (name = "某物", height = 100) -> 2202my_function = (name = "某物", height = 100) ->
2055 print "你好,我是", name 2203 print "你好,我是", name
2056 print "我的高度是", height 2204 print "我的高度是", height
2057``` 2205```
2058<YueDisplay> 2206<YueDisplay>
2059<pre> 2207
2208```yue
2060my_function = (name = "某物", height = 100) -> 2209my_function = (name = "某物", height = 100) ->
2061 print "你好,我是", name 2210 print "你好,我是", name
2062 print "我的高度是", height 2211 print "我的高度是", height
2063</pre> 2212```
2213
2064</YueDisplay> 2214</YueDisplay>
2065 2215
2066函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。 2216函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。
2067 2217
2068```moonscript 2218```yuescript
2069some_args = (x = 100, y = x + 1000) -> 2219some_args = (x = 100, y = x + 1000) ->
2070 print x + y 2220 print x + y
2071``` 2221```
2072<YueDisplay> 2222<YueDisplay>
2073<pre> 2223
2224```yue
2074some_args = (x = 100, y = x + 1000) -> 2225some_args = (x = 100, y = x + 1000) ->
2075 print x + y 2226 print x + y
2076</pre> 2227```
2228
2077</YueDisplay> 2229</YueDisplay>
2078 2230
2079### 多行参数 2231### 多行参数
@@ -2082,7 +2234,7 @@ some_args = (x = 100, y = x + 1000) ->
2082 2234
2083如果要将参数列表写到下一行,那么当前行必须以逗号结束。并且下一行的缩进必须比当前的缩进多。一旦做了参数的缩进,所有其他参数列表的行必须保持相同的缩进级别,以成为参数列表的一部分。 2235如果要将参数列表写到下一行,那么当前行必须以逗号结束。并且下一行的缩进必须比当前的缩进多。一旦做了参数的缩进,所有其他参数列表的行必须保持相同的缩进级别,以成为参数列表的一部分。
2084 2236
2085```moonscript 2237```yuescript
2086my_func 5, 4, 3, 2238my_func 5, 4, 3,
2087 8, 9, 10 2239 8, 9, 10
2088 2240
@@ -2092,7 +2244,8 @@ cool_func 1, 2,
2092 7, 8 2244 7, 8
2093``` 2245```
2094<YueDisplay> 2246<YueDisplay>
2095<pre> 2247
2248```yue
2096my_func 5, 4, 3, 2249my_func 5, 4, 3,
2097 8, 9, 10 2250 8, 9, 10
2098 2251
@@ -2100,29 +2253,32 @@ cool_func 1, 2,
2100 3, 4, 2253 3, 4,
2101 5, 6, 2254 5, 6,
2102 7, 8 2255 7, 8
2103</pre> 2256```
2257
2104</YueDisplay> 2258</YueDisplay>
2105 2259
2106这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。 2260这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。
2107 2261
2108```moonscript 2262```yuescript
2109my_func 5, 6, 7, 2263my_func 5, 6, 7,
2110 6, another_func 6, 7, 8, 2264 6, another_func 6, 7, 8,
2111 9, 1, 2, 2265 9, 1, 2,
2112 5, 4 2266 5, 4
2113``` 2267```
2114<YueDisplay> 2268<YueDisplay>
2115<pre> 2269
2270```yue
2116my_func 5, 6, 7, 2271my_func 5, 6, 7,
2117 6, another_func 6, 7, 8, 2272 6, another_func 6, 7, 8,
2118 9, 1, 2, 2273 9, 1, 2,
2119 5, 4 2274 5, 4
2120</pre> 2275```
2276
2121</YueDisplay> 2277</YueDisplay>
2122 2278
2123因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。 2279因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。
2124 2280
2125```moonscript 2281```yuescript
2126x = [ 2282x = [
2127 1, 2, 3, 4, a_func 4, 5, 2283 1, 2, 3, 4, a_func 4, 5,
2128 5, 6, 2284 5, 6,
@@ -2130,35 +2286,39 @@ x = [
2130] 2286]
2131``` 2287```
2132<YueDisplay> 2288<YueDisplay>
2133<pre> 2289
2290```yue
2134x = [ 2291x = [
2135 1, 2, 3, 4, a_func 4, 5, 2292 1, 2, 3, 4, a_func 4, 5,
2136 5, 6, 2293 5, 6,
2137 8, 9, 10 2294 8, 9, 10
2138] 2295]
2139</pre> 2296```
2297
2140</YueDisplay> 2298</YueDisplay>
2141 2299
2142有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。 2300有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。
2143 2301
2144```moonscript 2302```yuescript
2145y = [ my_func 1, 2, 3, 2303y = [ my_func 1, 2, 3,
2146 4, 5, 2304 4, 5,
2147 5, 6, 7 2305 5, 6, 7
2148] 2306]
2149``` 2307```
2150<YueDisplay> 2308<YueDisplay>
2151<pre> 2309
2310```yue
2152y = [ my_func 1, 2, 3, 2311y = [ my_func 1, 2, 3,
2153 4, 5, 2312 4, 5,
2154 5, 6, 7 2313 5, 6, 7
2155] 2314]
2156</pre> 2315```
2316
2157</YueDisplay> 2317</YueDisplay>
2158 2318
2159对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句: 2319对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句:
2160 2320
2161```moonscript 2321```yuescript
2162if func 1, 2, 3, 2322if func 1, 2, 3,
2163 "你好", 2323 "你好",
2164 "世界" 2324 "世界"
@@ -2172,7 +2332,8 @@ if func 1, 2, 3,
2172 print "我在if内部" 2332 print "我在if内部"
2173``` 2333```
2174<YueDisplay> 2334<YueDisplay>
2175<pre> 2335
2336```yue
2176if func 1, 2, 3, 2337if func 1, 2, 3,
2177 "你好", 2338 "你好",
2178 "世界" 2339 "世界"
@@ -2184,7 +2345,8 @@ if func 1, 2, 3,
2184 "世界" 2345 "世界"
2185 print "你好" 2346 print "你好"
2186 print "我在if内部" 2347 print "我在if内部"
2187</pre> 2348```
2349
2188</YueDisplay> 2350</YueDisplay>
2189 2351
2190### 参数解构 2352### 参数解构
@@ -2195,7 +2357,7 @@ if func 1, 2, 3,
2195 2357
2196- 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。 2358- 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。
2197 2359
2198```moonscript 2360```yuescript
2199f1 = (:a, :b, :c) -> 2361f1 = (:a, :b, :c) ->
2200 print a, b, c 2362 print a, b, c
2201 2363
@@ -2208,7 +2370,8 @@ arg1 = {a: 0}
2208f2 arg1, arg2 2370f2 arg1, arg2
2209``` 2371```
2210<YueDisplay> 2372<YueDisplay>
2211<pre> 2373
2374```yue
2212f1 = (:a, :b, :c) -> 2375f1 = (:a, :b, :c) ->
2213 print a, b, c 2376 print a, b, c
2214 2377
@@ -2219,14 +2382,15 @@ f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2219 2382
2220arg1 = {a: 0} 2383arg1 = {a: 0}
2221f2 arg1, arg2 2384f2 arg1, arg2
2222</pre> 2385```
2386
2223</YueDisplay> 2387</YueDisplay>
2224 2388
2225### 前置返回表达式 2389### 前置返回表达式
2226 2390
2227在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下: 2391在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
2228 2392
2229```moon 2393```yuescript
2230findFirstEven = (list): nil -> 2394findFirstEven = (list): nil ->
2231 for item in *list 2395 for item in *list
2232 if type(item) == "table" 2396 if type(item) == "table"
@@ -2235,19 +2399,21 @@ findFirstEven = (list): nil ->
2235 return sub 2399 return sub
2236``` 2400```
2237<YueDisplay> 2401<YueDisplay>
2238<pre> 2402
2403```yue
2239findFirstEven = (list): nil -> 2404findFirstEven = (list): nil ->
2240 for item in *list 2405 for item in *list
2241 if type(item) == "table" 2406 if type(item) == "table"
2242 for sub in *item 2407 for sub in *item
2243 if sub % 2 == 0 2408 if sub % 2 == 0
2244 return sub 2409 return sub
2245</pre> 2410```
2411
2246</YueDisplay> 2412</YueDisplay>
2247 2413
2248这个写法等价于: 2414这个写法等价于:
2249 2415
2250```moon 2416```yuescript
2251findFirstEven = (list) -> 2417findFirstEven = (list) ->
2252 for item in *list 2418 for item in *list
2253 if type(item) == "table" 2419 if type(item) == "table"
@@ -2257,7 +2423,8 @@ findFirstEven = (list) ->
2257 nil 2423 nil
2258``` 2424```
2259<YueDisplay> 2425<YueDisplay>
2260<pre> 2426
2427```yue
2261findFirstEven = (list) -> 2428findFirstEven = (list) ->
2262 for item in *list 2429 for item in *list
2263 if type(item) == "table" 2430 if type(item) == "table"
@@ -2265,7 +2432,8 @@ findFirstEven = (list) ->
2265 if sub % 2 == 0 2432 if sub % 2 == 0
2266 return sub 2433 return sub
2267 nil 2434 nil
2268</pre> 2435```
2436
2269</YueDisplay> 2437</YueDisplay>
2270 2438
2271唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。 2439唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。
@@ -2274,7 +2442,7 @@ findFirstEven = (list) ->
2274 2442
2275你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。 2443你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。
2276 2444
2277```moonscript 2445```yuescript
2278f = (...t) -> 2446f = (...t) ->
2279 print "参数个数:", t.n 2447 print "参数个数:", t.n
2280 print "表长度:", #t 2448 print "表长度:", #t
@@ -2296,7 +2464,8 @@ process = (...args) ->
2296process 1, nil, 3, nil, 5 2464process 1, nil, 3, nil, 5
2297``` 2465```
2298<YueDisplay> 2466<YueDisplay>
2299<pre> 2467
2468```yue
2300f = (...t) -> 2469f = (...t) ->
2301 print "参数个数:", t.n 2470 print "参数个数:", t.n
2302 print "表长度:", #t 2471 print "表长度:", #t
@@ -2316,53 +2485,60 @@ process = (...args) ->
2316 sum 2485 sum
2317 2486
2318process 1, nil, 3, nil, 5 2487process 1, nil, 3, nil, 5
2319</pre> 2488```
2489
2320</YueDisplay> 2490</YueDisplay>
2321 2491
2322## 反向回调 2492## 反向回调
2323 2493
2324反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。 2494反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。
2325 2495
2326```moonscript 2496```yuescript
2327<- f 2497<- f
2328print "hello" 2498print "hello"
2329``` 2499```
2330<YueDisplay> 2500<YueDisplay>
2331<pre> 2501
2502```yue
2332<- f 2503<- f
2333print "hello" 2504print "hello"
2334</pre> 2505```
2506
2335</YueDisplay> 2507</YueDisplay>
2336 2508
2337月之脚本也提供了粗箭头反向回调函数。 2509月之脚本也提供了粗箭头反向回调函数。
2338 2510
2339```moonscript 2511```yuescript
2340<= f 2512<= f
2341print @value 2513print @value
2342``` 2514```
2343<YueDisplay> 2515<YueDisplay>
2344<pre> 2516
2517```yue
2345<= f 2518<= f
2346print @value 2519print @value
2347</pre> 2520```
2521
2348</YueDisplay> 2522</YueDisplay>
2349 2523
2350你可以通过一个占位符指定回调函数的传参位置。 2524你可以通过一个占位符指定回调函数的传参位置。
2351 2525
2352```moonscript 2526```yuescript
2353(x) <- map _, [1, 2, 3] 2527(x) <- map _, [1, 2, 3]
2354x * 2 2528x * 2
2355``` 2529```
2356<YueDisplay> 2530<YueDisplay>
2357<pre> 2531
2532```yue
2358(x) <- map _, [1, 2, 3] 2533(x) <- map _, [1, 2, 3]
2359x * 2 2534x * 2
2360</pre> 2535```
2536
2361</YueDisplay> 2537</YueDisplay>
2362 2538
2363如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。 2539如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
2364 2540
2365```moonscript 2541```yuescript
2366result, msg = do 2542result, msg = do
2367 data <- readAsync "文件名.txt" 2543 data <- readAsync "文件名.txt"
2368 print data 2544 print data
@@ -2371,32 +2547,36 @@ result, msg = do
2371print result, msg 2547print result, msg
2372``` 2548```
2373<YueDisplay> 2549<YueDisplay>
2374<pre> 2550
2551```yue
2375result, msg = do 2552result, msg = do
2376 data <- readAsync "文件名.txt" 2553 data <- readAsync "文件名.txt"
2377 print data 2554 print data
2378 info <- processAsync data 2555 info <- processAsync data
2379 check info 2556 check info
2380print result, msg 2557print result, msg
2381</pre> 2558```
2559
2382</YueDisplay> 2560</YueDisplay>
2383 2561
2384## 表格字面量 2562## 表格字面量
2385 2563
2386和 Lua 一样,表格可以通过花括号进行定义。 2564和 Lua 一样,表格可以通过花括号进行定义。
2387 2565
2388```moonscript 2566```yuescript
2389some_values = [1, 2, 3, 4] 2567some_values = [1, 2, 3, 4]
2390``` 2568```
2391<YueDisplay> 2569<YueDisplay>
2392<pre> 2570
2571```yue
2393some_values = [1, 2, 3, 4] 2572some_values = [1, 2, 3, 4]
2394</pre> 2573```
2574
2395</YueDisplay> 2575</YueDisplay>
2396 2576
2397但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。 2577但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。
2398 2578
2399```moonscript 2579```yuescript
2400some_values = { 2580some_values = {
2401 name: "Bill", 2581 name: "Bill",
2402 age: 200, 2582 age: 200,
@@ -2404,35 +2584,39 @@ some_values = {
2404} 2584}
2405``` 2585```
2406<YueDisplay> 2586<YueDisplay>
2407<pre> 2587
2588```yue
2408some_values = { 2589some_values = {
2409 name: "Bill", 2590 name: "Bill",
2410 age: 200, 2591 age: 200,
2411 ["favorite food"]: "rice" 2592 ["favorite food"]: "rice"
2412} 2593}
2413</pre> 2594```
2595
2414</YueDisplay> 2596</YueDisplay>
2415 2597
2416如果只分配一个键值对的表格,可以省略花括号。 2598如果只分配一个键值对的表格,可以省略花括号。
2417 2599
2418```moonscript 2600```yuescript
2419profile = 2601profile =
2420 height: "4英尺", 2602 height: "4英尺",
2421 shoe_size: 13, 2603 shoe_size: 13,
2422 favorite_foods: ["冰淇淋", "甜甜圈"] 2604 favorite_foods: ["冰淇淋", "甜甜圈"]
2423``` 2605```
2424<YueDisplay> 2606<YueDisplay>
2425<pre> 2607
2608```yue
2426profile = 2609profile =
2427 height: "4英尺", 2610 height: "4英尺",
2428 shoe_size: 13, 2611 shoe_size: 13,
2429 favorite_foods: ["冰淇淋", "甜甜圈"] 2612 favorite_foods: ["冰淇淋", "甜甜圈"]
2430</pre> 2613```
2614
2431</YueDisplay> 2615</YueDisplay>
2432 2616
2433可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值: 2617可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值:
2434 2618
2435```moonscript 2619```yuescript
2436values = { 2620values = {
2437 1, 2, 3, 4 2621 1, 2, 3, 4
2438 5, 6, 7, 8 2622 5, 6, 7, 8
@@ -2441,51 +2625,57 @@ values = {
2441} 2625}
2442``` 2626```
2443<YueDisplay> 2627<YueDisplay>
2444<pre> 2628
2629```yue
2445values = { 2630values = {
2446 1, 2, 3, 4 2631 1, 2, 3, 4
2447 5, 6, 7, 8 2632 5, 6, 7, 8
2448 name: "超人" 2633 name: "超人"
2449 occupation: "打击犯罪" 2634 occupation: "打击犯罪"
2450} 2635}
2451</pre> 2636```
2637
2452</YueDisplay> 2638</YueDisplay>
2453 2639
2454创建单行表格字面量时,也可以省略花括号: 2640创建单行表格字面量时,也可以省略花括号:
2455 2641
2456```moonscript 2642```yuescript
2457my_function dance: "探戈", partner: "无" 2643my_function dance: "探戈", partner: "无"
2458 2644
2459y = type: "狗", legs: 4, tails: 1 2645y = type: "狗", legs: 4, tails: 1
2460``` 2646```
2461<YueDisplay> 2647<YueDisplay>
2462<pre> 2648
2649```yue
2463my_function dance: "探戈", partner: "无" 2650my_function dance: "探戈", partner: "无"
2464 2651
2465y = type: "狗", legs: 4, tails: 1 2652y = type: "狗", legs: 4, tails: 1
2466</pre> 2653```
2654
2467</YueDisplay> 2655</YueDisplay>
2468 2656
2469表格字面量的键可以使用 Lua 语言的关键字,而无需转义: 2657表格字面量的键可以使用 Lua 语言的关键字,而无需转义:
2470 2658
2471```moonscript 2659```yuescript
2472tbl = { 2660tbl = {
2473 do: "某事" 2661 do: "某事"
2474 end: "饥饿" 2662 end: "饥饿"
2475} 2663}
2476``` 2664```
2477<YueDisplay> 2665<YueDisplay>
2478<pre> 2666
2667```yue
2479tbl = { 2668tbl = {
2480 do: "某事" 2669 do: "某事"
2481 end: "饥饿" 2670 end: "饥饿"
2482} 2671}
2483</pre> 2672```
2673
2484</YueDisplay> 2674</YueDisplay>
2485 2675
2486如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符: 2676如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符:
2487 2677
2488```moonscript 2678```yuescript
2489hair = "金色" 2679hair = "金色"
2490height = 200 2680height = 200
2491person = { :hair, :height, shoe_size: 40 } 2681person = { :hair, :height, shoe_size: 40 }
@@ -2493,43 +2683,49 @@ person = { :hair, :height, shoe_size: 40 }
2493print_table :hair, :height 2683print_table :hair, :height
2494``` 2684```
2495<YueDisplay> 2685<YueDisplay>
2496<pre> 2686
2687```yue
2497hair = "金色" 2688hair = "金色"
2498height = 200 2689height = 200
2499person = { :hair, :height, shoe_size: 40 } 2690person = { :hair, :height, shoe_size: 40 }
2500 2691
2501print_table :hair, :height 2692print_table :hair, :height
2502</pre> 2693```
2694
2503</YueDisplay> 2695</YueDisplay>
2504 2696
2505如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。 2697如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。
2506 2698
2507```moonscript 2699```yuescript
2508t = { 2700t = {
2509 [1 + 2]: "你好" 2701 [1 + 2]: "你好"
2510 "你好 世界": true 2702 "你好 世界": true
2511} 2703}
2512``` 2704```
2513<YueDisplay> 2705<YueDisplay>
2514<pre> 2706
2707```yue
2515t = { 2708t = {
2516 [1 + 2]: "你好" 2709 [1 + 2]: "你好"
2517 "你好 世界": true 2710 "你好 世界": true
2518} 2711}
2519</pre> 2712```
2713
2520</YueDisplay> 2714</YueDisplay>
2521 2715
2522Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。 2716Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。
2523 2717
2524```moonscript 2718```yuescript
2525some_values = [ 1, 2, 3, 4 ] 2719some_values = [ 1, 2, 3, 4 ]
2526list_with_one_element = [ 1, ] 2720list_with_one_element = [ 1, ]
2527``` 2721```
2528<YueDisplay> 2722<YueDisplay>
2529<pre> 2723
2724```yue
2530some_values = [ 1, 2, 3, 4 ] 2725some_values = [ 1, 2, 3, 4 ]
2531list_with_one_element = [ 1, ] 2726list_with_one_element = [ 1, ]
2532</pre> 2727```
2728
2533</YueDisplay> 2729</YueDisplay>
2534 2730
2535## 推导式 2731## 推导式
@@ -2540,42 +2736,48 @@ list_with_one_element = [ 1, ]
2540 2736
2541以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。 2737以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。
2542 2738
2543```moonscript 2739```yuescript
2544items = [1, 2, 3, 4] 2740items = [1, 2, 3, 4]
2545doubled = [item * 2 for i, item in ipairs items] 2741doubled = [item * 2 for i, item in ipairs items]
2546``` 2742```
2547<YueDisplay> 2743<YueDisplay>
2548<pre> 2744
2745```yue
2549items = [1, 2, 3, 4] 2746items = [1, 2, 3, 4]
2550doubled = [item * 2 for i, item in ipairs items] 2747doubled = [item * 2 for i, item in ipairs items]
2551</pre> 2748```
2749
2552</YueDisplay> 2750</YueDisplay>
2553 2751
2554可以使用 `when` 子句筛选新表中包含的项目: 2752可以使用 `when` 子句筛选新表中包含的项目:
2555 2753
2556```moonscript 2754```yuescript
2557slice = [item for i, item in ipairs items when i > 1 and i < 3] 2755slice = [item for i, item in ipairs items when i > 1 and i < 3]
2558``` 2756```
2559<YueDisplay> 2757<YueDisplay>
2560<pre> 2758
2759```yue
2561slice = [item for i, item in ipairs items when i > 1 and i < 3] 2760slice = [item for i, item in ipairs items when i > 1 and i < 3]
2562</pre> 2761```
2762
2563</YueDisplay> 2763</YueDisplay>
2564 2764
2565因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为: 2765因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为:
2566 2766
2567```moonscript 2767```yuescript
2568doubled = [item * 2 for item in *items] 2768doubled = [item * 2 for item in *items]
2569``` 2769```
2570<YueDisplay> 2770<YueDisplay>
2571<pre> 2771
2772```yue
2572doubled = [item * 2 for item in *items] 2773doubled = [item * 2 for item in *items]
2573</pre> 2774```
2775
2574</YueDisplay> 2776</YueDisplay>
2575 2777
2576在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理: 2778在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
2577 2779
2578```moonscript 2780```yuescript
2579data = 2781data =
2580 a: [1, 2, 3] 2782 a: [1, 2, 3]
2581 b: [4, 5, 6] 2783 b: [4, 5, 6]
@@ -2584,21 +2786,23 @@ flat = [...v for k,v in pairs data]
2584-- flat 现在为 [1, 2, 3, 4, 5, 6] 2786-- flat 现在为 [1, 2, 3, 4, 5, 6]
2585``` 2787```
2586<YueDisplay> 2788<YueDisplay>
2587<pre> 2789
2790```yue
2588data = 2791data =
2589 a: [1, 2, 3] 2792 a: [1, 2, 3]
2590 b: [4, 5, 6] 2793 b: [4, 5, 6]
2591 2794
2592flat = [...v for k,v in pairs data] 2795flat = [...v for k,v in pairs data]
2593-- flat 现在为 [1, 2, 3, 4, 5, 6] 2796-- flat 现在为 [1, 2, 3, 4, 5, 6]
2594</pre> 2797```
2798
2595</YueDisplay> 2799</YueDisplay>
2596 2800
2597for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。 2801for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。
2598 2802
2599使用多个 for 子句与使用多重循环的效果相同: 2803使用多个 for 子句与使用多重循环的效果相同:
2600 2804
2601```moonscript 2805```yuescript
2602x_coords = [4, 5, 6, 7] 2806x_coords = [4, 5, 6, 7]
2603y_coords = [9, 2, 3] 2807y_coords = [9, 2, 3]
2604 2808
@@ -2606,24 +2810,28 @@ points = [ [x, y] for x in *x_coords \
2606for y in *y_coords] 2810for y in *y_coords]
2607``` 2811```
2608<YueDisplay> 2812<YueDisplay>
2609<pre> 2813
2814```yue
2610x_coords = [4, 5, 6, 7] 2815x_coords = [4, 5, 6, 7]
2611y_coords = [9, 2, 3] 2816y_coords = [9, 2, 3]
2612 2817
2613points = [ [x, y] for x in *x_coords \ 2818points = [ [x, y] for x in *x_coords \
2614for y in *y_coords] 2819for y in *y_coords]
2615</pre> 2820```
2821
2616</YueDisplay> 2822</YueDisplay>
2617 2823
2618在推导式中也可以使用简单的数值 for 循环: 2824在推导式中也可以使用简单的数值 for 循环:
2619 2825
2620```moonscript 2826```yuescript
2621evens = [i for i = 1, 100 when i % 2 == 0] 2827evens = [i for i = 1, 100 when i % 2 == 0]
2622``` 2828```
2623<YueDisplay> 2829<YueDisplay>
2624<pre> 2830
2831```yue
2625evens = [i for i = 1, 100 when i % 2 == 0] 2832evens = [i for i = 1, 100 when i % 2 == 0]
2626</pre> 2833```
2834
2627</YueDisplay> 2835</YueDisplay>
2628 2836
2629### 表格推导式 2837### 表格推导式
@@ -2632,7 +2840,7 @@ evens = [i for i = 1, 100 when i % 2 == 0]
2632 2840
2633以下示例生成了表格 thing 的副本: 2841以下示例生成了表格 thing 的副本:
2634 2842
2635```moonscript 2843```yuescript
2636thing = { 2844thing = {
2637 color: "red" 2845 color: "red"
2638 name: "fast" 2846 name: "fast"
@@ -2642,52 +2850,60 @@ thing = {
2642thing_copy = {k, v for k, v in pairs thing} 2850thing_copy = {k, v for k, v in pairs thing}
2643``` 2851```
2644<YueDisplay> 2852<YueDisplay>
2645<pre> 2853
2854```yue
2646thing = { 2855thing = {
2647 color: "red" 2856 color: "red"
2648 name: "fast" 2857 name: "fast"
2649 width: 123 2858 width: 123
2650} 2859}
2651 2860
2652thing_copy = {k, v for k, v in pairs thing} 2861thing_copy = \{k, v for k, v in pairs thing}
2653</pre> 2862```
2863
2654</YueDisplay> 2864</YueDisplay>
2655 2865
2656```moonscript 2866```yuescript
2657no_color = {k, v for k, v in pairs thing when k != "color"} 2867no_color = {k, v for k, v in pairs thing when k != "color"}
2658``` 2868```
2659<YueDisplay> 2869<YueDisplay>
2660<pre> 2870
2661no_color = {k, v for k, v in pairs thing when k != "color"} 2871```yue
2662</pre> 2872no_color = \{k, v for k, v in pairs thing when k != "color"}
2873```
2874
2663</YueDisplay> 2875</YueDisplay>
2664 2876
2665**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。 2877**\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。
2666 2878
2667```moonscript 2879```yuescript
2668numbers = [1, 2, 3, 4] 2880numbers = [1, 2, 3, 4]
2669sqrts = {i, math.sqrt i for i in *numbers} 2881sqrts = {i, math.sqrt i for i in *numbers}
2670``` 2882```
2671<YueDisplay> 2883<YueDisplay>
2672<pre> 2884
2885```yue
2673numbers = [1, 2, 3, 4] 2886numbers = [1, 2, 3, 4]
2674sqrts = {i, math.sqrt i for i in *numbers} 2887sqrts = \{i, math.sqrt i for i in *numbers}
2675</pre> 2888```
2889
2676</YueDisplay> 2890</YueDisplay>
2677 2891
2678表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值: 2892表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值:
2679 2893
2680在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。 2894在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。
2681 2895
2682```moonscript 2896```yuescript
2683tuples = [ ["hello", "world"], ["foo", "bar"]] 2897tuples = [ ["hello", "world"], ["foo", "bar"]]
2684tbl = {unpack tuple for tuple in *tuples} 2898tbl = {unpack tuple for tuple in *tuples}
2685``` 2899```
2686<YueDisplay> 2900<YueDisplay>
2687<pre> 2901
2902```yue
2688tuples = [ ["hello", "world"], ["foo", "bar"]] 2903tuples = [ ["hello", "world"], ["foo", "bar"]]
2689tbl = {unpack tuple for tuple in *tuples} 2904tbl = \{unpack tuple for tuple in *tuples}
2690</pre> 2905```
2906
2691</YueDisplay> 2907</YueDisplay>
2692 2908
2693### 切片 2909### 切片
@@ -2696,82 +2912,94 @@ tbl = {unpack tuple for tuple in *tuples}
2696 2912
2697下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目: 2913下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目:
2698 2914
2699```moonscript 2915```yuescript
2700slice = [item for item in *items[1, 5]] 2916slice = [item for item in *items[1, 5]]
2701``` 2917```
2702<YueDisplay> 2918<YueDisplay>
2703<pre> 2919
2920```yue
2704slice = [item for item in *items[1, 5]] 2921slice = [item for item in *items[1, 5]]
2705</pre> 2922```
2923
2706</YueDisplay> 2924</YueDisplay>
2707 2925
2708切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素: 2926切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素:
2709 2927
2710```moonscript 2928```yuescript
2711slice = [item for item in *items[2,]] 2929slice = [item for item in *items[2,]]
2712``` 2930```
2713<YueDisplay> 2931<YueDisplay>
2714<pre> 2932
2933```yue
2715slice = [item for item in *items[2,]] 2934slice = [item for item in *items[2,]]
2716</pre> 2935```
2936
2717</YueDisplay> 2937</YueDisplay>
2718 2938
2719如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …) 2939如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …)
2720 2940
2721```moonscript 2941```yuescript
2722slice = [item for item in *items[,,2]] 2942slice = [item for item in *items[,,2]]
2723``` 2943```
2724<YueDisplay> 2944<YueDisplay>
2725 2945
2726<pre> 2946
2947```yue
2727slice = [item for item in *items[,,2]] 2948slice = [item for item in *items[,,2]]
2728</pre> 2949```
2950
2729</YueDisplay> 2951</YueDisplay>
2730 2952
2731最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。 2953最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
2732 2954
2733```moonscript 2955```yuescript
2734-- 取最后4个元素 2956-- 取最后4个元素
2735slice = [item for item in *items[-4,-1]] 2957slice = [item for item in *items[-4,-1]]
2736``` 2958```
2737<YueDisplay> 2959<YueDisplay>
2738<pre> 2960
2961```yue
2739-- 取最后4个元素 2962-- 取最后4个元素
2740slice = [item for item in *items[-4,-1]] 2963slice = [item for item in *items[-4,-1]]
2741</pre> 2964```
2965
2742</YueDisplay> 2966</YueDisplay>
2743 2967
2744切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。 2968切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
2745 2969
2746```moonscript 2970```yuescript
2747reverse_slice = [item for item in *items[-1,1,-1]] 2971reverse_slice = [item for item in *items[-1,1,-1]]
2748``` 2972```
2749<YueDisplay> 2973<YueDisplay>
2750<pre> 2974
2975```yue
2751reverse_slice = [item for item in *items[-1,1,-1]] 2976reverse_slice = [item for item in *items[-1,1,-1]]
2752</pre> 2977```
2978
2753</YueDisplay> 2979</YueDisplay>
2754 2980
2755#### 切片表达式 2981#### 切片表达式
2756 2982
2757切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。 2983切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
2758 2984
2759```moonscript 2985```yuescript
2760-- 取第2和第4个元素作为新的列表 2986-- 取第2和第4个元素作为新的列表
2761sub_list = items[2, 4] 2987sub_list = items[2, 4]
2762``` 2988```
2763<YueDisplay> 2989<YueDisplay>
2764<pre> 2990
2991```yue
2765-- 取第2和第4个元素作为新的列表 2992-- 取第2和第4个元素作为新的列表
2766sub_list = items[2, 4] 2993sub_list = items[2, 4]
2767</pre> 2994```
2995
2768</YueDisplay> 2996</YueDisplay>
2769 2997
2770## for 循环 2998## for 循环
2771 2999
2772Lua 中有两种 for 循环形式,数字型和通用型: 3000Lua 中有两种 for 循环形式,数字型和通用型:
2773 3001
2774```moonscript 3002```yuescript
2775for i = 10, 20 3003for i = 10, 20
2776 print i 3004 print i
2777 3005
@@ -2782,7 +3010,8 @@ for key, value in pairs object
2782 print key, value 3010 print key, value
2783``` 3011```
2784<YueDisplay> 3012<YueDisplay>
2785<pre> 3013
3014```yue
2786for i = 10, 20 3015for i = 10, 20
2787 print i 3016 print i
2788 3017
@@ -2791,42 +3020,47 @@ for k = 1, 15, 2 -- 提供了一个遍历的步长
2791 3020
2792for key, value in pairs object 3021for key, value in pairs object
2793 print key, value 3022 print key, value
2794</pre> 3023```
3024
2795</YueDisplay> 3025</YueDisplay>
2796 3026
2797可以使用切片和 **\*** 操作符,就像在列表推导中一样: 3027可以使用切片和 **\*** 操作符,就像在列表推导中一样:
2798 3028
2799```moonscript 3029```yuescript
2800for item in *items[2, 4] 3030for item in *items[2, 4]
2801 print item 3031 print item
2802``` 3032```
2803<YueDisplay> 3033<YueDisplay>
2804<pre> 3034
3035```yue
2805for item in *items[2, 4] 3036for item in *items[2, 4]
2806 print item 3037 print item
2807</pre> 3038```
3039
2808</YueDisplay> 3040</YueDisplay>
2809 3041
2810当代码语句只有一行时,循环语句也都可以写作更短的语法: 3042当代码语句只有一行时,循环语句也都可以写作更短的语法:
2811 3043
2812```moonscript 3044```yuescript
2813for item in *items do print item 3045for item in *items do print item
2814 3046
2815for j = 1, 10, 3 do print j 3047for j = 1, 10, 3 do print j
2816``` 3048```
2817<YueDisplay> 3049<YueDisplay>
2818<pre> 3050
3051```yue
2819for item in *items do print item 3052for item in *items do print item
2820 3053
2821for j = 1, 10, 3 do print j 3054for j = 1, 10, 3 do print j
2822</pre> 3055```
3056
2823</YueDisplay> 3057</YueDisplay>
2824 3058
2825for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。 3059for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。
2826 3060
2827将每个偶数加倍: 3061将每个偶数加倍:
2828 3062
2829```moonscript 3063```yuescript
2830doubled_evens = for i = 1, 20 3064doubled_evens = for i = 1, 20
2831 if i % 2 == 0 3065 if i % 2 == 0
2832 i * 2 3066 i * 2
@@ -2834,35 +3068,39 @@ doubled_evens = for i = 1, 20
2834 i 3068 i
2835``` 3069```
2836<YueDisplay> 3070<YueDisplay>
2837<pre> 3071
3072```yue
2838doubled_evens = for i = 1, 20 3073doubled_evens = for i = 1, 20
2839 if i % 2 == 0 3074 if i % 2 == 0
2840 i * 2 3075 i * 2
2841 else 3076 else
2842 i 3077 i
2843</pre> 3078```
3079
2844</YueDisplay> 3080</YueDisplay>
2845 3081
2846此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。 3082此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
2847 3083
2848例如,查找第一个大于 10 的数字: 3084例如,查找第一个大于 10 的数字:
2849 3085
2850```moonscript 3086```yuescript
2851first_large = for n in *numbers 3087first_large = for n in *numbers
2852 break n if n > 10 3088 break n if n > 10
2853``` 3089```
2854<YueDisplay> 3090<YueDisplay>
2855<pre> 3091
3092```yue
2856first_large = for n in *numbers 3093first_large = for n in *numbers
2857 break n if n > 10 3094 break n if n > 10
2858</pre> 3095```
3096
2859</YueDisplay> 3097</YueDisplay>
2860 3098
2861你还可以结合 for 循环表达式与 continue 语句来过滤值。 3099你还可以结合 for 循环表达式与 continue 语句来过滤值。
2862 3100
2863注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。 3101注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。
2864 3102
2865```moonscript 3103```yuescript
2866func_a = -> for i = 1, 10 do print i 3104func_a = -> for i = 1, 10 do print i
2867func_b = -> return for i = 1, 10 do i 3105func_b = -> return for i = 1, 10 do i
2868 3106
@@ -2870,13 +3108,15 @@ print func_a! -- 打印 nil
2870print func_b! -- 打印 table 对象 3108print func_b! -- 打印 table 对象
2871``` 3109```
2872<YueDisplay> 3110<YueDisplay>
2873<pre> 3111
3112```yue
2874func_a = -> for i = 1, 10 do print i 3113func_a = -> for i = 1, 10 do print i
2875func_b = -> return for i = 1, 10 do i 3114func_b = -> return for i = 1, 10 do i
2876 3115
2877print func_a! -- 打印 nil 3116print func_a! -- 打印 nil
2878print func_b! -- 打印 table 对象 3117print func_b! -- 打印 table 对象
2879</pre> 3118```
3119
2880</YueDisplay> 3120</YueDisplay>
2881 3121
2882这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。 3122这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。
@@ -2885,7 +3125,7 @@ print func_b! -- 打印 table 对象
2885 3125
2886repeat 循环是从 Lua 语言中搬过来的相似语法: 3126repeat 循环是从 Lua 语言中搬过来的相似语法:
2887 3127
2888```moonscript 3128```yuescript
2889i = 10 3129i = 10
2890repeat 3130repeat
2891 print i 3131 print i
@@ -2893,20 +3133,22 @@ repeat
2893until i == 0 3133until i == 0
2894``` 3134```
2895<YueDisplay> 3135<YueDisplay>
2896<pre> 3136
3137```yue
2897i = 10 3138i = 10
2898repeat 3139repeat
2899 print i 3140 print i
2900 i -= 1 3141 i -= 1
2901until i == 0 3142until i == 0
2902</pre> 3143```
3144
2903</YueDisplay> 3145</YueDisplay>
2904 3146
2905## while 循环 3147## while 循环
2906 3148
2907在月之脚本中的 while 循环有四种写法: 3149在月之脚本中的 while 循环有四种写法:
2908 3150
2909```moonscript 3151```yuescript
2910i = 10 3152i = 10
2911while i > 0 3153while i > 0
2912 print i 3154 print i
@@ -2915,17 +3157,19 @@ while i > 0
2915while running == true do my_function! 3157while running == true do my_function!
2916``` 3158```
2917<YueDisplay> 3159<YueDisplay>
2918<pre> 3160
3161```yue
2919i = 10 3162i = 10
2920while i > 0 3163while i > 0
2921 print i 3164 print i
2922 i -= 1 3165 i -= 1
2923 3166
2924while running == true do my_function! 3167while running == true do my_function!
2925</pre> 3168```
3169
2926</YueDisplay> 3170</YueDisplay>
2927 3171
2928```moonscript 3172```yuescript
2929i = 10 3173i = 10
2930until i == 0 3174until i == 0
2931 print i 3175 print i
@@ -2934,13 +3178,15 @@ until i == 0
2934until running == false do my_function! 3178until running == false do my_function!
2935``` 3179```
2936<YueDisplay> 3180<YueDisplay>
2937<pre> 3181
3182```yue
2938i = 10 3183i = 10
2939until i == 0 3184until i == 0
2940 print i 3185 print i
2941 i -= 1 3186 i -= 1
2942until running == false do my_function! 3187until running == false do my_function!
2943</pre> 3188```
3189
2944</YueDisplay> 3190</YueDisplay>
2945 3191
2946像 for 循环的语法一样,while 循环也可以作为一个表达式使用。为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。 3192像 for 循环的语法一样,while 循环也可以作为一个表达式使用。为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。
@@ -2949,7 +3195,7 @@ until running == false do my_function!
2949 3195
2950继续语句可以用来跳出当前的循环迭代。 3196继续语句可以用来跳出当前的循环迭代。
2951 3197
2952```moonscript 3198```yuescript
2953i = 0 3199i = 0
2954while i < 10 3200while i < 10
2955 i += 1 3201 i += 1
@@ -2957,35 +3203,39 @@ while i < 10
2957 print i 3203 print i
2958``` 3204```
2959<YueDisplay> 3205<YueDisplay>
2960<pre> 3206
3207```yue
2961i = 0 3208i = 0
2962while i < 10 3209while i < 10
2963 i += 1 3210 i += 1
2964 continue if i % 2 == 0 3211 continue if i % 2 == 0
2965 print i 3212 print i
2966</pre> 3213```
3214
2967</YueDisplay> 3215</YueDisplay>
2968 3216
2969继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组: 3217继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组:
2970 3218
2971```moonscript 3219```yuescript
2972my_numbers = [1, 2, 3, 4, 5, 6] 3220my_numbers = [1, 2, 3, 4, 5, 6]
2973odds = for x in *my_numbers 3221odds = for x in *my_numbers
2974 continue if x % 2 == 1 3222 continue if x % 2 == 1
2975 x 3223 x
2976``` 3224```
2977<YueDisplay> 3225<YueDisplay>
2978<pre> 3226
3227```yue
2979my_numbers = [1, 2, 3, 4, 5, 6] 3228my_numbers = [1, 2, 3, 4, 5, 6]
2980odds = for x in *my_numbers 3229odds = for x in *my_numbers
2981 continue if x % 2 == 1 3230 continue if x % 2 == 1
2982 x 3231 x
2983</pre> 3232```
3233
2984</YueDisplay> 3234</YueDisplay>
2985 3235
2986## 条件语句 3236## 条件语句
2987 3237
2988```moonscript 3238```yuescript
2989have_coins = false 3239have_coins = false
2990if have_coins 3240if have_coins
2991 print "有硬币" 3241 print "有硬币"
@@ -2993,44 +3243,50 @@ else
2993 print "没有硬币" 3243 print "没有硬币"
2994``` 3244```
2995<YueDisplay> 3245<YueDisplay>
2996<pre> 3246
3247```yue
2997have_coins = false 3248have_coins = false
2998if have_coins 3249if have_coins
2999 print "有硬币" 3250 print "有硬币"
3000else 3251else
3001 print "没有硬币" 3252 print "没有硬币"
3002</pre> 3253```
3254
3003</YueDisplay> 3255</YueDisplay>
3004 3256
3005对于简单的语句,也可以使用简短的语法: 3257对于简单的语句,也可以使用简短的语法:
3006 3258
3007```moonscript 3259```yuescript
3008have_coins = false 3260have_coins = false
3009if have_coins then print "有硬币" else print "没有硬币" 3261if have_coins then print "有硬币" else print "没有硬币"
3010``` 3262```
3011<YueDisplay> 3263<YueDisplay>
3012<pre> 3264
3265```yue
3013have_coins = false 3266have_coins = false
3014if have_coins then print "有硬币" else print "没有硬币" 3267if have_coins then print "有硬币" else print "没有硬币"
3015</pre> 3268```
3269
3016</YueDisplay> 3270</YueDisplay>
3017 3271
3018因为if语句可以用作表达式,所以也可以这样写: 3272因为if语句可以用作表达式,所以也可以这样写:
3019 3273
3020```moonscript 3274```yuescript
3021have_coins = false 3275have_coins = false
3022print if have_coins then "有硬币" else "没有硬币" 3276print if have_coins then "有硬币" else "没有硬币"
3023``` 3277```
3024<YueDisplay> 3278<YueDisplay>
3025<pre> 3279
3280```yue
3026have_coins = false 3281have_coins = false
3027print if have_coins then "有硬币" else "没有硬币" 3282print if have_coins then "有硬币" else "没有硬币"
3028</pre> 3283```
3284
3029</YueDisplay> 3285</YueDisplay>
3030 3286
3031条件语句也可以作为表达式用在返回语句和赋值语句中: 3287条件语句也可以作为表达式用在返回语句和赋值语句中:
3032 3288
3033```moonscript 3289```yuescript
3034is_tall = (name) -> 3290is_tall = (name) ->
3035 if name == "Rob" 3291 if name == "Rob"
3036 true 3292 true
@@ -3045,7 +3301,8 @@ else
3045print message -- 打印: 我很高 3301print message -- 打印: 我很高
3046``` 3302```
3047<YueDisplay> 3303<YueDisplay>
3048<pre> 3304
3305```yue
3049is_tall = (name) -> 3306is_tall = (name) ->
3050 if name == "Rob" 3307 if name == "Rob"
3051 true 3308 true
@@ -3058,37 +3315,42 @@ else
3058 "我不是很高" 3315 "我不是很高"
3059 3316
3060print message -- 打印: 我很高 3317print message -- 打印: 我很高
3061</pre> 3318```
3319
3062</YueDisplay> 3320</YueDisplay>
3063 3321
3064if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”): 3322if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”):
3065 3323
3066```moonscript 3324```yuescript
3067unless os.date("%A") == "Monday" 3325unless os.date("%A") == "Monday"
3068 print "今天不是星期一!" 3326 print "今天不是星期一!"
3069``` 3327```
3070<YueDisplay> 3328<YueDisplay>
3071 3329
3072<pre> 3330
3331```yue
3073unless os.date("%A") == "Monday" 3332unless os.date("%A") == "Monday"
3074 print "今天不是星期一!" 3333 print "今天不是星期一!"
3075</pre> 3334```
3335
3076</YueDisplay> 3336</YueDisplay>
3077 3337
3078```moonscript 3338```yuescript
3079print "你真幸运!" unless math.random! > 0.1 3339print "你真幸运!" unless math.random! > 0.1
3080``` 3340```
3081<YueDisplay> 3341<YueDisplay>
3082<pre> 3342
3343```yue
3083print "你真幸运!" unless math.random! > 0.1 3344print "你真幸运!" unless math.random! > 0.1
3084</pre> 3345```
3346
3085</YueDisplay> 3347</YueDisplay>
3086 3348
3087### 范围表达式 3349### 范围表达式
3088 3350
3089你可以使用范围表达式来编写进行范围检查的代码。 3351你可以使用范围表达式来编写进行范围检查的代码。
3090 3352
3091```moonscript 3353```yuescript
3092a = 5 3354a = 5
3093 3355
3094if a in [1, 3, 5, 7] 3356if a in [1, 3, 5, 7]
@@ -3098,7 +3360,8 @@ if a in list
3098 print "检查`a`是否在列表中" 3360 print "检查`a`是否在列表中"
3099``` 3361```
3100<YueDisplay> 3362<YueDisplay>
3101<pre> 3363
3364```yue
3102a = 5 3365a = 5
3103 3366
3104if a in [1, 3, 5, 7] 3367if a in [1, 3, 5, 7]
@@ -3106,62 +3369,71 @@ if a in [1, 3, 5, 7]
3106 3369
3107if a in list 3370if a in list
3108 print "检查`a`是否在列表中" 3371 print "检查`a`是否在列表中"
3109</pre> 3372```
3373
3110</YueDisplay> 3374</YueDisplay>
3111 3375
3112```moonscript 3376```yuescript
3113print "你很幸运!" unless math.random! > 0.1 3377print "你很幸运!" unless math.random! > 0.1
3114``` 3378```
3115<YueDisplay> 3379<YueDisplay>
3116<pre> 3380
3381```yue
3117print "你很幸运!" unless math.random! > 0.1 3382print "你很幸运!" unless math.random! > 0.1
3118</pre> 3383```
3384
3119</YueDisplay> 3385</YueDisplay>
3120 3386
3121## 代码行修饰符 3387## 代码行修饰符
3122 3388
3123为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾: 3389为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾:
3124 3390
3125```moonscript 3391```yuescript
3126print "你好,世界" if name == "Rob" 3392print "你好,世界" if name == "Rob"
3127``` 3393```
3128<YueDisplay> 3394<YueDisplay>
3129<pre> 3395
3396```yue
3130print "你好,世界" if name == "Rob" 3397print "你好,世界" if name == "Rob"
3131</pre> 3398```
3399
3132</YueDisplay> 3400</YueDisplay>
3133 3401
3134修饰 for 循环的示例: 3402修饰 for 循环的示例:
3135 3403
3136```moonscript 3404```yuescript
3137print "项目: ", item for item in *items 3405print "项目: ", item for item in *items
3138``` 3406```
3139<YueDisplay> 3407<YueDisplay>
3140<pre> 3408
3409```yue
3141print "项目: ", item for item in *items 3410print "项目: ", item for item in *items
3142</pre> 3411```
3412
3143</YueDisplay> 3413</YueDisplay>
3144 3414
3145修饰 while 循环的示例: 3415修饰 while 循环的示例:
3146 3416
3147```moonscript 3417```yuescript
3148game\update! while game\isRunning! 3418game\update! while game\isRunning!
3149 3419
3150reader\parse_line! until reader\eof! 3420reader\parse_line! until reader\eof!
3151``` 3421```
3152<YueDisplay> 3422<YueDisplay>
3153<pre> 3423
3424```yue
3154game\update! while game\isRunning! 3425game\update! while game\isRunning!
3155 3426
3156reader\parse_line! until reader\eof! 3427reader\parse_line! until reader\eof!
3157</pre> 3428```
3429
3158</YueDisplay> 3430</YueDisplay>
3159 3431
3160## switch 语句 3432## switch 语句
3161 3433
3162switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。 3434switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。
3163 3435
3164```moonscript 3436```yuescript
3165switch name := "Dan" 3437switch name := "Dan"
3166 when "Robert" 3438 when "Robert"
3167 print "你是Robert" 3439 print "你是Robert"
@@ -3171,7 +3443,8 @@ switch name := "Dan"
3171 print "我不认识你,你的名字是#{name}" 3443 print "我不认识你,你的名字是#{name}"
3172``` 3444```
3173<YueDisplay> 3445<YueDisplay>
3174<pre> 3446
3447```yue
3175switch name := "Dan" 3448switch name := "Dan"
3176 when "Robert" 3449 when "Robert"
3177 print "你是Robert" 3450 print "你是Robert"
@@ -3179,14 +3452,15 @@ switch name := "Dan"
3179 print "你的名字是Dan" 3452 print "你的名字是Dan"
3180 else 3453 else
3181 print "我不认识你,你的名字是#{name}" 3454 print "我不认识你,你的名字是#{name}"
3182</pre> 3455```
3456
3183</YueDisplay> 3457</YueDisplay>
3184 3458
3185switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。 3459switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。
3186 3460
3187switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量: 3461switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量:
3188 3462
3189```moonscript 3463```yuescript
3190b = 1 3464b = 1
3191next_number = switch b 3465next_number = switch b
3192 when 1 3466 when 1
@@ -3197,7 +3471,8 @@ next_number = switch b
3197 error "数字数得太大了!" 3471 error "数字数得太大了!"
3198``` 3472```
3199<YueDisplay> 3473<YueDisplay>
3200<pre> 3474
3475```yue
3201b = 1 3476b = 1
3202next_number = switch b 3477next_number = switch b
3203 when 1 3478 when 1
@@ -3206,29 +3481,32 @@ next_number = switch b
3206 3 3481 3
3207 else 3482 else
3208 error "数字数得太大了!" 3483 error "数字数得太大了!"
3209</pre> 3484```
3485
3210</YueDisplay> 3486</YueDisplay>
3211 3487
3212我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。 3488我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。
3213 3489
3214```moonscript 3490```yuescript
3215msg = switch math.random(1, 5) 3491msg = switch math.random(1, 5)
3216 when 1 then "你很幸运" 3492 when 1 then "你很幸运"
3217 when 2 then "你差点很幸运" 3493 when 2 then "你差点很幸运"
3218 else "不太幸运" 3494 else "不太幸运"
3219``` 3495```
3220<YueDisplay> 3496<YueDisplay>
3221<pre> 3497
3498```yue
3222msg = switch math.random(1, 5) 3499msg = switch math.random(1, 5)
3223 when 1 then "你很幸运" 3500 when 1 then "你很幸运"
3224 when 2 then "你差点很幸运" 3501 when 2 then "你差点很幸运"
3225 else "不太幸运" 3502 else "不太幸运"
3226</pre> 3503```
3504
3227</YueDisplay> 3505</YueDisplay>
3228 3506
3229如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。 3507如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。
3230 3508
3231```moonscript 3509```yuescript
3232switch math.random(1, 5) 3510switch math.random(1, 5)
3233 when 1 3511 when 1
3234 print "你很幸运" -- 两个缩进级别 3512 print "你很幸运" -- 两个缩进级别
@@ -3241,7 +3519,8 @@ else
3241 print "不太幸运" 3519 print "不太幸运"
3242``` 3520```
3243<YueDisplay> 3521<YueDisplay>
3244<pre> 3522
3523```yue
3245switch math.random(1, 5) 3524switch math.random(1, 5)
3246 when 1 3525 when 1
3247 print "你很幸运" -- 两个缩进级别 3526 print "你很幸运" -- 两个缩进级别
@@ -3252,7 +3531,8 @@ switch math.random(1, 5) when 1
3252 print "你很幸运" -- 一个缩进级别 3531 print "你很幸运" -- 一个缩进级别
3253else 3532else
3254 print "不太幸运" 3533 print "不太幸运"
3255</pre> 3534```
3535
3256</YueDisplay> 3536</YueDisplay>
3257 3537
3258值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。 3538值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。
@@ -3261,7 +3541,7 @@ else
3261 3541
3262在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。 3542在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。
3263 3543
3264```moonscript 3544```yuescript
3265items = 3545items =
3266 * x: 100 3546 * x: 100
3267 y: 200 3547 y: 200
@@ -3276,7 +3556,8 @@ for item in *items
3276 print "尺寸 #{width}, #{height}" 3556 print "尺寸 #{width}, #{height}"
3277``` 3557```
3278<YueDisplay> 3558<YueDisplay>
3279<pre> 3559
3560```yue
3280items = 3561items =
3281 * x: 100 3562 * x: 100
3282 y: 200 3563 y: 200
@@ -3289,12 +3570,13 @@ for item in *items
3289 print "Vec2 #{x}, #{y}" 3570 print "Vec2 #{x}, #{y}"
3290 when :width, :height 3571 when :width, :height
3291 print "尺寸 #{width}, #{height}" 3572 print "尺寸 #{width}, #{height}"
3292</pre> 3573```
3574
3293</YueDisplay> 3575</YueDisplay>
3294 3576
3295你可以使用默认值来选择性地解构表格的某些字段。 3577你可以使用默认值来选择性地解构表格的某些字段。
3296 3578
3297```moonscript 3579```yuescript
3298item = {} 3580item = {}
3299 3581
3300{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos') 3582{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
@@ -3304,22 +3586,24 @@ switch item
3304 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过 3586 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3305``` 3587```
3306<YueDisplay> 3588<YueDisplay>
3307<pre> 3589
3308item = {} 3590```yue
3591item = \{}
3309 3592
3310{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos') 3593{pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos')
3311 3594
3312switch item 3595switch item
3313 when {pos: {:x = 50, :y = 200}} 3596 when {pos: {:x = 50, :y = 200}}
3314 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过 3597 print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过
3315</pre> 3598```
3599
3316</YueDisplay> 3600</YueDisplay>
3317 3601
3318你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。 3602你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3319 3603
3320匹配数组元素。 3604匹配数组元素。
3321 3605
3322```moonscript 3606```yuescript
3323switch tb 3607switch tb
3324 when [1, 2, 3] 3608 when [1, 2, 3]
3325 print "1, 2, 3" 3609 print "1, 2, 3"
@@ -3329,7 +3613,8 @@ switch tb
3329 print "1, 2, #{b}" 3613 print "1, 2, #{b}"
3330``` 3614```
3331<YueDisplay> 3615<YueDisplay>
3332<pre> 3616
3617```yue
3333switch tb 3618switch tb
3334 when [1, 2, 3] 3619 when [1, 2, 3]
3335 print "1, 2, 3" 3620 print "1, 2, 3"
@@ -3337,12 +3622,13 @@ switch tb
3337 print "1, #{b}, 3" 3622 print "1, #{b}, 3"
3338 when [1, 2, b = 3] -- 变量b有默认值 3623 when [1, 2, b = 3] -- 变量b有默认值
3339 print "1, 2, #{b}" 3624 print "1, 2, #{b}"
3340</pre> 3625```
3626
3341</YueDisplay> 3627</YueDisplay>
3342 3628
3343匹配表格字段。 3629匹配表格字段。
3344 3630
3345```moonscript 3631```yuescript
3346switch tb 3632switch tb
3347 when success: true, :result 3633 when success: true, :result
3348 print "成功", result 3634 print "成功", result
@@ -3352,7 +3638,8 @@ switch tb
3352 print "无效值" 3638 print "无效值"
3353``` 3639```
3354<YueDisplay> 3640<YueDisplay>
3355<pre> 3641
3642```yue
3356switch tb 3643switch tb
3357 when success: true, :result 3644 when success: true, :result
3358 print "成功", result 3645 print "成功", result
@@ -3360,12 +3647,13 @@ switch tb
3360 print "失败", result 3647 print "失败", result
3361 else 3648 else
3362 print "无效值" 3649 print "无效值"
3363</pre> 3650```
3651
3364</YueDisplay> 3652</YueDisplay>
3365 3653
3366匹配嵌套的表格结构。 3654匹配嵌套的表格结构。
3367 3655
3368```moonscript 3656```yuescript
3369switch tb 3657switch tb
3370 when data: {type: "success", :content} 3658 when data: {type: "success", :content}
3371 print "成功", content 3659 print "成功", content
@@ -3375,7 +3663,8 @@ switch tb
3375 print "无效值" 3663 print "无效值"
3376``` 3664```
3377<YueDisplay> 3665<YueDisplay>
3378<pre> 3666
3667```yue
3379switch tb 3668switch tb
3380 when data: {type: "success", :content} 3669 when data: {type: "success", :content}
3381 print "成功", content 3670 print "成功", content
@@ -3383,12 +3672,13 @@ switch tb
3383 print "失败", content 3672 print "失败", content
3384 else 3673 else
3385 print "无效值" 3674 print "无效值"
3386</pre> 3675```
3676
3387</YueDisplay> 3677</YueDisplay>
3388 3678
3389匹配表格数组。 3679匹配表格数组。
3390 3680
3391```moonscript 3681```yuescript
3392switch tb 3682switch tb
3393 when [ 3683 when [
3394 {a: 1, b: 2} 3684 {a: 1, b: 2}
@@ -3399,7 +3689,8 @@ switch tb
3399 print "匹配成功", fourth 3689 print "匹配成功", fourth
3400``` 3690```
3401<YueDisplay> 3691<YueDisplay>
3402<pre> 3692
3693```yue
3403switch tb 3694switch tb
3404 when [ 3695 when [
3405 {a: 1, b: 2} 3696 {a: 1, b: 2}
@@ -3408,12 +3699,13 @@ switch tb
3408 fourth 3699 fourth
3409 ] 3700 ]
3410 print "匹配成功", fourth 3701 print "匹配成功", fourth
3411</pre> 3702```
3703
3412</YueDisplay> 3704</YueDisplay>
3413 3705
3414匹配一个列表并捕获特定范围内的元素。 3706匹配一个列表并捕获特定范围内的元素。
3415 3707
3416```moonscript 3708```yuescript
3417segments = ["admin", "users", "logs", "view"] 3709segments = ["admin", "users", "logs", "view"]
3418switch segments 3710switch segments
3419 when [...groups, resource, action] 3711 when [...groups, resource, action]
@@ -3422,14 +3714,16 @@ switch segments
3422 print "Action:", action -- 打印: "view" 3714 print "Action:", action -- 打印: "view"
3423``` 3715```
3424<YueDisplay> 3716<YueDisplay>
3425<pre> 3717
3718```yue
3426segments = ["admin", "users", "logs", "view"] 3719segments = ["admin", "users", "logs", "view"]
3427switch segments 3720switch segments
3428 when [...groups, resource, action] 3721 when [...groups, resource, action]
3429 print "Group:", groups -- 打印: {"admin", "users"} 3722 print "Group:", groups -- 打印: {"admin", "users"}
3430 print "Resource:", resource -- 打印: "logs" 3723 print "Resource:", resource -- 打印: "logs"
3431 print "Action:", action -- 打印: "view" 3724 print "Action:", action -- 打印: "view"
3432</pre> 3725```
3726
3433</YueDisplay> 3727</YueDisplay>
3434 3728
3435## 面向对象编程 3729## 面向对象编程
@@ -3438,7 +3732,7 @@ switch segments
3438 3732
3439一个简单的类: 3733一个简单的类:
3440 3734
3441```moonscript 3735```yuescript
3442class Inventory 3736class Inventory
3443 new: => 3737 new: =>
3444 @items = {} 3738 @items = {}
@@ -3450,17 +3744,19 @@ class Inventory
3450 @items[name] = 1 3744 @items[name] = 1
3451``` 3745```
3452<YueDisplay> 3746<YueDisplay>
3453<pre> 3747
3748```yue
3454class Inventory 3749class Inventory
3455 new: => 3750 new: =>
3456 @items = {} 3751 @items = \{}
3457 3752
3458 add_item: (name) => 3753 add_item: (name) =>
3459 if @items[name] 3754 if @items[name]
3460 @items[name] += 1 3755 @items[name] += 1
3461 else 3756 else
3462 @items[name] = 1 3757 @items[name] = 1
3463</pre> 3758```
3759
3464</YueDisplay> 3760</YueDisplay>
3465 3761
3466在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。 3762在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。
@@ -3471,18 +3767,20 @@ class Inventory
3471 3767
3472为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。 3768为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。
3473 3769
3474```moonscript 3770```yuescript
3475inv = Inventory! 3771inv = Inventory!
3476inv\add_item "t-shirt" 3772inv\add_item "t-shirt"
3477inv\add_item "pants" 3773inv\add_item "pants"
3478``` 3774```
3479<YueDisplay> 3775<YueDisplay>
3480 3776
3481<pre> 3777
3778```yue
3482inv = Inventory! 3779inv = Inventory!
3483inv\add_item "t-shirt" 3780inv\add_item "t-shirt"
3484inv\add_item "pants" 3781inv\add_item "pants"
3485</pre> 3782```
3783
3486</YueDisplay> 3784</YueDisplay>
3487 3785
3488在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。 3786在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。
@@ -3491,7 +3789,7 @@ inv\add_item "pants"
3491 3789
3492例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。 3790例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。
3493 3791
3494```moonscript 3792```yuescript
3495class Person 3793class Person
3496 clothes: [] 3794 clothes: []
3497 give_item: (name) => 3795 give_item: (name) =>
@@ -3507,7 +3805,8 @@ b\give_item "shirt"
3507print item for item in *a.clothes 3805print item for item in *a.clothes
3508``` 3806```
3509<YueDisplay> 3807<YueDisplay>
3510<pre> 3808
3809```yue
3511class Person 3810class Person
3512 clothes: [] 3811 clothes: []
3513 give_item: (name) => 3812 give_item: (name) =>
@@ -3521,29 +3820,32 @@ b\give_item "shirt"
3521 3820
3522-- 会同时打印出裤子和衬衫 3821-- 会同时打印出裤子和衬衫
3523print item for item in *a.clothes 3822print item for item in *a.clothes
3524</pre> 3823```
3824
3525</YueDisplay> 3825</YueDisplay>
3526 3826
3527避免这个问题的正确方法是在构造函数中创建对象的可变状态: 3827避免这个问题的正确方法是在构造函数中创建对象的可变状态:
3528 3828
3529```moonscript 3829```yuescript
3530class Person 3830class Person
3531 new: => 3831 new: =>
3532 @clothes = [] 3832 @clothes = []
3533``` 3833```
3534<YueDisplay> 3834<YueDisplay>
3535<pre> 3835
3836```yue
3536class Person 3837class Person
3537 new: => 3838 new: =>
3538 @clothes = [] 3839 @clothes = []
3539</pre> 3840```
3841
3540</YueDisplay> 3842</YueDisplay>
3541 3843
3542### 继承 3844### 继承
3543 3845
3544`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。 3846`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。
3545 3847
3546```moonscript 3848```yuescript
3547class BackPack extends Inventory 3849class BackPack extends Inventory
3548 size: 10 3850 size: 10
3549 add_item: (name) => 3851 add_item: (name) =>
@@ -3551,13 +3853,15 @@ class BackPack extends Inventory
3551 super name 3853 super name
3552``` 3854```
3553<YueDisplay> 3855<YueDisplay>
3554<pre> 3856
3857```yue
3555class BackPack extends Inventory 3858class BackPack extends Inventory
3556 size: 10 3859 size: 10
3557 add_item: (name) => 3860 add_item: (name) =>
3558 if #@items > size then error "背包已满" 3861 if #@items > size then error "背包已满"
3559 super name 3862 super name
3560</pre> 3863```
3864
3561</YueDisplay> 3865</YueDisplay>
3562 3866
3563 3867
@@ -3567,7 +3871,7 @@ class BackPack extends Inventory
3567 3871
3568此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。 3872此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。
3569 3873
3570```moonscript 3874```yuescript
3571class Shelf 3875class Shelf
3572 @__inherited: (child) => 3876 @__inherited: (child) =>
3573 print @__name, "被", child.__name, "继承" 3877 print @__name, "被", child.__name, "继承"
@@ -3576,14 +3880,16 @@ class Shelf
3576class Cupboard extends Shelf 3880class Cupboard extends Shelf
3577``` 3881```
3578<YueDisplay> 3882<YueDisplay>
3579<pre> 3883
3884```yue
3580class Shelf 3885class Shelf
3581 @__inherited: (child) => 3886 @__inherited: (child) =>
3582 print @__name, "被", child.__name, "继承" 3887 print @__name, "被", child.__name, "继承"
3583 3888
3584-- 将打印: Shelf 被 Cupboard 继承 3889-- 将打印: Shelf 被 Cupboard 继承
3585class Cupboard extends Shelf 3890class Cupboard extends Shelf
3586</pre> 3891```
3892
3587</YueDisplay> 3893</YueDisplay>
3588 3894
3589### super 关键字 3895### super 关键字
@@ -3598,7 +3904,7 @@ class Cupboard extends Shelf
3598 3904
3599下面是一些使用 `super` 的不同方法的示例: 3905下面是一些使用 `super` 的不同方法的示例:
3600 3906
3601```moonscript 3907```yuescript
3602class MyClass extends ParentClass 3908class MyClass extends ParentClass
3603 a_method: => 3909 a_method: =>
3604 -- 以下效果相同: 3910 -- 以下效果相同:
@@ -3610,7 +3916,8 @@ class MyClass extends ParentClass
3610 assert super == ParentClass 3916 assert super == ParentClass
3611``` 3917```
3612<YueDisplay> 3918<YueDisplay>
3613<pre> 3919
3920```yue
3614class MyClass extends ParentClass 3921class MyClass extends ParentClass
3615 a_method: => 3922 a_method: =>
3616 -- 以下效果相同: 3923 -- 以下效果相同:
@@ -3620,7 +3927,8 @@ class MyClass extends ParentClass
3620 3927
3621 -- super 作为值等于父类: 3928 -- super 作为值等于父类:
3622 assert super == ParentClass 3929 assert super == ParentClass
3623</pre> 3930```
3931
3624</YueDisplay> 3932</YueDisplay>
3625 3933
3626**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。 3934**super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。
@@ -3629,19 +3937,21 @@ class MyClass extends ParentClass
3629 3937
3630每个类的实例都带有它的类型。这存储在特殊的 \_\_class 属性中。此属性会保存类对象。类对象是我们用来构建新实例的对象。我们还可以索引类对象以检索类方法和属性。 3938每个类的实例都带有它的类型。这存储在特殊的 \_\_class 属性中。此属性会保存类对象。类对象是我们用来构建新实例的对象。我们还可以索引类对象以检索类方法和属性。
3631 3939
3632```moonscript 3940```yuescript
3633b = BackPack! 3941b = BackPack!
3634assert b.__class == BackPack 3942assert b.__class == BackPack
3635 3943
3636print BackPack.size -- 打印 10 3944print BackPack.size -- 打印 10
3637``` 3945```
3638<YueDisplay> 3946<YueDisplay>
3639<pre> 3947
3948```yue
3640b = BackPack! 3949b = BackPack!
3641assert b.__class == BackPack 3950assert b.__class == BackPack
3642 3951
3643print BackPack.size -- 打印 10 3952print BackPack.size -- 打印 10
3644</pre> 3953```
3954
3645</YueDisplay> 3955</YueDisplay>
3646 3956
3647### 类对象 3957### 类对象
@@ -3659,13 +3969,15 @@ print BackPack.size -- 打印 10
3659 3969
3660此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “__name” 字段中。 3970此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “__name” 字段中。
3661 3971
3662```moonscript 3972```yuescript
3663print BackPack.__name -- 打印 Backpack 3973print BackPack.__name -- 打印 Backpack
3664``` 3974```
3665<YueDisplay> 3975<YueDisplay>
3666<pre> 3976
3977```yue
3667print BackPack.__name -- 打印 Backpack 3978print BackPack.__name -- 打印 Backpack
3668</pre> 3979```
3980
3669</YueDisplay> 3981</YueDisplay>
3670 3982
3671基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。 3983基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。
@@ -3676,7 +3988,7 @@ print BackPack.__name -- 打印 Backpack
3676 3988
3677我们可以直接在类对象中创建变量,而不是在类的基对象中,通过在类声明中的属性名前使用 @。 3989我们可以直接在类对象中创建变量,而不是在类的基对象中,通过在类声明中的属性名前使用 @。
3678 3990
3679```moonscript 3991```yuescript
3680class Things 3992class Things
3681 @some_func: => print "Hello from", @__name 3993 @some_func: => print "Hello from", @__name
3682 3994
@@ -3686,7 +3998,8 @@ Things\some_func!
3686assert Things().some_func == nil 3998assert Things().some_func == nil
3687``` 3999```
3688<YueDisplay> 4000<YueDisplay>
3689<pre> 4001
4002```yue
3690class Things 4003class Things
3691 @some_func: => print "Hello from", @__name 4004 @some_func: => print "Hello from", @__name
3692 4005
@@ -3694,12 +4007,13 @@ Things\some_func!
3694 4007
3695-- 类变量在实例中不可见 4008-- 类变量在实例中不可见
3696assert Things().some_func == nil 4009assert Things().some_func == nil
3697</pre> 4010```
4011
3698</YueDisplay> 4012</YueDisplay>
3699 4013
3700在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。 4014在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。
3701 4015
3702```moonscript 4016```yuescript
3703class Counter 4017class Counter
3704 @count: 0 4018 @count: 0
3705 4019
@@ -3712,7 +4026,8 @@ Counter!
3712print Counter.count -- 输出 2 4026print Counter.count -- 输出 2
3713``` 4027```
3714<YueDisplay> 4028<YueDisplay>
3715<pre> 4029
4030```yue
3716class Counter 4031class Counter
3717 @count: 0 4032 @count: 0
3718 4033
@@ -3723,18 +4038,21 @@ Counter!
3723Counter! 4038Counter!
3724 4039
3725print Counter.count -- 输出 2 4040print Counter.count -- 输出 2
3726</pre> 4041```
4042
3727</YueDisplay> 4043</YueDisplay>
3728 4044
3729@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。 4045@@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。
3730 4046
3731```moonscript 4047```yuescript
3732@@hello 1,2,3,4 4048@@hello 1,2,3,4
3733``` 4049```
3734<YueDisplay> 4050<YueDisplay>
3735<pre> 4051
4052```yue
3736@@hello 1,2,3,4 4053@@hello 1,2,3,4
3737</pre> 4054```
4055
3738</YueDisplay> 4056</YueDisplay>
3739 4057
3740### 类声明语句 4058### 类声明语句
@@ -3743,22 +4061,24 @@ print Counter.count -- 输出 2
3743 4061
3744以下是创建类变量的另一种方法: 4062以下是创建类变量的另一种方法:
3745 4063
3746```moonscript 4064```yuescript
3747class Things 4065class Things
3748 @class_var = "hello world" 4066 @class_var = "hello world"
3749``` 4067```
3750<YueDisplay> 4068<YueDisplay>
3751<pre> 4069
4070```yue
3752class Things 4071class Things
3753 @class_var = "hello world" 4072 @class_var = "hello world"
3754</pre> 4073```
4074
3755</YueDisplay> 4075</YueDisplay>
3756 4076
3757这些表达式会在所有属性被添加到类的基对象后执行。 4077这些表达式会在所有属性被添加到类的基对象后执行。
3758 4078
3759在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便: 4079在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便:
3760 4080
3761```moonscript 4081```yuescript
3762class MoreThings 4082class MoreThings
3763 secret = 123 4083 secret = 123
3764 log = (msg) -> print "LOG:", msg 4084 log = (msg) -> print "LOG:", msg
@@ -3767,14 +4087,16 @@ class MoreThings
3767 log "hello world: " .. secret 4087 log "hello world: " .. secret
3768``` 4088```
3769<YueDisplay> 4089<YueDisplay>
3770<pre> 4090
4091```yue
3771class MoreThings 4092class MoreThings
3772 secret = 123 4093 secret = 123
3773 log = (msg) -> print "LOG:", msg 4094 log = (msg) -> print "LOG:", msg
3774 4095
3775 some_method: => 4096 some_method: =>
3776 log "hello world: " .. secret 4097 log "hello world: " .. secret
3777</pre> 4098```
4099
3778</YueDisplay> 4100</YueDisplay>
3779 4101
3780### @ 和 @@ 值 4102### @ 和 @@ 值
@@ -3783,33 +4105,37 @@ class MoreThings
3783 4105
3784如果它们单独使用,它们是 self 和 self.\_\_class 的别名。 4106如果它们单独使用,它们是 self 和 self.\_\_class 的别名。
3785 4107
3786```moonscript 4108```yuescript
3787assert @ == self 4109assert @ == self
3788assert @@ == self.__class 4110assert @@ == self.__class
3789``` 4111```
3790<YueDisplay> 4112<YueDisplay>
3791<pre> 4113
4114```yue
3792assert @ == self 4115assert @ == self
3793assert @@ == self.__class 4116assert @@ == self.__class
3794</pre> 4117```
4118
3795</YueDisplay> 4119</YueDisplay>
3796 4120
3797例如,使用 @@ 从实例方法快速创建同一类的新实例的方法: 4121例如,使用 @@ 从实例方法快速创建同一类的新实例的方法:
3798 4122
3799```moonscript 4123```yuescript
3800some_instance_method = (...) => @@ ... 4124some_instance_method = (...) => @@ ...
3801``` 4125```
3802<YueDisplay> 4126<YueDisplay>
3803<pre> 4127
4128```yue
3804some_instance_method = (...) => @@ ... 4129some_instance_method = (...) => @@ ...
3805</pre> 4130```
4131
3806</YueDisplay> 4132</YueDisplay>
3807 4133
3808### 构造属性提升 4134### 构造属性提升
3809 4135
3810为了减少编写简单值对象定义的代码。你可以这样简单写一个类: 4136为了减少编写简单值对象定义的代码。你可以这样简单写一个类:
3811 4137
3812```moonscript 4138```yuescript
3813class Something 4139class Something
3814 new: (@foo, @bar, @@biz, @@baz) => 4140 new: (@foo, @bar, @@biz, @@baz) =>
3815 4141
@@ -3823,7 +4149,8 @@ class Something
3823 @@baz = baz 4149 @@baz = baz
3824``` 4150```
3825<YueDisplay> 4151<YueDisplay>
3826<pre> 4152
4153```yue
3827class Something 4154class Something
3828 new: (@foo, @bar, @@biz, @@baz) => 4155 new: (@foo, @bar, @@biz, @@baz) =>
3829 4156
@@ -3835,76 +4162,85 @@ class Something
3835 @bar = bar 4162 @bar = bar
3836 @@biz = biz 4163 @@biz = biz
3837 @@baz = baz 4164 @@baz = baz
3838</pre> 4165```
4166
3839</YueDisplay> 4167</YueDisplay>
3840 4168
3841你也可以使用这种语法为一个函数初始化传入对象的字段。 4169你也可以使用这种语法为一个函数初始化传入对象的字段。
3842 4170
3843```moonscript 4171```yuescript
3844new = (@fieldA, @fieldB) => @ 4172new = (@fieldA, @fieldB) => @
3845obj = new {}, 123, "abc" 4173obj = new {}, 123, "abc"
3846print obj 4174print obj
3847``` 4175```
3848<YueDisplay> 4176<YueDisplay>
3849<pre> 4177
4178```yue
3850new = (@fieldA, @fieldB) => @ 4179new = (@fieldA, @fieldB) => @
3851obj = new {}, 123, "abc" 4180obj = new {}, 123, "abc"
3852print obj 4181print obj
3853</pre> 4182```
4183
3854</YueDisplay> 4184</YueDisplay>
3855 4185
3856### 类表达式 4186### 类表达式
3857 4187
3858类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。 4188类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。
3859 4189
3860```moonscript 4190```yuescript
3861x = class Bucket 4191x = class Bucket
3862 drops: 0 4192 drops: 0
3863 add_drop: => @drops += 1 4193 add_drop: => @drops += 1
3864``` 4194```
3865<YueDisplay> 4195<YueDisplay>
3866<pre> 4196
4197```yue
3867x = class Bucket 4198x = class Bucket
3868 drops: 0 4199 drops: 0
3869 add_drop: => @drops += 1 4200 add_drop: => @drops += 1
3870</pre> 4201```
4202
3871</YueDisplay> 4203</YueDisplay>
3872 4204
3873### 匿名类 4205### 匿名类
3874 4206
3875声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。 4207声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。
3876 4208
3877```moonscript 4209```yuescript
3878BigBucket = class extends Bucket 4210BigBucket = class extends Bucket
3879 add_drop: => @drops += 10 4211 add_drop: => @drops += 10
3880 4212
3881assert Bucket.__name == "BigBucket" 4213assert Bucket.__name == "BigBucket"
3882``` 4214```
3883<YueDisplay> 4215<YueDisplay>
3884<pre> 4216
4217```yue
3885BigBucket = class extends Bucket 4218BigBucket = class extends Bucket
3886 add_drop: => @drops += 10 4219 add_drop: => @drops += 10
3887 4220
3888assert Bucket.__name == "BigBucket" 4221assert Bucket.__name == "BigBucket"
3889</pre> 4222```
4223
3890</YueDisplay> 4224</YueDisplay>
3891 4225
3892你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类: 4226你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类:
3893 4227
3894```moonscript 4228```yuescript
3895x = class 4229x = class
3896``` 4230```
3897<YueDisplay> 4231<YueDisplay>
3898<pre> 4232
4233```yue
3899x = class 4234x = class
3900</pre> 4235```
4236
3901</YueDisplay> 4237</YueDisplay>
3902 4238
3903### 类混合 4239### 类混合
3904 4240
3905你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 4241你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
3906 4242
3907```moonscript 4243```yuescript
3908MyIndex = __index: var: 1 4244MyIndex = __index: var: 1
3909 4245
3910class X using MyIndex 4246class X using MyIndex
@@ -3922,7 +4258,8 @@ y\func!
3922assert y.__class.__parent ~= X -- X 不是 Y 的父类 4258assert y.__class.__parent ~= X -- X 不是 Y 的父类
3923``` 4259```
3924<YueDisplay> 4260<YueDisplay>
3925<pre> 4261
4262```yue
3926MyIndex = __index: var: 1 4263MyIndex = __index: var: 1
3927 4264
3928class X using MyIndex 4265class X using MyIndex
@@ -3938,7 +4275,8 @@ y = Y!
3938y\func! 4275y\func!
3939 4276
3940assert y.__class.__parent ~= X -- X 不是 Y 的父类 4277assert y.__class.__parent ~= X -- X 不是 Y 的父类
3941</pre> 4278```
4279
3942</YueDisplay> 4280</YueDisplay>
3943 4281
3944## with 语句 4282## with 语句
@@ -3951,7 +4289,7 @@ with 块有助于简化编写这样的代码。在 with 块内,我们可以使
3951 4289
3952例如,我们可以这样处理一个新创建的对象: 4290例如,我们可以这样处理一个新创建的对象:
3953 4291
3954```moonscript 4292```yuescript
3955with Person! 4293with Person!
3956 .name = "Oswald" 4294 .name = "Oswald"
3957 \add_relative my_dad 4295 \add_relative my_dad
@@ -3959,31 +4297,35 @@ with Person!
3959 print .name 4297 print .name
3960``` 4298```
3961<YueDisplay> 4299<YueDisplay>
3962<pre> 4300
4301```yue
3963with Person! 4302with Person!
3964 .name = "Oswald" 4303 .name = "Oswald"
3965 \add_relative my_dad 4304 \add_relative my_dad
3966 \save! 4305 \save!
3967 print .name 4306 print .name
3968</pre> 4307```
4308
3969</YueDisplay> 4309</YueDisplay>
3970 4310
3971with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。 4311with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。
3972 4312
3973```moonscript 4313```yuescript
3974file = with File "favorite_foods.txt" 4314file = with File "favorite_foods.txt"
3975 \set_encoding "utf8" 4315 \set_encoding "utf8"
3976``` 4316```
3977<YueDisplay> 4317<YueDisplay>
3978<pre> 4318
4319```yue
3979file = with File "favorite_foods.txt" 4320file = with File "favorite_foods.txt"
3980 \set_encoding "utf8" 4321 \set_encoding "utf8"
3981</pre> 4322```
4323
3982</YueDisplay> 4324</YueDisplay>
3983 4325
3984或者… 4326或者…
3985 4327
3986```moonscript 4328```yuescript
3987create_person = (name, relatives) -> 4329create_person = (name, relatives) ->
3988 with Person! 4330 with Person!
3989 .name = name 4331 .name = name
@@ -3992,36 +4334,40 @@ create_person = (name, relatives) ->
3992me = create_person "Leaf", [dad, mother, sister] 4334me = create_person "Leaf", [dad, mother, sister]
3993``` 4335```
3994<YueDisplay> 4336<YueDisplay>
3995<pre> 4337
4338```yue
3996create_person = (name, relatives) -> 4339create_person = (name, relatives) ->
3997 with Person! 4340 with Person!
3998 .name = name 4341 .name = name
3999 \add_relative relative for relative in *relatives 4342 \add_relative relative for relative in *relatives
4000 4343
4001me = create_person "Leaf", [dad, mother, sister] 4344me = create_person "Leaf", [dad, mother, sister]
4002</pre> 4345```
4346
4003</YueDisplay> 4347</YueDisplay>
4004 4348
4005在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。 4349在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。
4006 4350
4007如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。 4351如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。
4008 4352
4009```moonscript 4353```yuescript
4010with str := "你好" 4354with str := "你好"
4011 print "原始:", str 4355 print "原始:", str
4012 print "大写:", \upper! 4356 print "大写:", \upper!
4013``` 4357```
4014<YueDisplay> 4358<YueDisplay>
4015<pre> 4359
4360```yue
4016with str := "你好" 4361with str := "你好"
4017 print "原始:", str 4362 print "原始:", str
4018 print "大写:", \upper! 4363 print "大写:", \upper!
4019</pre> 4364```
4365
4020</YueDisplay> 4366</YueDisplay>
4021 4367
4022你可以在 `with` 语句中使用 `[]` 访问特殊键。 4368你可以在 `with` 语句中使用 `[]` 访问特殊键。
4023 4369
4024```moonscript 4370```yuescript
4025with tb 4371with tb
4026 [1] = 1 4372 [1] = 1
4027 print [2] 4373 print [2]
@@ -4031,7 +4377,8 @@ with tb
4031 [] = "abc" -- 追加到 "tb" 4377 [] = "abc" -- 追加到 "tb"
4032``` 4378```
4033<YueDisplay> 4379<YueDisplay>
4034<pre> 4380
4381```yue
4035with tb 4382with tb
4036 [1] = 1 4383 [1] = 1
4037 print [2] 4384 print [2]
@@ -4039,44 +4386,49 @@ with tb
4039 [3] = [2]\func! 4386 [3] = [2]\func!
4040 ["key-name"] = value 4387 ["key-name"] = value
4041 [] = "abc" -- 追加到 "tb" 4388 [] = "abc" -- 追加到 "tb"
4042</pre> 4389```
4390
4043</YueDisplay> 4391</YueDisplay>
4044 4392
4045`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。 4393`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
4046 4394
4047```moonscript 4395```yuescript
4048with? obj 4396with? obj
4049 print obj.name 4397 print obj.name
4050``` 4398```
4051<YueDisplay> 4399<YueDisplay>
4052<pre> 4400
4401```yue
4053with? obj 4402with? obj
4054 print obj.name 4403 print obj.name
4055</pre> 4404```
4405
4056</YueDisplay> 4406</YueDisplay>
4057 4407
4058## do 语句 4408## do 语句
4059 4409
4060当用作语句时,do 语句的作用就像在 Lua 中差不多。 4410当用作语句时,do 语句的作用就像在 Lua 中差不多。
4061 4411
4062```moonscript 4412```yuescript
4063do 4413do
4064 var = "hello" 4414 var = "hello"
4065 print var 4415 print var
4066print var -- 这里是nil 4416print var -- 这里是nil
4067``` 4417```
4068<YueDisplay> 4418<YueDisplay>
4069<pre> 4419
4420```yue
4070do 4421do
4071 var = "hello" 4422 var = "hello"
4072 print var 4423 print var
4073print var -- 这里是nil 4424print var -- 这里是nil
4074</pre> 4425```
4426
4075</YueDisplay> 4427</YueDisplay>
4076 4428
4077月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。 4429月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。
4078 4430
4079```moonscript 4431```yuescript
4080counter = do 4432counter = do
4081 i = 0 4433 i = 0
4082 -> 4434 ->
@@ -4087,7 +4439,8 @@ print counter!
4087print counter! 4439print counter!
4088``` 4440```
4089<YueDisplay> 4441<YueDisplay>
4090<pre> 4442
4443```yue
4091counter = do 4444counter = do
4092 i = 0 4445 i = 0
4093 -> 4446 ->
@@ -4096,10 +4449,11 @@ counter = do
4096 4449
4097print counter! 4450print counter!
4098print counter! 4451print counter!
4099</pre> 4452```
4453
4100</YueDisplay> 4454</YueDisplay>
4101 4455
4102```moonscript 4456```yuescript
4103tbl = { 4457tbl = {
4104 key: do 4458 key: do
4105 print "分配键值!" 4459 print "分配键值!"
@@ -4107,13 +4461,15 @@ tbl = {
4107} 4461}
4108``` 4462```
4109<YueDisplay> 4463<YueDisplay>
4110<pre> 4464
4111tbl = { 4465```yue
4466tbl = \{
4112 key: do 4467 key: do
4113 print "分配键值!" 4468 print "分配键值!"
4114 1234 4469 1234
4115} 4470}
4116</pre> 4471```
4472
4117</YueDisplay> 4473</YueDisplay>
4118 4474
4119## 函数存根 4475## 函数存根
@@ -4124,7 +4480,7 @@ tbl = {
4124 4480
4125这种语法类似于使用 \ 操作符调用实例方法的方式,区别在于,这里不需要在 \ 操作符后面附加参数列表。 4481这种语法类似于使用 \ 操作符调用实例方法的方式,区别在于,这里不需要在 \ 操作符后面附加参数列表。
4126 4482
4127```moonscript 4483```yuescript
4128my_object = { 4484my_object = {
4129 value: 1000 4485 value: 1000
4130 write: => print "值为:", @value 4486 write: => print "值为:", @value
@@ -4143,8 +4499,9 @@ run_callback my_object.write
4143run_callback my_object\write 4499run_callback my_object\write
4144``` 4500```
4145<YueDisplay> 4501<YueDisplay>
4146<pre> 4502
4147my_object = { 4503```yue
4504my_object = \{
4148 value: 1000 4505 value: 1000
4149 write: => print "值为:", @value 4506 write: => print "值为:", @value
4150} 4507}
@@ -4160,14 +4517,15 @@ run_callback my_object.write
4160-- 函数存根语法 4517-- 函数存根语法
4161-- 让我们把对象捆绑到一个新函数中 4518-- 让我们把对象捆绑到一个新函数中
4162run_callback my_object\write 4519run_callback my_object\write
4163</pre> 4520```
4521
4164</YueDisplay> 4522</YueDisplay>
4165 4523
4166## 使用 using 语句:防止破坏性赋值 4524## 使用 using 语句:防止破坏性赋值
4167 4525
4168Lua 的变量作用域是降低代码复杂度的重要工具。然而,随着代码量的增加,维护这些变量可能变得更加困难。比如,看看下面的代码片段: 4526Lua 的变量作用域是降低代码复杂度的重要工具。然而,随着代码量的增加,维护这些变量可能变得更加困难。比如,看看下面的代码片段:
4169 4527
4170```moonscript 4528```yuescript
4171i = 100 4529i = 100
4172 4530
4173-- 许多代码行... 4531-- 许多代码行...
@@ -4183,7 +4541,8 @@ my_func!
4183print i -- 将打印 0 4541print i -- 将打印 0
4184``` 4542```
4185<YueDisplay> 4543<YueDisplay>
4186<pre> 4544
4545```yue
4187i = 100 4546i = 100
4188 4547
4189-- 许多代码行... 4548-- 许多代码行...
@@ -4197,7 +4556,8 @@ my_func = ->
4197my_func! 4556my_func!
4198 4557
4199print i -- 将打印 0 4558print i -- 将打印 0
4200</pre> 4559```
4560
4201</YueDisplay> 4561</YueDisplay>
4202 4562
4203在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。 4563在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。
@@ -4206,7 +4566,7 @@ print i -- 将打印 0
4206 4566
4207`using` 语句就是为此而生。`using nil` 确保函数内部的赋值不会意外地影响到外部作用域的变量。我们只需将 `using` 子句放在函数的参数列表之后;若函数没有参数,则直接放在括号内即可。 4567`using` 语句就是为此而生。`using nil` 确保函数内部的赋值不会意外地影响到外部作用域的变量。我们只需将 `using` 子句放在函数的参数列表之后;若函数没有参数,则直接放在括号内即可。
4208 4568
4209```moonscript 4569```yuescript
4210i = 100 4570i = 100
4211 4571
4212my_func = (using nil) -> 4572my_func = (using nil) ->
@@ -4216,7 +4576,8 @@ my_func!
4216print i -- 打印 100,i 没有受到影响 4576print i -- 打印 100,i 没有受到影响
4217``` 4577```
4218<YueDisplay> 4578<YueDisplay>
4219<pre> 4579
4580```yue
4220i = 100 4581i = 100
4221 4582
4222my_func = (using nil) -> 4583my_func = (using nil) ->
@@ -4224,12 +4585,13 @@ my_func = (using nil) ->
4224 4585
4225my_func! 4586my_func!
4226print i -- 打印 100,i 没有受到影响 4587print i -- 打印 100,i 没有受到影响
4227</pre> 4588```
4589
4228</YueDisplay> 4590</YueDisplay>
4229 4591
4230using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称: 4592using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称:
4231 4593
4232```moonscript 4594```yuescript
4233tmp = 1213 4595tmp = 1213
4234i, k = 100, 50 4596i, k = 100, 50
4235 4597
@@ -4242,7 +4604,8 @@ my_func(22)
4242print i, k -- 这些已经被更新 4604print i, k -- 这些已经被更新
4243``` 4605```
4244<YueDisplay> 4606<YueDisplay>
4245<pre> 4607
4608```yue
4246tmp = 1213 4609tmp = 1213
4247i, k = 100, 50 4610i, k = 100, 50
4248 4611
@@ -4253,7 +4616,8 @@ my_func = (add using k, i) ->
4253 4616
4254my_func(22) 4617my_func(22)
4255print i, k -- 这些已经被更新 4618print i, k -- 这些已经被更新
4256</pre> 4619```
4620
4257</YueDisplay> 4621</YueDisplay>
4258 4622
4259## 月之脚本语言库 4623## 月之脚本语言库
diff --git a/doc/docs/zh/index.md b/doc/docs/zh/index.md
new file mode 100644
index 0000000..6d677e9
--- /dev/null
+++ b/doc/docs/zh/index.md
@@ -0,0 +1,25 @@
1---
2layout: home
3hero:
4 name: 月之脚本
5 text: 一门编译到 Lua 的语言
6 image:
7 src: /image/yuescript.svg
8 alt: 月之脚本
9 actions:
10 - theme: brand
11 text: 快速上手 →
12 link: /zh/doc/
13features:
14 - title: 熟悉的 Lua 工作流
15 details: 更精简的语法,编译为可读 Lua,输出可预测、易集成。
16 - title: 现代语言特性
17 details: 管道、模式匹配、切片与解构,同时保留 Lua 互操作性。
18 - title: 内置工具链
19 details: 在线 Playground、语法高亮与同步更新的文档。
20footer: MIT Licensed | Copyright © 2017-2026 Li Jin
21---
22
23### 版权和协议
24
25MIT 许可。Copyright © 2017-2026 Li Jin. 保留所有权利。
diff --git a/doc/docs/zh/try/README.md b/doc/docs/zh/try/index.md
index 46667a8..46667a8 100755
--- a/doc/docs/zh/try/README.md
+++ b/doc/docs/zh/try/index.md