aboutsummaryrefslogtreecommitdiff
path: root/doc/docs
diff options
context:
space:
mode:
Diffstat (limited to 'doc/docs')
-rwxr-xr-xdoc/docs/.vuepress/components/YueCompiler.vue83
-rwxr-xr-xdoc/docs/README.md2
-rwxr-xr-xdoc/docs/doc/README.md1000
-rwxr-xr-xdoc/docs/zh/README.md2
-rwxr-xr-xdoc/docs/zh/doc/README.md1177
5 files changed, 1885 insertions, 379 deletions
diff --git a/doc/docs/.vuepress/components/YueCompiler.vue b/doc/docs/.vuepress/components/YueCompiler.vue
index 6b6042c..3a22d1c 100755
--- a/doc/docs/.vuepress/components/YueCompiler.vue
+++ b/doc/docs/.vuepress/components/YueCompiler.vue
@@ -1,21 +1,21 @@
1<template> 1<template>
2 <div style="width: 100%; height: auto;"> 2 <div style="width: 100%; height: auto;">
3 <div class="parent" style="background-color: #f5f7ff;"> 3 <div class="parent" style="background-color: #f5f7ff;">
4 <div class="childL" style="height: 2.5em;"> 4 <div class="editor-section">
5 <div class="childTitle">YueScript {{ info }}</div> 5 <div class="childTitle">YueScript {{ info }}</div>
6 <div class="editor-container" ref='yueEditor'>
7 <ClientOnly>
8 <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor>
9 </ClientOnly>
10 </div>
6 </div> 11 </div>
7 <div class="childR" style="height: 2.5em;"> 12 <div class="editor-section">
8 <div class="childTitle">Lua</div> 13 <div class="childTitle">Lua</div>
9 </div> 14 <div class="editor-container">
10 <div class="childL" ref='yueEditor' style="height: 30em;"> 15 <ClientOnly>
11 <ClientOnly> 16 <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" :line-numbers="isMobileLayout" readonly></prism-editor>
12 <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor> 17 </ClientOnly>
13 </ClientOnly> 18 </div>
14 </div>
15 <div class="childR" style="height: 30em;">
16 <ClientOnly>
17 <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" readonly></prism-editor>
18 </ClientOnly>
19 </div> 19 </div>
20 </div> 20 </div>
21 <div v-if="!compileronly"> 21 <div v-if="!compileronly">
@@ -57,9 +57,18 @@
57 code: '', 57 code: '',
58 compiled: '', 58 compiled: '',
59 result: '', 59 result: '',
60 windowWidth: 0,
60 }; 61 };
61 }, 62 },
63 computed: {
64 isMobileLayout() {
65 return this.windowWidth <= 768;
66 },
67 },
62 mounted () { 68 mounted () {
69 this.windowWidth = window.innerWidth;
70 window.addEventListener('resize', this.handleResize);
71
63 if (this.text !== '') { 72 if (this.text !== '') {
64 this.$data.code = this.text; 73 this.$data.code = this.text;
65 this.codeChanged(this.text); 74 this.codeChanged(this.text);
@@ -86,7 +95,13 @@
86 })(this); 95 })(this);
87 check(); 96 check();
88 }, 97 },
98 beforeDestroy() {
99 window.removeEventListener('resize', this.handleResize);
100 },
89 methods: { 101 methods: {
102 handleResize() {
103 this.windowWidth = window.innerWidth;
104 },
90 runCode() { 105 runCode() {
91 if (window.yue && this.$data.compiled !== '') { 106 if (window.yue && this.$data.compiled !== '') {
92 let res = ''; 107 let res = '';
@@ -136,27 +151,35 @@
136 resize: none; 151 resize: none;
137 margin-top: 5px; 152 margin-top: 5px;
138 } 153 }
139 .childL { 154
140 float: left; 155 .parent {
141 width: 50%; 156 display: flex;
142 box-sizing: border-box; 157 flex-wrap: wrap;
143 background-clip: content-box; 158 width: 100%;
144 background: #f5f7ff;
145 } 159 }
146 .childR { 160
147 float: left; 161 .editor-section {
148 width: 50%; 162 width: 50%;
149 box-sizing: border-box; 163 box-sizing: border-box;
150 background-clip: content-box;
151 background: #f5f7ff; 164 background: #f5f7ff;
152 } 165 }
166
167 .editor-container {
168 height: 55vh;
169 }
170
153 .childTitle { 171 .childTitle {
154 width: 100%; 172 width: 100%;
155 font-size: 1.2em; 173 font-size: 1.2em;
156 color: #b7ae8f; 174 color: #b7ae8f;
157 text-align: center; 175 text-align: center;
158 padding: 0.2em; 176 padding: 0.2em;
177 height: 2.5em;
178 display: flex;
179 align-items: center;
180 justify-content: center;
159 } 181 }
182
160 .button { 183 .button {
161 float: right; 184 float: right;
162 border: none; 185 border: none;
@@ -173,9 +196,11 @@
173 margin-top: 10px; 196 margin-top: 10px;
174 margin-right: 5px; 197 margin-right: 5px;
175 } 198 }
199
176 .button:hover { 200 .button:hover {
177 background-color: #beb69a; 201 background-color: #beb69a;
178 } 202 }
203
179 .button:focus, 204 .button:focus,
180 .button:active:focus, 205 .button:active:focus,
181 .button.active:focus, 206 .button.active:focus,
@@ -207,5 +232,19 @@
207 .my-editor >>> .prism-editor__textarea:focus { 232 .my-editor >>> .prism-editor__textarea:focus {
208 outline: none; 233 outline: none;
209 } 234 }
210</style>
211 235
236 /* 移动端响应式布局 */
237 @media screen and (max-width: 768px) {
238 .parent {
239 flex-direction: column;
240 }
241
242 .editor-section {
243 width: 100%;
244 }
245
246 .editor-container {
247 height: 30vh;
248 }
249 }
250</style>
diff --git a/doc/docs/README.md b/doc/docs/README.md
index 21e47c4..098d7da 100755
--- a/doc/docs/README.md
+++ b/doc/docs/README.md
@@ -3,6 +3,6 @@ home: true
3heroImage: ./image/yuescript.svg 3heroImage: ./image/yuescript.svg
4actionText: Quick Start → 4actionText: Quick Start →
5actionLink: /doc/ 5actionLink: /doc/
6footer: MIT Licensed | Copyright © 2017-2025 Li Jin 6footer: MIT Licensed | Copyright © 2017-2026 Li Jin
7--- 7---
8 8
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index c4518bf..b5051d4 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -16,19 +16,29 @@ Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ].
16### An Overview of YueScript 16### An Overview of YueScript
17```moonscript 17```moonscript
18-- import syntax 18-- import syntax
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- object literals 21-- object literals
22inventory = 22inventory =
23 equipment: 23 equipment:
24 * "sword" 24 - "sword"
25 * "shield" 25 - "shield"
26 items: 26 items:
27 * name: "potion" 27 - name: "potion"
28 count: 10 28 count: 10
29 * name: "bread" 29 - name: "bread"
30 count: 3 30 count: 3
31 31
32-- list comprehension
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (arr, init, action): init ->
40 init = action init, item for item in *arr
41
32-- pipe operator 42-- pipe operator
33[1, 2, 3] 43[1, 2, 3]
34 |> map (x) -> x * 2 44 |> map (x) -> x * 2
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本"
51<YueDisplay> 61<YueDisplay>
52<pre> 62<pre>
53-- import syntax 63-- import syntax
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- object literals 66-- object literals
57inventory = 67inventory =
58 equipment: 68 equipment:
59 * "sword" 69 - "sword"
60 * "shield" 70 - "shield"
61 items: 71 items:
62 * name: "potion" 72 - name: "potion"
63 count: 10 73 count: 10
64 * name: "bread" 74 - name: "bread"
65 count: 3 75 count: 3
66 76
77-- list comprehension
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (arr, init, action): init ->
85 init = action init, item for item in *arr
86
67-- pipe operator 87-- pipe operator
68[1, 2, 3] 88[1, 2, 3]
69 |> map (x) -> x * 2 89 |> map (x) -> x * 2
@@ -132,14 +152,14 @@ export 🌛 = "月之脚本"
132 152
133&emsp;Use YueScript module in Lua: 153&emsp;Use YueScript module in Lua:
134 154
135* **Case 1** 155* **Case 1**
136Require "your_yuescript_entry.yue" in Lua. 156Require "your_yuescript_entry.yue" in Lua.
137```Lua 157```Lua
138require("yue")("your_yuescript_entry") 158require("yue")("your_yuescript_entry")
139``` 159```
140&emsp;And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. 160&emsp;And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly.
141 161
142* **Case 2** 162* **Case 2**
143Require YueScript module and rewite message by hand. 163Require YueScript module and rewite message by hand.
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,7 +171,7 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **Case 3** 174* **Case 3**
155Use the YueScript compiler function in Lua. 175Use the YueScript compiler function in Lua.
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
@@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ...
203 Execute without options to enter REPL, type symbol '$' 223 Execute without options to enter REPL, type symbol '$'
204 in a single line to start/stop multi-line mode 224 in a single line to start/stop multi-line mode
205``` 225```
206&emsp;&emsp;Use cases: 226&emsp;&emsp;Use cases:
207&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .** 227&emsp;&emsp;Recursively compile every YueScript file with extension **.yue** under current path: **yue .**
208&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .** 228&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .**
209&emsp;&emsp;Compile and reserve debug info: **yue -l .** 229&emsp;&emsp;Compile and reserve debug info: **yue -l .**
210&emsp;&emsp;Compile and generate minified codes: **yue -m .** 230&emsp;&emsp;Compile and generate minified codes: **yue -m .**
211&emsp;&emsp;Execute raw codes: **yue -e 'print 123'** 231&emsp;&emsp;Execute raw codes: **yue -e 'print 123'**
212&emsp;&emsp;Execute a YueScript file: **yue -e main.yue** 232&emsp;&emsp;Execute a YueScript file: **yue -e main.yue**
213 233
214## Macro 234## Macro
@@ -388,16 +408,16 @@ In YueScript, macro functions allow you to generate code at compile time. By nes
388 408
389```moonscript 409```moonscript
390macro Enum = (...) -> 410macro Enum = (...) ->
391 items = {...} 411 items = {...}
392 itemSet = {item, true for item in *items} 412 itemSet = {item, true for item in *items}
393 (item) -> 413 (item) ->
394 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] 414 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
395 "\"#{item}\"" 415 "\"#{item}\""
396 416
397macro BodyType = $Enum( 417macro BodyType = $Enum(
398 Static 418 Static
399 Dynamic 419 Dynamic
400 Kinematic 420 Kinematic
401) 421)
402 422
403print "Valid enum type:", $BodyType Static 423print "Valid enum type:", $BodyType Static
@@ -407,16 +427,16 @@ print "Valid enum type:", $BodyType Static
407<YueDisplay> 427<YueDisplay>
408<pre> 428<pre>
409macro Enum = (...) -> 429macro Enum = (...) ->
410 items = {...} 430 items = {...}
411 itemSet = {item, true for item in *items} 431 itemSet = {item, true for item in *items}
412 (item) -> 432 (item) ->
413 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] 433 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
414 "\"#{item}\"" 434 "\"#{item}\""
415 435
416macro BodyType = $Enum( 436macro BodyType = $Enum(
417 Static 437 Static
418 Dynamic 438 Dynamic
419 Kinematic 439 Kinematic
420) 440)
421 441
422print "Valid enum type:", $BodyType Static 442print "Valid enum type:", $BodyType Static
@@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static
424</pre> 444</pre>
425</YueDisplay> 445</YueDisplay>
426 446
447### Argument Validation
448
449You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time.
450
451```moonscript
452macro printNumAndStr = (num `Num, str `String) -> |
453 print(
454 #{num}
455 #{str}
456 )
457
458$printNumAndStr 123, "hello"
459```
460<YueDisplay>
461<pre>
462macro printNumAndStr = (num `Num, str `String) -> |
463 print(
464 #{num}
465 #{str}
466 )
467
468$printNumAndStr 123, "hello"
469</pre>
470</YueDisplay>
471
472If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place.
473
474```moonscript
475macro printNumAndStr = (num, str) ->
476 error "expected Num as first argument" unless $is_ast Num, num
477 error "expected String as second argument" unless $is_ast String, str
478 "print(#{num}, #{str})"
479
480$printNumAndStr 123, "hello"
481```
482<YueDisplay>
483<pre>
484macro printNumAndStr = (num, str) ->
485 error "expected Num as first argument" unless $is_ast Num, num
486 error "expected String as second argument" unless $is_ast String, str
487 "print(#{num}, #{str})"
488
489$printNumAndStr 123, "hello"
490</pre>
491</YueDisplay>
492
493For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp).
494
427## Operator 495## Operator
428 496
429All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. 497All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes.
@@ -466,47 +534,47 @@ Note the evaluation behavior of chained comparisons:
466 534
467```moonscript 535```moonscript
468v = (x) -> 536v = (x) ->
469 print x 537 print x
470 x 538 x
471 539
472print v(1) < v(2) <= v(3) 540print v(1) < v(2) <= v(3)
473--[[ 541--[[
474 output: 542 output:
475 2 543 2
476 1 544 1
477 3 545 3
478 true 546 true
479]] 547]]
480 548
481print v(1) > v(2) <= v(3) 549print v(1) > v(2) <= v(3)
482--[[ 550--[[
483 output: 551 output:
484 2 552 2
485 1 553 1
486 false 554 false
487]] 555]]
488``` 556```
489<YueDisplay> 557<YueDisplay>
490<pre> 558<pre>
491v = (x) -> 559v = (x) ->
492 print x 560 print x
493 x 561 x
494 562
495print v(1) < v(2) <= v(3) 563print v(1) < v(2) <= v(3)
496--[[ 564--[[
497 output: 565 output:
498 2 566 2
499 1 567 1
500 3 568 3
501 true 569 true
502]] 570]]
503 571
504print v(1) > v(2) <= v(3) 572print v(1) > v(2) <= v(3)
505--[[ 573--[[
506 output: 574 output:
507 2 575 2
508 1 576 1
509 false 577 false
510]] 578]]
511</pre> 579</pre>
512</YueDisplay> 580</YueDisplay>
@@ -527,19 +595,36 @@ tab[] = "Value"
527</pre> 595</pre>
528</YueDisplay> 596</YueDisplay>
529 597
598You can also use the spread operator `...` to append all elements from one list to another:
599
600```moonscript
601tbA = [1, 2, 3]
602tbB = [4, 5, 6]
603tbA[] = ...tbB
604-- tbA is now [1, 2, 3, 4, 5, 6]
605```
606<YueDisplay>
607<pre>
608tbA = [1, 2, 3]
609tbB = [4, 5, 6]
610tbA[] = ...tbB
611-- tbA is now [1, 2, 3, 4, 5, 6]
612</pre>
613</YueDisplay>
614
530### Table Spreading 615### Table Spreading
531 616
532You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. 617You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals.
533 618
534```moonscript 619```moonscript
535parts = 620parts =
536 * "shoulders" 621 * "shoulders"
537 * "knees" 622 * "knees"
538lyrics = 623lyrics =
539 * "head" 624 * "head"
540 * ...parts 625 * ...parts
541 * "and" 626 * "and"
542 * "toes" 627 * "toes"
543 628
544copy = {...other} 629copy = {...other}
545 630
@@ -550,13 +635,13 @@ merge = {...a, ...b}
550<YueDisplay> 635<YueDisplay>
551<pre> 636<pre>
552parts = 637parts =
553 * "shoulders" 638 * "shoulders"
554 * "knees" 639 * "knees"
555lyrics = 640lyrics =
556 * "head" 641 * "head"
557 * ...parts 642 * ...parts
558 * "and" 643 * "and"
559 * "toes" 644 * "toes"
560 645
561copy = {...other} 646copy = {...other}
562 647
@@ -566,11 +651,28 @@ merge = {...a, ...b}
566</pre> 651</pre>
567</YueDisplay> 652</YueDisplay>
568 653
654### Table Reversed Indexing
655
656You can use the **#** operator to get the last elements of a table.
657
658```moonscript
659last = data.items[#]
660second_last = data.items[#-1]
661data.items[#] = 1
662```
663<YueDisplay>
664<pre>
665last = data.items[#]
666second_last = data.items[#-1]
667data.items[#] = 1
668</pre>
669</YueDisplay>
670
569### Metatable 671### Metatable
570 672
571The **<>** operator can be used as a shortcut for metatable manipulation. 673The **<>** operator can be used as a shortcut for metatable manipulation.
572 674
573* **Metatable Creation** 675* **Metatable Creation**
574Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. 676Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**.
575 677
576```moonscript 678```moonscript
@@ -606,7 +708,7 @@ close _ = &lt;close&gt;: -> print "out of scope"
606</pre> 708</pre>
607</YueDisplay> 709</YueDisplay>
608 710
609* **Metatable Accessing** 711* **Metatable Accessing**
610Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. 712Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**.
611 713
612```moonscript 714```moonscript
@@ -630,7 +732,7 @@ print tb.item
630</pre> 732</pre>
631</YueDisplay> 733</YueDisplay>
632 734
633* **Metatable Destructure** 735* **Metatable Destructure**
634Destruct metatable with metamethod key surrounded by **<>**. 736Destruct metatable with metamethod key surrounded by **<>**.
635 737
636```moonscript 738```moonscript
@@ -732,34 +834,45 @@ a ??= false
732 834
733### Implicit Object 835### Implicit Object
734 836
735You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. 837You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent.
838
736```moonscript 839```moonscript
840-- assignment with implicit object
737list = 841list =
738 * 1 842 * 1
739 * 2 843 * 2
740 * 3 844 * 3
741 845
846-- function call with implicit object
742func 847func
743 * 1 848 * 1
744 * 2 849 * 2
745 * 3 850 * 3
746 851
852-- return with implicit object
853f = ->
854 return
855 * 1
856 * 2
857 * 3
858
859-- table with implicit object
747tb = 860tb =
748 name: "abc" 861 name: "abc"
749 862
750 values: 863 values:
751 * "a" 864 - "a"
752 * "b" 865 - "b"
753 * "c" 866 - "c"
754 867
755 objects: 868 objects:
756 * name: "a" 869 - name: "a"
757 value: 1 870 value: 1
758 func: => @value + 1 871 func: => @value + 1
759 tb: 872 tb:
760 fieldA: 1 873 fieldA: 1
761 874
762 * name: "b" 875 - name: "b"
763 value: 2 876 value: 2
764 func: => @value + 2 877 func: => @value + 2
765 tb: { } 878 tb: { }
@@ -767,32 +880,42 @@ tb =
767``` 880```
768<YueDisplay> 881<YueDisplay>
769<pre> 882<pre>
883-- assignment with implicit object
770list = 884list =
771 * 1 885 * 1
772 * 2 886 * 2
773 * 3 887 * 3
774 888
889-- function call with implicit object
775func 890func
776 * 1 891 * 1
777 * 2 892 * 2
778 * 3 893 * 3
779 894
895-- return with implicit object
896f = ->
897 return
898 * 1
899 * 2
900 * 3
901
902-- table with implicit object
780tb = 903tb =
781 name: "abc" 904 name: "abc"
782 905
783 values: 906 values:
784 * "a" 907 - "a"
785 * "b" 908 - "b"
786 * "c" 909 - "c"
787 910
788 objects: 911 objects:
789 * name: "a" 912 - name: "a"
790 value: 1 913 value: 1
791 func: => @value + 1 914 func: => @value + 1
792 tb: 915 tb:
793 fieldA: 1 916 fieldA: 1
794 917
795 * name: "b" 918 - name: "b"
796 value: 2 919 value: 2
797 func: => @value + 2 920 func: => @value + 2
798 tb: { } 921 tb: { }
@@ -856,11 +979,67 @@ do
856</pre> 979</pre>
857</YueDisplay> 980</YueDisplay>
858 981
982### Import Global
983
984You can import specific globals into local variables with `import`. When importing a chain of global variable accessings, the last field will be assigned to the local variable.
985
986```moonscript
987do
988 import tostring
989 import table.concat
990 print concat ["a", tostring 1]
991```
992<YueDisplay>
993<pre>
994do
995 import tostring
996 import table.concat
997 print concat ["a", tostring 1]
998</pre>
999</YueDisplay>
1000
1001#### Automatic Import
1002
1003You can place `import global` at the top of a block to automatically import all names that have not been explicitly declared or assigned in the current scope as globals. These implicit imports are treated as local consts that reference the corresponding globals at the position of the statement.
1004
1005Names that are explicitly declared as globals in the same scope will not be imported, so you can still assign to them.
1006
1007```moonscript
1008do
1009 import global
1010 print "hello"
1011 math.random 3
1012 -- print = nil -- error: imported globals are const
1013
1014do
1015 -- explicit global variable will not be imported
1016 import global
1017 global FLAG
1018 print FLAG
1019 FLAG = 123
1020```
1021<YueDisplay>
1022<pre>
1023do
1024 import global
1025 print "hello"
1026 math.random 3
1027 -- print = nil -- error: imported globals are const
1028
1029do
1030 -- explicit global variable will not be imported
1031 import global
1032 global FLAG
1033 print FLAG
1034 FLAG = 123
1035</pre>
1036</YueDisplay>
1037
859### Export 1038### Export
860 1039
861The export statement offers a concise way to define modules. 1040The export statement offers a concise way to define modules.
862 1041
863* **Named Export** 1042* **Named Export**
864Named export will define a local variable as well as adding a field in the exported table. 1043Named export will define a local variable as well as adding a field in the exported table.
865 1044
866```moonscript 1045```moonscript
@@ -924,7 +1103,7 @@ export["a-b-c"] = 123
924</pre> 1103</pre>
925</YueDisplay> 1104</YueDisplay>
926 1105
927* **Unnamed Export** 1106* **Unnamed Export**
928Unnamed export will add the target item into the array part of the exported table. 1107Unnamed export will add the target item into the array part of the exported table.
929 1108
930```moonscript 1109```moonscript
@@ -954,7 +1133,7 @@ export with tmp
954</pre> 1133</pre>
955</YueDisplay> 1134</YueDisplay>
956 1135
957* **Default Export** 1136* **Default Export**
958Using the **default** keyword in export statement to replace the exported table with any thing. 1137Using the **default** keyword in export statement to replace the exported table with any thing.
959 1138
960```moonscript 1139```moonscript
@@ -1202,7 +1381,7 @@ If the destructuring statement is complicated, feel free to spread it out over a
1202</pre> 1381</pre>
1203</YueDisplay> 1382</YueDisplay>
1204 1383
1205It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: 1384It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator:
1206 1385
1207```moonscript 1386```moonscript
1208{:concat, :insert} = table 1387{:concat, :insert} = table
@@ -1246,6 +1425,52 @@ You can use `_` as placeholder when doing a list destructuring:
1246</pre> 1425</pre>
1247</YueDisplay> 1426</YueDisplay>
1248 1427
1428### Range Destructuring
1429
1430You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between.
1431
1432```moonscript
1433orders = ["first", "second", "third", "fourth", "last"]
1434[first, ...bulk, last] = orders
1435print first -- prints: first
1436print bulk -- prints: {"second", "third", "fourth"}
1437print last -- prints: last
1438```
1439<YueDisplay>
1440<pre>
1441orders = ["first", "second", "third", "fourth", "last"]
1442[first, ...bulk, last] = orders
1443print first -- prints: first
1444print bulk -- prints: {"second", "third", "fourth"}
1445print last -- prints: last
1446</pre>
1447</YueDisplay>
1448
1449The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture:
1450
1451```moonscript
1452-- Capture everything after first element
1453[first, ...rest] = orders
1454
1455-- Capture everything before last element
1456[...start, last] = orders
1457
1458-- Capture things except the middle elements
1459[first, ..._, last] = orders
1460```
1461<YueDisplay>
1462<pre>
1463-- Capture everything after first element
1464[first, ...rest] = orders
1465
1466-- Capture everything before last element
1467[...start, last] = orders
1468
1469-- Capture things except the middle elements
1470[first, ..._, last] = orders
1471</pre>
1472</YueDisplay>
1473
1249### Destructuring In Other Places 1474### Destructuring In Other Places
1250 1475
1251Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: 1476Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop:
@@ -1363,6 +1588,19 @@ print ok, count, first
1363 1588
1364YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs. 1589YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs.
1365 1590
1591### Statement Separator
1592
1593A statement normally ends at a line break. You can also use a semicolon `;` to explicitly terminate a statement, which allows writing multiple statements on the same line:
1594
1595```moonscript
1596a = 1; b = 2; print a + b
1597```
1598<YueDisplay>
1599<pre>
1600a = 1; b = 2; print a + b
1601</pre>
1602</YueDisplay>
1603
1366### Multiline Chaining 1604### Multiline Chaining
1367 1605
1368You can write multi-line chaining function calls with a same indent. 1606You can write multi-line chaining function calls with a same indent.
@@ -1475,6 +1713,47 @@ catch err
1475</pre> 1713</pre>
1476</YueDisplay> 1714</YueDisplay>
1477 1715
1716### Try?
1717
1718`try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise.
1719
1720```moonscript
1721a, b, c = try? func!
1722
1723-- with nil coalescing operator
1724a = (try? func!) ?? "default"
1725
1726-- as function argument
1727f try? func!
1728
1729-- with catch block
1730f try?
1731 print 123
1732 func!
1733catch e
1734 print e
1735 e
1736```
1737<YueDisplay>
1738<pre>
1739a, b, c = try? func!
1740
1741-- with nil coalescing operator
1742a = (try? func!) ?? "default"
1743
1744-- as function argument
1745f try? func!
1746
1747-- with catch block
1748f try?
1749 print 123
1750 func!
1751catch e
1752 print e
1753 e
1754</pre>
1755</YueDisplay>
1756
1478## Attributes 1757## Attributes
1479 1758
1480Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. 1759Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4.
@@ -1503,6 +1782,19 @@ const {:a, :b, c, d} = tb
1503</pre> 1782</pre>
1504</YueDisplay> 1783</YueDisplay>
1505 1784
1785You can also declare a global variable to be `const`.
1786
1787```moonscript
1788global const Constant = 123
1789-- Constant = 1
1790```
1791<YueDisplay>
1792<pre>
1793global const Constant = 123
1794-- Constant = 1
1795</pre>
1796</YueDisplay>
1797
1506## Literals 1798## Literals
1507 1799
1508All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. 1800All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**.
@@ -1535,12 +1827,73 @@ You can use underscores in a number literal to increase readability.
1535```moonscript 1827```moonscript
1536integer = 1_000_000 1828integer = 1_000_000
1537hex = 0xEF_BB_BF 1829hex = 0xEF_BB_BF
1830binary = 0B10011
1538``` 1831```
1539<YueDisplay> 1832<YueDisplay>
1540 1833
1541<pre> 1834<pre>
1542integer = 1_000_000 1835integer = 1_000_000
1543hex = 0xEF_BB_BF 1836hex = 0xEF_BB_BF
1837binary = 0B10011
1838</pre>
1839</YueDisplay>
1840
1841### YAML Multiline String
1842
1843The `|` prefix introduces a YAML-style multiline string literal:
1844
1845```moonscript
1846str = |
1847 key: value
1848 list:
1849 - item1
1850 - #{expr}
1851```
1852<YueDisplay>
1853<pre>
1854str = |
1855 key: value
1856 list:
1857 - item1
1858 - #{expr}
1859</pre>
1860</YueDisplay>
1861
1862This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`.
1863
1864YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content.
1865
1866```moonscript
1867fn = ->
1868 str = |
1869 foo:
1870 bar: baz
1871 return str
1872```
1873<YueDisplay>
1874<pre>
1875fn = ->
1876 str = |
1877 foo:
1878 bar: baz
1879 return str
1880</pre>
1881</YueDisplay>
1882
1883Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures.
1884
1885All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected.
1886
1887```moonscript
1888str = |
1889 path: "C:\Program Files\App"
1890 note: 'He said: "#{Hello}!"'
1891```
1892<YueDisplay>
1893<pre>
1894str = |
1895 path: "C:\Program Files\App"
1896 note: 'He said: "#{Hello}!"'
1544</pre> 1897</pre>
1545</YueDisplay> 1898</YueDisplay>
1546 1899
@@ -1861,6 +2214,138 @@ if func 1, 2, 3,
1861</pre> 2214</pre>
1862</YueDisplay> 2215</YueDisplay>
1863 2216
2217### Parameter Destructuring
2218
2219YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available:
2220
2221* **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`).
2222
2223* **Unwrapped simple table syntax**, starting with a sequence of key-value or shorthand bindings and continuing until another expression terminates it (e.g., `:a, b: b1, :c`). This form extracts multiple fields from the same object.
2224
2225```moonscript
2226f1 = (:a, :b, :c) ->
2227 print a, b, c
2228
2229f1 a: 1, b: "2", c: {}
2230
2231f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2232 print a1, b, c
2233
2234arg1 = {a: 0}
2235f2 arg1, arg2
2236```
2237<YueDisplay>
2238<pre>
2239f1 = (:a, :b, :c) ->
2240 print a, b, c
2241
2242f1 a: 1, b: "2", c: {}
2243
2244f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2245print a1, b, c
2246
2247arg1 = {a: 0}
2248f2 arg1, arg2
2249</pre>
2250</YueDisplay>
2251
2252### Prefixed Return Expression
2253
2254When working with deeply nested function bodies, it can be tedious to maintain readability and consistency of the return value. To address this, YueScript introduces the **Prefixed Return Expression** syntax. Its form is as follows:
2255
2256```moon
2257findFirstEven = (list): nil ->
2258 for item in *list
2259 if type(item) == "table"
2260 for sub in *item
2261 if sub % 2 == 0
2262 return sub
2263```
2264<YueDisplay>
2265<pre>
2266findFirstEven = (list): nil ->
2267 for item in *list
2268 if type(item) == "table"
2269 for sub in *item
2270 if sub % 2 == 0
2271 return sub
2272</pre>
2273</YueDisplay>
2274
2275This is equivalent to:
2276
2277```moon
2278findFirstEven = (list) ->
2279 for item in *list
2280 if type(item) == "table"
2281 for sub in *item
2282 if sub % 2 == 0
2283 return sub
2284 nil
2285```
2286<YueDisplay>
2287<pre>
2288findFirstEven = (list) ->
2289 for item in *list
2290 if type(item) == "table"
2291 for sub in *item
2292 if sub % 2 == 0
2293 return sub
2294 nil
2295</pre>
2296</YueDisplay>
2297
2298The only difference is that you can move the final return expression before the `->` or `=>` token to indicate the function’s implicit return value as the last statement. This way, even in functions with multiple nested loops or conditional branches, you no longer need to write a trailing return expression at the end of the function body, making the logic structure more straightforward and easier to follow.
2299
2300### Named Varargs
2301
2302You can use the `(...t) ->` syntax to automatically store varargs into a named table. This table will contain all passed arguments (including `nil` values), and the `n` field of the table will store the actual number of arguments passed (including `nil` values).
2303
2304```moonscript
2305f = (...t) ->
2306 print "argument count:", t.n
2307 print "table length:", #t
2308 for i = 1, t.n
2309 print t[i]
2310
2311f 1, 2, 3
2312f "a", "b", "c", "d"
2313f!
2314
2315-- Handling cases with nil values
2316process = (...args) ->
2317 sum = 0
2318 for i = 1, args.n
2319 if args[i] != nil and type(args[i]) == "number"
2320 sum += args[i]
2321 sum
2322
2323process 1, nil, 3, nil, 5
2324```
2325<YueDisplay>
2326<pre>
2327f = (...t) ->
2328 print "argument count:", t.n
2329 print "table length:", #t
2330 for i = 1, t.n
2331 print t[i]
2332
2333f 1, 2, 3
2334f "a", "b", "c", "d"
2335f!
2336
2337-- Handling cases with nil values
2338process = (...args) ->
2339 sum = 0
2340 for i = 1, args.n
2341 if args[i] != nil and type(args[i]) == "number"
2342 sum += args[i]
2343 sum
2344
2345process 1, nil, 3, nil, 5
2346</pre>
2347</YueDisplay>
2348
1864## Backcalls 2349## Backcalls
1865 2350
1866Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent. 2351Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent.
@@ -1902,22 +2387,22 @@ x * 2
1902</pre> 2387</pre>
1903</YueDisplay> 2388</YueDisplay>
1904 2389
1905If you wish to have further code after your backcalls, you can set them aside with a do statement. 2390If you wish to have further code after your backcalls, you can set them aside with a do statement. And the parentheses can be omitted with non-fat arrow functions.
1906 2391
1907```moonscript 2392```moonscript
1908result, msg = do 2393result, msg = do
1909 (data) <- readAsync "filename.txt" 2394 data <- readAsync "filename.txt"
1910 print data 2395 print data
1911 (info) <- processAsync data 2396 info <- processAsync data
1912 check info 2397 check info
1913print result, msg 2398print result, msg
1914``` 2399```
1915<YueDisplay> 2400<YueDisplay>
1916<pre> 2401<pre>
1917result, msg = do 2402result, msg = do
1918 (data) <- readAsync "filename.txt" 2403 data <- readAsync "filename.txt"
1919 print data 2404 print data
1920 (info) <- processAsync data 2405 info <- processAsync data
1921 check info 2406 check info
1922print result, msg 2407print result, msg
1923</pre> 2408</pre>
@@ -2115,6 +2600,27 @@ doubled = [item * 2 for item in *items]
2115</pre> 2600</pre>
2116</YueDisplay> 2601</YueDisplay>
2117 2602
2603In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect:
2604
2605```moonscript
2606data =
2607 a: [1, 2, 3]
2608 b: [4, 5, 6]
2609
2610flat = [...v for k,v in pairs data]
2611-- flat is now [1, 2, 3, 4, 5, 6]
2612```
2613<YueDisplay>
2614<pre>
2615data =
2616 a: [1, 2, 3]
2617 b: [4, 5, 6]
2618
2619flat = [...v for k,v in pairs data]
2620-- flat is now [1, 2, 3, 4, 5, 6]
2621</pre>
2622</YueDisplay>
2623
2118The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. 2624The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause.
2119 2625
2120Using multiple for clauses is the same as using nested loops: 2626Using multiple for clauses is the same as using nested loops:
@@ -2248,6 +2754,45 @@ slice = [item for item in *items[,,2]]
2248</pre> 2754</pre>
2249</YueDisplay> 2755</YueDisplay>
2250 2756
2757Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table.
2758
2759```moonscript
2760-- take the last 4 items
2761slice = [item for item in *items[-4,-1]]
2762```
2763<YueDisplay>
2764<pre>
2765-- take the last 4 items
2766slice = [item for item in *items[-4,-1]]
2767</pre>
2768</YueDisplay>
2769
2770The step size can also be negative, which means that the items are taken in reverse order.
2771
2772```moonscript
2773reverse_slice = [item for item in *items[-1,1,-1]]
2774```
2775<YueDisplay>
2776<pre>
2777reverse_slice = [item for item in *items[-1,1,-1]]
2778</pre>
2779</YueDisplay>
2780
2781#### Slicing Expression
2782
2783Slicing can also be used as an expression. This is useful for getting a sub-list of a table.
2784
2785```moonscript
2786-- take the 2nd and 4th items as a new list
2787sub_list = items[2, 4]
2788```
2789<YueDisplay>
2790<pre>
2791-- take the 2nd and 4th items as a new list
2792sub_list = items[2, 4]
2793</pre>
2794</YueDisplay>
2795
2251## For Loop 2796## For Loop
2252 2797
2253There are two for loop forms, just like in Lua. A numeric one and a generic one: 2798There are two for loop forms, just like in Lua. A numeric one and a generic one:
@@ -2324,6 +2869,23 @@ doubled_evens = for i = 1, 20
2324</pre> 2869</pre>
2325</YueDisplay> 2870</YueDisplay>
2326 2871
2872In addition, for loops support break with a return value, allowing the loop itself to be used as an expression that exits early with a meaningful result.
2873
2874For example, to find the first number greater than 10:
2875
2876```moonscript
2877first_large = for n in *numbers
2878 break n if n > 10
2879```
2880<YueDisplay>
2881<pre>
2882first_large = for n in *numbers
2883 break n if n > 10
2884</pre>
2885</YueDisplay>
2886
2887This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions.
2888
2327You can also filter values by combining the for loop expression with the continue statement. 2889You can also filter values by combining the for loop expression with the continue statement.
2328 2890
2329For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. 2891For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension.
@@ -2345,7 +2907,7 @@ print func_b! -- prints table object
2345</pre> 2907</pre>
2346</YueDisplay> 2908</YueDisplay>
2347 2909
2348This is done to avoid the needless creation of tables for functions that dont need to return the results of the loop. 2910This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop.
2349 2911
2350## Repeat Loop 2912## Repeat Loop
2351 2913
@@ -2624,28 +3186,26 @@ reader\parse_line! until reader\eof!
2624 3186
2625## Switch 3187## Switch
2626 3188
2627The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. 3189The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value.
2628 3190
2629```moonscript 3191```moonscript
2630name = "Dan" 3192switch name := "Dan"
2631switch name
2632 when "Robert" 3193 when "Robert"
2633 print "You are Robert" 3194 print "You are Robert"
2634 when "Dan", "Daniel" 3195 when "Dan", "Daniel"
2635 print "Your name, it's Dan" 3196 print "Your name, it's Dan"
2636 else 3197 else
2637 print "I don't know about your name" 3198 print "I don't know about you with name #{name}"
2638``` 3199```
2639<YueDisplay> 3200<YueDisplay>
2640<pre> 3201<pre>
2641name = "Dan" 3202switch name := "Dan"
2642switch name
2643 when "Robert" 3203 when "Robert"
2644 print "You are Robert" 3204 print "You are Robert"
2645 when "Dan", "Daniel" 3205 when "Dan", "Daniel"
2646 print "Your name, it's Dan" 3206 print "Your name, it's Dan"
2647 else 3207 else
2648 print "I don't know about your name" 3208 print "I don't know about you with name #{name}"
2649</pre> 3209</pre>
2650</YueDisplay> 3210</YueDisplay>
2651 3211
@@ -2676,7 +3236,7 @@ next_number = switch b
2676</pre> 3236</pre>
2677</YueDisplay> 3237</YueDisplay>
2678 3238
2679We can use the then keyword to write a switch’s when block on a single line. No extra keyword is needed to write the else block on a single line. 3239We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line.
2680 3240
2681```moonscript 3241```moonscript
2682msg = switch math.random(1, 5) 3242msg = switch math.random(1, 5)
@@ -2722,7 +3282,7 @@ else
2722</pre> 3282</pre>
2723</YueDisplay> 3283</YueDisplay>
2724 3284
2725It is worth noting the order of the case comparison expression. The case’s expression is on the left hand side. This can be useful if the case’s expression wants to overwrite how the comparison is done by defining an eq metamethod. 3285It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod.
2726 3286
2727### Table Matching 3287### Table Matching
2728 3288
@@ -2782,6 +3342,123 @@ switch item
2782</pre> 3342</pre>
2783</YueDisplay> 3343</YueDisplay>
2784 3344
3345You can also match against array elements, table fields, and even nested structures with array or table literals.
3346
3347Match against array elements.
3348
3349```moonscript
3350switch tb
3351 when [1, 2, 3]
3352 print "1, 2, 3"
3353 when [1, b, 3]
3354 print "1, #{b}, 3"
3355 when [1, 2, b = 3] -- b has a default value
3356 print "1, 2, #{b}"
3357```
3358<YueDisplay>
3359<pre>
3360switch tb
3361 when [1, 2, 3]
3362 print "1, 2, 3"
3363 when [1, b, 3]
3364 print "1, #{b}, 3"
3365 when [1, 2, b = 3] -- b has a default value
3366 print "1, 2, #{b}"
3367</pre>
3368</YueDisplay>
3369
3370Match against table fields with destructuring.
3371
3372```moonscript
3373switch tb
3374 when success: true, :result
3375 print "success", result
3376 when success: false
3377 print "failed", result
3378 else
3379 print "invalid"
3380```
3381<YueDisplay>
3382<pre>
3383switch tb
3384 when success: true, :result
3385 print "success", result
3386 when success: false
3387 print "failed", result
3388 else
3389 print "invalid"
3390</pre>
3391</YueDisplay>
3392
3393Match against nested table structures.
3394
3395```moonscript
3396switch tb
3397 when data: {type: "success", :content}
3398 print "success", content
3399 when data: {type: "error", :content}
3400 print "failed", content
3401 else
3402 print "invalid"
3403```
3404<YueDisplay>
3405<pre>
3406switch tb
3407 when data: {type: "success", :content}
3408 print "success", content
3409 when data: {type: "error", :content}
3410 print "failed", content
3411 else
3412 print "invalid"
3413</pre>
3414</YueDisplay>
3415
3416Match against array of tables.
3417
3418```moonscript
3419switch tb
3420 when [
3421 {a: 1, b: 2}
3422 {a: 3, b: 4}
3423 {a: 5, b: 6}
3424 fourth
3425 ]
3426 print "matched", fourth
3427```
3428<YueDisplay>
3429<pre>
3430switch tb
3431 when [
3432 {a: 1, b: 2}
3433 {a: 3, b: 4}
3434 {a: 5, b: 6}
3435 fourth
3436 ]
3437 print "matched", fourth
3438</pre>
3439</YueDisplay>
3440
3441Match against a list and capture a range of elements.
3442
3443```moonscript
3444segments = ["admin", "users", "logs", "view"]
3445switch segments
3446 when [...groups, resource, action]
3447 print "Group:", groups -- prints: {"admin", "users"}
3448 print "Resource:", resource -- prints: "logs"
3449 print "Action:", action -- prints: "view"
3450```
3451<YueDisplay>
3452<pre>
3453segments = ["admin", "users", "logs", "view"]
3454switch segments
3455 when [...groups, resource, action]
3456 print "Group:", groups -- prints: {"admin", "users"}
3457 print "Resource:", resource -- prints: "logs"
3458 print "Action:", action -- prints: "view"
3459</pre>
3460</YueDisplay>
3461
2785## Object Oriented Programming 3462## Object Oriented Programming
2786 3463
2787In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. 3464In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details.
@@ -2913,7 +3590,7 @@ class BackPack extends Inventory
2913 3590
2914Here we extend our Inventory class, and limit the amount of items it can carry. 3591Here we extend our Inventory class, and limit the amount of items it can carry.
2915 3592
2916In this example, we don’t define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. 3593In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor.
2917 3594
2918Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. 3595Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class.
2919 3596
@@ -3000,13 +3677,13 @@ print BackPack.size -- prints 10
3000 3677
3001The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. 3678The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class.
3002 3679
3003The class object can be called like a function in order to create new instances. That’s how we created instances of classes in the examples above. 3680The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above.
3004 3681
3005A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. 3682A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base.
3006 3683
3007The class object’s metatable reads properties from the base if they don’t exist in the class object. This means we can access functions and properties directly from the class. 3684The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class.
3008 3685
3009It is important to note that assigning to the class object does not assign into the base, so it’s not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. 3686It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below.
3010 3687
3011The class object has a couple special properties: 3688The class object has a couple special properties:
3012 3689
@@ -3079,7 +3756,7 @@ print Counter.count -- prints 2
3079</pre> 3756</pre>
3080</YueDisplay> 3757</YueDisplay>
3081 3758
3082The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. 3759The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax.
3083 3760
3084```moonscript 3761```moonscript
3085@@hello 1,2,3,4 3762@@hello 1,2,3,4
@@ -3094,7 +3771,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl
3094 3771
3095In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. 3772In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object.
3096 3773
3097Here is an alternative way to create a class variable compared to whats described above: 3774Here is an alternative way to create a class variable compared to what's described above:
3098 3775
3099```moonscript 3776```moonscript
3100class Things 3777class Things
@@ -3360,19 +4037,19 @@ In this usage, with can be seen as a special form of the K combinator.
3360The expression in the with statement can also be an assignment, if you want to give a name to the expression. 4037The expression in the with statement can also be an assignment, if you want to give a name to the expression.
3361 4038
3362```moonscript 4039```moonscript
3363with str = "Hello" 4040with str := "Hello"
3364 print "original:", str 4041 print "original:", str
3365 print "upper:", \upper! 4042 print "upper:", \upper!
3366``` 4043```
3367<YueDisplay> 4044<YueDisplay>
3368<pre> 4045<pre>
3369with str = "Hello" 4046with str := "Hello"
3370 print "original:", str 4047 print "original:", str
3371 print "upper:", \upper! 4048 print "upper:", \upper!
3372</pre> 4049</pre>
3373</YueDisplay> 4050</YueDisplay>
3374 4051
3375Accessing special keys with `[]` in a `with` statement. 4052You can access special keys with `[]` in a `with` statement.
3376 4053
3377```moonscript 4054```moonscript
3378with tb 4055with tb
@@ -3395,6 +4072,18 @@ with tb
3395</pre> 4072</pre>
3396</YueDisplay> 4073</YueDisplay>
3397 4074
4075`with?` is an enhanced version of `with` syntax, which introduces an existential check to safely access objects that may be nil without explicit null checks.
4076
4077```moonscript
4078with? obj
4079 print obj.name
4080```
4081<YueDisplay>
4082<pre>
4083with? obj
4084 print obj.name
4085</pre>
4086</YueDisplay>
3398 4087
3399## Do 4088## Do
3400 4089
@@ -3415,7 +4104,7 @@ print var -- nil here
3415</pre> 4104</pre>
3416</YueDisplay> 4105</YueDisplay>
3417 4106
3418YueScript’s **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. 4107YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body.
3419 4108
3420```moonscript 4109```moonscript
3421counter = do 4110counter = do
@@ -3541,7 +4230,7 @@ print i -- will print 0
3541</pre> 4230</pre>
3542</YueDisplay> 4231</YueDisplay>
3543 4232
3544In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn’t clear what names have already been declared. 4233In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared.
3545 4234
3546It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. 4235It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident.
3547 4236
@@ -3657,9 +4346,9 @@ The YueScript compiling function. It compiles the YueScript code to Lua code.
3657**Signature:** 4346**Signature:**
3658```lua 4347```lua
3659to_lua: function(code: string, config?: Config): 4348to_lua: function(code: string, config?: Config):
3660 --[[codes]] string | nil, 4349 --[[codes]] string | nil,
3661 --[[error]] string | nil, 4350 --[[error]] string | nil,
3662 --[[globals]] {{string, integer, integer}} | nil 4351 --[[globals]] {{string, integer, integer}} | nil
3663``` 4352```
3664 4353
3665**Parameters:** 4354**Parameters:**
@@ -3782,8 +4471,8 @@ Loads YueScript code from a string into a function.
3782**Signature:** 4471**Signature:**
3783```lua 4472```lua
3784loadstring: function(input: string, chunkname: string, env: table, config?: Config): 4473loadstring: function(input: string, chunkname: string, env: table, config?: Config):
3785 --[[loaded function]] nil | function(...: any): (any...), 4474 --[[loaded function]] nil | function(...: any): (any...),
3786 --[[error]] string | nil 4475 --[[error]] string | nil
3787``` 4476```
3788 4477
3789**Parameters:** 4478**Parameters:**
@@ -3813,8 +4502,8 @@ Loads YueScript code from a string into a function.
3813**Signature:** 4502**Signature:**
3814```lua 4503```lua
3815loadstring: function(input: string, chunkname: string, config?: Config): 4504loadstring: function(input: string, chunkname: string, config?: Config):
3816 --[[loaded function]] nil | function(...: any): (any...), 4505 --[[loaded function]] nil | function(...: any): (any...),
3817 --[[error]] string | nil 4506 --[[error]] string | nil
3818``` 4507```
3819 4508
3820**Parameters:** 4509**Parameters:**
@@ -3843,8 +4532,8 @@ Loads YueScript code from a string into a function.
3843**Signature:** 4532**Signature:**
3844```lua 4533```lua
3845loadstring: function(input: string, config?: Config): 4534loadstring: function(input: string, config?: Config):
3846 --[[loaded function]] nil | function(...: any): (any...), 4535 --[[loaded function]] nil | function(...: any): (any...),
3847 --[[error]] string | nil 4536 --[[error]] string | nil
3848``` 4537```
3849 4538
3850**Parameters:** 4539**Parameters:**
@@ -3872,8 +4561,8 @@ Loads YueScript code from a file into a function.
3872**Signature:** 4561**Signature:**
3873```lua 4562```lua
3874loadfile: function(filename: string, env: table, config?: Config): 4563loadfile: function(filename: string, env: table, config?: Config):
3875 nil | function(...: any): (any...), 4564 nil | function(...: any): (any...),
3876 string | nil 4565 string | nil
3877``` 4566```
3878 4567
3879**Parameters:** 4568**Parameters:**
@@ -3902,8 +4591,8 @@ Loads YueScript code from a file into a function.
3902**Signature:** 4591**Signature:**
3903```lua 4592```lua
3904loadfile: function(filename: string, config?: Config): 4593loadfile: function(filename: string, config?: Config):
3905 nil | function(...: any): (any...), 4594 nil | function(...: any): (any...),
3906 string | nil 4595 string | nil
3907``` 4596```
3908 4597
3909**Parameters:** 4598**Parameters:**
@@ -4158,9 +4847,9 @@ Converts the code to the AST.
4158 4847
4159**Signature:** 4848**Signature:**
4160```lua 4849```lua
4161to_ast: function(code: string, flattenLevel?: number, astName?: string): 4850to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
4162 --[[AST]] AST | nil, 4851 --[[AST]] AST | nil,
4163 --[[error]] nil | string 4852 --[[error]] nil | string
4164``` 4853```
4165 4854
4166**Parameters:** 4855**Parameters:**
@@ -4170,6 +4859,7 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string):
4170| code | string | The code. | 4859| code | string | The code. |
4171| flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | 4860| flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. |
4172| astName | string | [Optional] The AST name. Default is "File". | 4861| astName | string | [Optional] The AST name. Default is "File". |
4862| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. |
4173 4863
4174**Returns:** 4864**Returns:**
4175 4865
@@ -4178,6 +4868,33 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string):
4178| AST \| nil | The AST, or nil if the conversion failed. | 4868| AST \| nil | The AST, or nil if the conversion failed. |
4179| string \| nil | The error message, or nil if the conversion succeeded. | 4869| string \| nil | The error message, or nil if the conversion succeeded. |
4180 4870
4871#### format
4872
4873**Type:** Function.
4874
4875**Description:**
4876
4877Formats the YueScript code.
4878
4879**Signature:**
4880```lua
4881format: function(code: string, tabSize?: number, reserveComment?: boolean): string
4882```
4883
4884**Parameters:**
4885
4886| Parameter | Type | Description |
4887| --- | --- | --- |
4888| code | string | The code. |
4889| tabSize | integer | [Optional] The tab size. Default is 4. |
4890| reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. |
4891
4892**Returns:**
4893
4894| Return Type | Description |
4895| --- | --- |
4896| string | The formatted code. |
4897
4181#### __call 4898#### __call
4182 4899
4183**Type:** Metamethod. 4900**Type:** Metamethod.
@@ -4249,6 +4966,19 @@ Whether the compiler should reserve the original line number in the compiled cod
4249reserve_line_number: boolean 4966reserve_line_number: boolean
4250``` 4967```
4251 4968
4969#### reserve_comment
4970
4971**Type:** Field.
4972
4973**Description:**
4974
4975Whether the compiler should reserve the original comments in the compiled code.
4976
4977**Signature:**
4978```lua
4979reserve_comment: boolean
4980```
4981
4252#### space_over_tab 4982#### space_over_tab
4253 4983
4254**Type:** Field. 4984**Type:** Field.
@@ -4299,11 +5029,11 @@ The target Lua version enumeration.
4299**Signature:** 5029**Signature:**
4300```lua 5030```lua
4301enum LuaTarget 5031enum LuaTarget
4302 "5.1" 5032 "5.1"
4303 "5.2" 5033 "5.2"
4304 "5.3" 5034 "5.3"
4305 "5.4" 5035 "5.4"
4306 "5.5" 5036 "5.5"
4307end 5037end
4308``` 5038```
4309 5039
@@ -4380,7 +5110,7 @@ simplified: boolean
4380 5110
4381## Licence: MIT 5111## Licence: MIT
4382 5112
4383Copyright (c) 2017-2025 Li Jin \<dragon-fly@qq.com\> 5113Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\>
4384 5114
4385Permission is hereby granted, free of charge, to any person obtaining a copy 5115Permission is hereby granted, free of charge, to any person obtaining a copy
4386of this software and associated documentation files (the "Software"), to deal 5116of this software and associated documentation files (the "Software"), to deal
diff --git a/doc/docs/zh/README.md b/doc/docs/zh/README.md
index f5c9811..05b2069 100755
--- a/doc/docs/zh/README.md
+++ b/doc/docs/zh/README.md
@@ -3,6 +3,6 @@ home: true
3heroImage: /image/yuescript.svg 3heroImage: /image/yuescript.svg
4actionText: 快速上手 → 4actionText: 快速上手 →
5actionLink: /zh/doc/ 5actionLink: /zh/doc/
6footer: MIT Licensed | Copyright © 2017-2025 Li Jin 6footer: MIT Licensed | Copyright © 2017-2026 Li Jin
7--- 7---
8 8
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 754566c..43713fe 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -9,26 +9,36 @@ title: 参考手册
9 9
10## 介绍 10## 介绍
11 11
12月之脚本(YueScript)是一种动态语言,可以编译为Lua。它是[MoonScript](https://github.com/leafo/moonscript)的方言。用月之脚本编写的代码既有表现力又非常简洁。它适合编写一些更易于维护的代码,并在嵌入 Lua 的环境中运行,如游戏或网站服务器。 12月之脚本(YueScript)是一种动态语言,可以编译为 Lua。它是 [MoonScript](https://github.com/leafo/moonscript) 的方言。用月之脚本编写的代码既有表现力又非常简洁。它适合编写一些更易于维护的代码,并在嵌入 Lua 的环境中运行,如游戏或网站服务器。
13 13
14Yue(月)是中文中“月亮”的名称。 14Yue(月)是中文中“月亮”的名称。
15 15
16### 月之脚本概览 16### 月之脚本概览
17```moonscript 17```moonscript
18-- 导入语法 18-- 导入语法
19import "yue" as :p, :to_lua 19import p, to_lua from "yue"
20 20
21-- 隐式对象 21-- 隐式对象
22inventory = 22inventory =
23 equipment: 23 equipment:
24 * "sword" 24 - "sword"
25 * "shield" 25 - "shield"
26 items: 26 items:
27 * name: "potion" 27 - name: "potion"
28 count: 10 28 count: 10
29 * name: "bread" 29 - name: "bread"
30 count: 3 30 count: 3
31 31
32-- 列表推导
33map = (arr, action) ->
34 [action item for item in *arr]
35
36filter = (arr, cond) ->
37 [item for item in *arr when cond item]
38
39reduce = (arr, init, action): init ->
40 init = action init, item for item in *arr
41
32-- 管道操作符 42-- 管道操作符
33[1, 2, 3] 43[1, 2, 3]
34 |> map (x) -> x * 2 44 |> map (x) -> x * 2
@@ -51,19 +61,29 @@ export 🌛 = "月之脚本"
51<YueDisplay> 61<YueDisplay>
52<pre> 62<pre>
53-- 导入语法 63-- 导入语法
54import "yue" as :p, :to_lua 64import p, to_lua from "yue"
55 65
56-- 隐式对象 66-- 隐式对象
57inventory = 67inventory =
58 equipment: 68 equipment:
59 * "sword" 69 - "sword"
60 * "shield" 70 - "shield"
61 items: 71 items:
62 * name: "potion" 72 - name: "potion"
63 count: 10 73 count: 10
64 * name: "bread" 74 - name: "bread"
65 count: 3 75 count: 3
66 76
77-- 列表推导
78map = (arr, action) ->
79 [action item for item in *arr]
80
81filter = (arr, cond) ->
82 [item for item in *arr when cond item]
83
84reduce = (arr, init, action): init ->
85 init = action init, item for item in *arr
86
67-- 管道操作符 87-- 管道操作符
68[1, 2, 3] 88[1, 2, 3]
69 |> map (x) -> x * 2 89 |> map (x) -> x * 2
@@ -89,7 +109,7 @@ export 🌛 = "月之脚本"
89 109
90* **Lua 模块** 110* **Lua 模块**
91 111
92&emsp;安装 [luarocks](https://luarocks.org),一个Lua模块的包管理器。然后作为Lua模块和可执行文件安装它: 112&emsp;安装 [luarocks](https://luarocks.org),一个 Lua 模块的包管理器。然后作为 Lua 模块和可执行文件安装它:
93 113
94``` 114```
95> luarocks install yuescript 115> luarocks install yuescript
@@ -122,7 +142,7 @@ export 🌛 = "月之脚本"
122 142
123* **下载预编译的二进制程序** 143* **下载预编译的二进制程序**
124 144
125&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。 145&emsp;可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。
126 146
127&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。 147&emsp;在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。
128 148
@@ -130,16 +150,16 @@ export 🌛 = "月之脚本"
130 150
131### Lua 模块 151### Lua 模块
132 152
133在Lua中使用月之脚本模块: 153 Lua 中使用月之脚本模块:
134 154
135* **用法 1** 155* **用法 1**
136在Lua中引入 "你的脚本入口文件.yue"。 156 Lua 中引入 "你的脚本入口文件.yue"。
137```Lua 157```Lua
138require("yue")("你的脚本入口文件") 158require("yue")("你的脚本入口文件")
139``` 159```
140当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import**进行脚本引用即可。错误消息中的代码行号也会被正确处理。 160当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import** 进行脚本引用即可。错误消息中的代码行号也会被正确处理。
141 161
142* **用法 2** 162* **用法 2**
143手动引入月之脚本模块并重写错误消息来帮助调试。 163手动引入月之脚本模块并重写错误消息来帮助调试。
144```lua 164```lua
145local yue = require("yue") 165local yue = require("yue")
@@ -151,8 +171,8 @@ end, function(err)
151end) 171end)
152``` 172```
153 173
154* **用法 3** 174* **用法 3**
155在Lua中使用月之脚本编译器功能。 175 Lua 中使用月之脚本编译器功能。
156```lua 176```lua
157local yue = require("yue") 177local yue = require("yue")
158local codes, err, globals = yue.to_lua([[ 178local codes, err, globals = yue.to_lua([[
@@ -333,7 +353,7 @@ end
333 353
334### 导出宏 354### 导出宏
335 355
336宏函数可以从一个模块中导出,并在另一个模块中导入。您必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 356宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。
337```moonscript 357```moonscript
338-- 文件: utils.yue 358-- 文件: utils.yue
339export macro map = (items, action) -> "[#{action} for _ in *#{items}]" 359export macro map = (items, action) -> "[#{action} for _ in *#{items}]"
@@ -387,16 +407,16 @@ print $LINE -- 获取当前代码行数:2
387 407
388```moonscript 408```moonscript
389macro Enum = (...) -> 409macro Enum = (...) ->
390 items = {...} 410 items = {...}
391 itemSet = {item, true for item in *items} 411 itemSet = {item, true for item in *items}
392 (item) -> 412 (item) ->
393 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] 413 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
394 "\"#{item}\"" 414 "\"#{item}\""
395 415
396macro BodyType = $Enum( 416macro BodyType = $Enum(
397 Static 417 Static
398 Dynamic 418 Dynamic
399 Kinematic 419 Kinematic
400) 420)
401 421
402print "有效的枚举类型:", $BodyType Static 422print "有效的枚举类型:", $BodyType Static
@@ -405,16 +425,16 @@ print "有效的枚举类型:", $BodyType Static
405<YueDisplay> 425<YueDisplay>
406<pre> 426<pre>
407macro Enum = (...) -> 427macro Enum = (...) ->
408 items = {...} 428 items = {...}
409 itemSet = {item, true for item in *items} 429 itemSet = {item, true for item in *items}
410 (item) -> 430 (item) ->
411 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] 431 error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item]
412 "\"#{item}\"" 432 "\"#{item}\""
413 433
414macro BodyType = $Enum( 434macro BodyType = $Enum(
415 Static 435 Static
416 Dynamic 436 Dynamic
417 Kinematic 437 Kinematic
418) 438)
419 439
420print "有效的枚举类型:", $BodyType Static 440print "有效的枚举类型:", $BodyType Static
@@ -422,9 +442,57 @@ print "有效的枚举类型:", $BodyType Static
422</pre> 442</pre>
423</YueDisplay> 443</YueDisplay>
424 444
445### 宏参数检查
446
447可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。
448
449```moonscript
450macro printNumAndStr = (num `Num, str `String) -> |
451 print(
452 #{num}
453 #{str}
454 )
455
456$printNumAndStr 123, "hello"
457```
458<YueDisplay>
459<pre>
460macro printNumAndStr = (num `Num, str `String) -> |
461 print(
462 #{num}
463 #{str}
464 )
465
466$printNumAndStr 123, "hello"
467</pre>
468</YueDisplay>
469
470如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。
471
472```moonscript
473macro printNumAndStr = (num, str) ->
474 error "expected Num as first argument" unless $is_ast Num, num
475 error "expected String as second argument" unless $is_ast String, str
476 "print(#{num}, #{str})"
477
478$printNumAndStr 123, "hello"
479```
480<YueDisplay>
481<pre>
482macro printNumAndStr = (num, str) ->
483 error "expected Num as first argument" unless $is_ast Num, num
484 error "expected String as second argument" unless $is_ast String, str
485 "print(#{num}, #{str})"
486
487$printNumAndStr 123, "hello"
488</pre>
489</YueDisplay>
490
491更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。
492
425## 操作符 493## 操作符
426 494
427Lua的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 495Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。
428 496
429```moonscript 497```moonscript
430tb\func! if tb ~= nil 498tb\func! if tb ~= nil
@@ -439,7 +507,7 @@ tb::func! if tb != nil
439 507
440### 链式比较 508### 链式比较
441 509
442可以在月之脚本中进行比较表达式的链式书写: 510可以在月之脚本中进行比较表达式的链式书写:
443 511
444```moonscript 512```moonscript
445print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 513print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
@@ -464,56 +532,56 @@ print 1 <= a <= 10
464 532
465```moonscript 533```moonscript
466v = (x) -> 534v = (x) ->
467 print x 535 print x
468 x 536 x
469 537
470print v(1) < v(2) <= v(3) 538print v(1) < v(2) <= v(3)
471--[[ 539--[[
472 输出: 540 输出:
473 2 541 2
474 1 542 1
475 3 543 3
476 true 544 true
477]] 545]]
478 546
479print v(1) > v(2) <= v(3) 547print v(1) > v(2) <= v(3)
480--[[ 548--[[
481 输出: 549 输出:
482 2 550 2
483 1 551 1
484 false 552 false
485]] 553]]
486``` 554```
487<YueDisplay> 555<YueDisplay>
488<pre> 556<pre>
489v = (x) -> 557v = (x) ->
490 print x 558 print x
491 x 559 x
492 560
493print v(1) < v(2) <= v(3) 561print v(1) < v(2) <= v(3)
494--[[ 562--[[
495 输出: 563 输出:
496 2 564 2
497 1 565 1
498 3 566 3
499 true 567 true
500]] 568]]
501 569
502print v(1) > v(2) <= v(3) 570print v(1) > v(2) <= v(3)
503--[[ 571--[[
504 输出: 572 输出:
505 2 573 2
506 1 574 1
507 false 575 false
508]] 576]]
509</pre> 577</pre>
510</YueDisplay> 578</YueDisplay>
511 579
512在上面的例子里,中间的表达式`v(2)`仅被计算一次,如果把表达式写成`v(1) < v(2) and v(2) <= v(3)`的方式,中间的`v(2)`才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。 580在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。
513 581
514### 表追加 582### 表追加
515 583
516**[] =** 操作符用于向Lua表的最后插入值。 584**[] =** 操作符用于向 Lua 表的最后插入值。
517 585
518```moonscript 586```moonscript
519tab = [] 587tab = []
@@ -526,19 +594,36 @@ tab[] = "Value"
526</pre> 594</pre>
527</YueDisplay> 595</YueDisplay>
528 596
597你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
598
599```moonscript
600tbA = [1, 2, 3]
601tbB = [4, 5, 6]
602tbA[] = ...tbB
603-- tbA 现在为 [1, 2, 3, 4, 5, 6]
604```
605<YueDisplay>
606<pre>
607tbA = [1, 2, 3]
608tbB = [4, 5, 6]
609tbA[] = ...tbB
610-- tbA 现在为 [1, 2, 3, 4, 5, 6]
611</pre>
612</YueDisplay>
613
529### 表扩展 614### 表扩展
530 615
531可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。 616可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。
532 617
533```moonscript 618```moonscript
534parts = 619parts =
535 * "shoulders" 620 * "shoulders"
536 * "knees" 621 * "knees"
537lyrics = 622lyrics =
538 * "head" 623 * "head"
539 * ...parts 624 * ...parts
540 * "and" 625 * "and"
541 * "toes" 626 * "toes"
542 627
543copy = {...other} 628copy = {...other}
544 629
@@ -549,13 +634,13 @@ merge = {...a, ...b}
549<YueDisplay> 634<YueDisplay>
550<pre> 635<pre>
551parts = 636parts =
552 * "shoulders" 637 * "shoulders"
553 * "knees" 638 * "knees"
554lyrics = 639lyrics =
555 * "head" 640 * "head"
556 * ...parts 641 * ...parts
557 * "and" 642 * "and"
558 * "toes" 643 * "toes"
559 644
560copy = {...other} 645copy = {...other}
561 646
@@ -565,12 +650,29 @@ merge = {...a, ...b}
565</pre> 650</pre>
566</YueDisplay> 651</YueDisplay>
567 652
653### 表反向索引
654
655你可以使用 **#** 操作符来反向索引表中的元素。
656
657```moonscript
658last = data.items[#]
659second_last = data.items[#-1]
660data.items[#] = 1
661```
662<YueDisplay>
663<pre>
664last = data.items[#]
665second_last = data.items[#-1]
666data.items[#] = 1
667</pre>
668</YueDisplay>
669
568### 元表 670### 元表
569 671
570**<>** 操作符可提供元表操作的快捷方式。 672**<>** 操作符可提供元表操作的快捷方式。
571 673
572* **元表创建** 674* **元表创建**
573使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 675使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。
574 676
575```moonscript 677```moonscript
576mt = {} 678mt = {}
@@ -605,7 +707,7 @@ close _ = &lt;close&gt;: -> print "超出范围"
605</pre> 707</pre>
606</YueDisplay> 708</YueDisplay>
607 709
608* **元表访问** 710* **元表访问**
609使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 711使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。
610 712
611```moonscript 713```moonscript
@@ -629,7 +731,7 @@ print tb.item
629</pre> 731</pre>
630</YueDisplay> 732</YueDisplay>
631 733
632* **元表解构** 734* **元表解构**
633使用被 **<>** 包围的元方法键解构元表。 735使用被 **<>** 包围的元方法键解构元表。
634 736
635```moonscript 737```moonscript
@@ -680,7 +782,7 @@ with? io.open "test.txt", "w"
680 782
681### 管道 783### 管道
682 784
683与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。 785与其使用一系列嵌套的函数调用,还可以考虑使用运算符 **|>** 来传递值。
684 786
685```moonscript 787```moonscript
686"你好" |> print 788"你好" |> print
@@ -712,7 +814,7 @@ readFile "example.txt"
712 814
713### 空值合并 815### 空值合并
714 816
715如果其左操作数不是**nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非nil的值,**??** 运算符将不再计算其右操作数。 817如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。
716```moonscript 818```moonscript
717local a, b, c, d 819local a, b, c, d
718a = b ?? c ?? d 820a = b ?? c ?? d
@@ -731,67 +833,87 @@ a ??= false
731 833
732### 隐式对象 834### 隐式对象
733 835
734您可以在表格块内使用符号 **\*** 开始编写一系列隐式结构。如果您正在创建隐式对象,对象的字段必须具有相同的缩进。 836你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。
837
735```moonscript 838```moonscript
839-- 赋值时使用隐式对象
736list = 840list =
737 * 1 841 * 1
738 * 2 842 * 2
739 * 3 843 * 3
740 844
845-- 函数调用时使用隐式对象
741func 846func
742 * 1 847 * 1
743 * 2 848 * 2
744 * 3 849 * 3
745 850
851-- 返回时使用隐式对象
852f = ->
853 return
854 * 1
855 * 2
856 * 3
857
858-- 表格时使用隐式对象
746tb = 859tb =
747 name: "abc" 860 name: "abc"
748 861
749 values: 862 values:
750 * "a" 863 - "a"
751 * "b" 864 - "b"
752 * "c" 865 - "c"
753 866
754 objects: 867 objects:
755 * name: "a" 868 - name: "a"
756 value: 1 869 value: 1
757 func: => @value + 1 870 func: => @value + 1
758 tb: 871 tb:
759 fieldA: 1 872 fieldA: 1
760 873
761 * name: "b" 874 - name: "b"
762 value: 2 875 value: 2
763 func: => @value + 2 876 func: => @value + 2
764 tb: { } 877 tb: { }
765
766``` 878```
767<YueDisplay> 879<YueDisplay>
768<pre> 880<pre>
881-- 赋值时使用隐式对象
769list = 882list =
770 * 1 883 * 1
771 * 2 884 * 2
772 * 3 885 * 3
773 886
887-- 函数调用时使用隐式对象
774func 888func
775 * 1 889 * 1
776 * 2 890 * 2
777 * 3 891 * 3
778 892
893-- 返回时使用隐式对象
894f = ->
895 return
896 * 1
897 * 2
898 * 3
899
900-- 表格时使用隐式对象
779tb = 901tb =
780 name: "abc" 902 name: "abc"
781 903
782 values: 904 values:
783 * "a" 905 - "a"
784 * "b" 906 - "b"
785 * "c" 907 - "c"
786 908
787 objects: 909 objects:
788 * name: "a" 910 - name: "a"
789 value: 1 911 value: 1
790 func: => @value + 1 912 func: => @value + 1
791 tb: 913 tb:
792 fieldA: 1 914 fieldA: 1
793 915
794 * name: "b" 916 - name: "b"
795 value: 2 917 value: 2
796 func: => @value + 2 918 func: => @value + 2
797 tb: { } 919 tb: { }
@@ -855,11 +977,67 @@ do
855</pre> 977</pre>
856</YueDisplay> 978</YueDisplay>
857 979
980### 导入全局变量
981
982你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。
983
984```moonscript
985do
986 import tostring
987 import table.concat
988 print concat ["a", tostring 1]
989```
990<YueDisplay>
991<pre>
992do
993 import tostring
994 import table.concat
995 print concat ["a", tostring 1]
996</pre>
997</YueDisplay>
998
999#### 自动导入
1000
1001在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。
1002
1003但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。
1004
1005```moonscript
1006do
1007 import global
1008 print "hello"
1009 math.random 3
1010 -- print = nil -- 报错:自动导入的全局变量为常量
1011
1012do
1013 -- 被显式声明为全局的变量不会被自动导入
1014 import global
1015 global FLAG
1016 print FLAG
1017 FLAG = 123
1018```
1019<YueDisplay>
1020<pre>
1021do
1022 import global
1023 print "hello"
1024 math.random 3
1025 -- print = nil -- 报错:自动导入的全局变量是常量
1026
1027do
1028 -- 被显式声明为全局的变量不会被自动导入
1029 import global
1030 global FLAG
1031 print FLAG
1032 FLAG = 123
1033</pre>
1034</YueDisplay>
1035
858### 导出 1036### 导出
859 1037
860导出语句提供了一种简洁的方式来定义当前的模块。 1038导出语句提供了一种简洁的方式来定义当前的模块。
861 1039
862* **命名导出** 1040* **命名导出**
863带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。 1041带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。
864 1042
865```moonscript 1043```moonscript
@@ -923,7 +1101,7 @@ export["a-b-c"] = 123
923</pre> 1101</pre>
924</YueDisplay> 1102</YueDisplay>
925 1103
926* **未命名导出** 1104* **未命名导出**
927未命名导出会将要导出的目标项目添加到导出表的数组部分。 1105未命名导出会将要导出的目标项目添加到导出表的数组部分。
928 1106
929```moonscript 1107```moonscript
@@ -953,7 +1131,7 @@ export with tmp
953</pre> 1131</pre>
954</YueDisplay> 1132</YueDisplay>
955 1133
956* **默认导出** 1134* **默认导出**
957在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 1135在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。
958 1136
959```moonscript 1137```moonscript
@@ -971,7 +1149,7 @@ export default ->
971 1149
972## 赋值 1150## 赋值
973 1151
974月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过**local**和**global**声明来改变声明变量的作用范围。 1152月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。
975 1153
976```moonscript 1154```moonscript
977hello = "world" 1155hello = "world"
@@ -1100,9 +1278,9 @@ do
1100 1278
1101## 解构赋值 1279## 解构赋值
1102 1280
1103解构赋值是一种快速从Lua表中按名称或基于数组中的位置提取值的方法。 1281解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。
1104 1282
1105通常当你看到一个字面量的Lua表,比如{1,2,3},它位于赋值的右侧,因为它是一个值。解构赋值语句的写法就是交换了字面量Lua表的角色,并将其放在赋值语句的左侧。 1283通常当你看到一个字面量的 Lua 表,比如 `{1,2,3}`,它位于赋值的右侧,因为它是一个值。解构赋值语句的写法就是交换了字面量 Lua 表的角色,并将其放在赋值语句的左侧。
1106 1284
1107最好是通过示例来解释。以下是如何从表格中解包前两个值的方法: 1285最好是通过示例来解释。以下是如何从表格中解包前两个值的方法:
1108 1286
@@ -1201,7 +1379,7 @@ print first, second, color
1201</pre> 1379</pre>
1202</YueDisplay> 1380</YueDisplay>
1203 1381
1204有时候我们会需要从Lua表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符: 1382有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符:
1205 1383
1206```moonscript 1384```moonscript
1207{:concat, :insert} = table 1385{:concat, :insert} = table
@@ -1223,7 +1401,7 @@ print first, second, color
1223</pre> 1401</pre>
1224</YueDisplay> 1402</YueDisplay>
1225 1403
1226在进行解构时,可以指定默认值,如: 1404在进行解构时,可以指定默认值,如:
1227 1405
1228```moonscript 1406```moonscript
1229{:name = "nameless", :job = "jobless"} = person 1407{:name = "nameless", :job = "jobless"} = person
@@ -1234,7 +1412,7 @@ print first, second, color
1234</pre> 1412</pre>
1235</YueDisplay> 1413</YueDisplay>
1236 1414
1237在进行列表解构时,可以使用`_`作为占位符: 1415在进行列表解构时,可以使用`_`作为占位符:
1238 1416
1239```moonscript 1417```moonscript
1240[_, two, _, four] = items 1418[_, two, _, four] = items
@@ -1245,9 +1423,55 @@ print first, second, color
1245</pre> 1423</pre>
1246</YueDisplay> 1424</YueDisplay>
1247 1425
1248### 在其方的解构 1426### 解构
1249 1427
1250解构也可以出现在其它隐式进行赋值的地方。一个例子是用在for循环: 1428你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。
1429
1430```moonscript
1431orders = ["first", "second", "third", "fourth", "last"]
1432[first, ...bulk, last] = orders
1433print first -- 打印: first
1434print bulk -- 打印: {"second", "third", "fourth"}
1435print last -- 打印: last
1436```
1437<YueDisplay>
1438<pre>
1439orders = ["first", "second", "third", "fourth", "last"]
1440[first, ...bulk, last] = orders
1441print first -- 打印: first
1442print bulk -- 打印: {"second", "third", "fourth"}
1443print last -- 打印: last
1444</pre>
1445</YueDisplay>
1446
1447展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获:
1448
1449```moonscript
1450-- 捕获第一个元素之后的所有元素
1451[first, ...rest] = orders
1452
1453-- 捕获最后一个元素之前的所有元素
1454[...start, last] = orders
1455
1456-- 跳过中间的元素,只捕获第一个和最后一个元素
1457[first, ..._, last] = orders
1458```
1459<YueDisplay>
1460<pre>
1461-- 捕获第一个元素之后的所有元素
1462[first, ...rest] = orders
1463
1464-- 捕获最后一个元素之前的所有元素
1465[...start, last] = orders
1466
1467-- 跳过中间的元素,只捕获第一个和最后一个元素
1468[first, ..._, last] = orders
1469</pre>
1470</YueDisplay>
1471
1472### 在其它地方的解构赋值
1473
1474解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中:
1251 1475
1252```moonscript 1476```moonscript
1253tuples = [ 1477tuples = [
@@ -1270,7 +1494,7 @@ for [left, right] in *tuples
1270</pre> 1494</pre>
1271</YueDisplay> 1495</YueDisplay>
1272 1496
1273我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在for语句的名称子句中使用解构来解包它。 1497我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。
1274 1498
1275## If 赋值 1499## If 赋值
1276 1500
@@ -1322,7 +1546,7 @@ print "好的"
1322 1546
1323### While 赋值 1547### While 赋值
1324 1548
1325可以在 while 循环中同样使用赋值来获取循环条件的值。 1549可以在 while 循环中同样使用赋值来获取循环条件的值。
1326```moonscript 1550```moonscript
1327while byte := stream\read_one! 1551while byte := stream\read_one!
1328 -- 对 byte 做一些操作 1552 -- 对 byte 做一些操作
@@ -1338,7 +1562,7 @@ while byte := stream\read_one!
1338 1562
1339## 可变参数赋值 1563## 可变参数赋值
1340 1564
1341可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用Lua的方式访问其内容。 1565可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。
1342```moonscript 1566```moonscript
1343list = [1, 2, 3, 4, 5] 1567list = [1, 2, 3, 4, 5]
1344fn = (ok) -> ok, table.unpack list 1568fn = (ok) -> ok, table.unpack list
@@ -1360,7 +1584,20 @@ print ok, count, first
1360 1584
1361## 空白 1585## 空白
1362 1586
1363月之脚本是一个对空白敏感的语言。您必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 1587月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。
1588
1589### 语句分隔符
1590
1591一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句:
1592
1593```moonscript
1594a = 1; b = 2; print a + b
1595```
1596<YueDisplay>
1597<pre>
1598a = 1; b = 2; print a + b
1599</pre>
1600</YueDisplay>
1364 1601
1365### 多行链式调用 1602### 多行链式调用
1366 1603
@@ -1415,7 +1652,7 @@ func --[[端口]] 3000, --[[ip]] "192.168.1.1"
1415 1652
1416## 错误处理 1653## 错误处理
1417 1654
1418用于统一进行Lua错误处理的便捷语法。 1655用于统一进行 Lua 错误处理的便捷语法。
1419 1656
1420```moonscript 1657```moonscript
1421try 1658try
@@ -1474,9 +1711,50 @@ catch err
1474</pre> 1711</pre>
1475</YueDisplay> 1712</YueDisplay>
1476 1713
1714### 错误处理简化
1715
1716`try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。
1717
1718```moonscript
1719a, b, c = try? func!
1720
1721-- 与空值合并运算符一起使用
1722a = (try? func!) ?? "default"
1723
1724-- 作为函数参数
1725f try? func!
1726
1727-- 带 catch 块的 try!
1728f try?
1729 print 123
1730 func!
1731catch e
1732 print e
1733 e
1734```
1735<YueDisplay>
1736<pre>
1737a, b, c = try? func!
1738
1739-- 与空值合并运算符一起使用
1740a = (try? func!) ?? "default"
1741
1742-- 作为函数参数
1743f try? func!
1744
1745-- 带 catch 块的 try!
1746f try?
1747 print 123
1748 func!
1749catch e
1750 print e
1751 e
1752</pre>
1753</YueDisplay>
1754
1477## 属性 1755## 属性
1478 1756
1479月之脚本现在提供了Lua 5.4新增的叫做属性的语法支持。在月之脚本编译到的Lua目标版本低于5.4时,你仍然可以同时使用`const`和`close`的属性声明语法,并获得常量检查和作用域回调的功能。 1757月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。
1480 1758
1481```moonscript 1759```moonscript
1482const a = 123 1760const a = 123
@@ -1502,11 +1780,24 @@ const {:a, :b, c, d} = tb
1502</pre> 1780</pre>
1503</YueDisplay> 1781</YueDisplay>
1504 1782
1783你也可以声明全局变量为常量。
1784
1785```moonscript
1786global const Constant = 123
1787-- Constant = 1
1788```
1789<YueDisplay>
1790<pre>
1791global const Constant = 123
1792-- Constant = 1
1793</pre>
1794</YueDisplay>
1795
1505## 字面量 1796## 字面量
1506 1797
1507Lua中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和**nil**。 1798Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。
1508 1799
1509但与Lua不同的是,单引号和双引号字符串内部允许有换行: 1800但与 Lua 不同的是,单引号和双引号字符串内部允许有换行:
1510 1801
1511```moonscript 1802```moonscript
1512some_string = "这是一个字符串 1803some_string = "这是一个字符串
@@ -1529,17 +1820,78 @@ print "我有#{math.random! * 100}%的把握。"
1529 1820
1530### 数字字面量 1821### 数字字面量
1531 1822
1532可以在数字字面量中使用下划线来增加可读性。 1823可以在数字字面量中使用下划线来增加可读性。
1533 1824
1534```moonscript 1825```moonscript
1535integer = 1_000_000 1826integer = 1_000_000
1536hex = 0xEF_BB_BF 1827hex = 0xEF_BB_BF
1828binary = 0B10011
1537``` 1829```
1538<YueDisplay> 1830<YueDisplay>
1539 1831
1540<pre> 1832<pre>
1541integer = 1_000_000 1833integer = 1_000_000
1542hex = 0xEF_BB_BF 1834hex = 0xEF_BB_BF
1835binary = 0B10011
1836</pre>
1837</YueDisplay>
1838
1839### YAML 风格字符串
1840
1841使用 `|` 前缀标记一个多行 YAML 风格字符串:
1842
1843```moonscript
1844str = |
1845 key: value
1846 list:
1847 - item1
1848 - #{expr}
1849```
1850<YueDisplay>
1851<pre>
1852str = |
1853 key: value
1854 list:
1855 - item1
1856 - #{expr}
1857</pre>
1858</YueDisplay>
1859
1860其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。
1861
1862YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。
1863
1864```moonscript
1865fn = ->
1866 str = |
1867 foo:
1868 bar: baz
1869 return str
1870```
1871<YueDisplay>
1872<pre>
1873fn = ->
1874 str = |
1875 foo:
1876 bar: baz
1877 return str
1878</pre>
1879</YueDisplay>
1880
1881输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。
1882
1883支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义:
1884
1885```moonscript
1886str = |
1887 path: "C:\Program Files\App"
1888 note: 'He said: "#{Hello}!"'
1889```
1890<YueDisplay>
1891<pre>
1892str = |
1893 path: "C:\Program Files\App"
1894 note: 'He said: "#{Hello}!"'
1543</pre> 1895</pre>
1544</YueDisplay> 1896</YueDisplay>
1545 1897
@@ -1644,7 +1996,7 @@ print "数字的和是", sum 10, 20
1644</pre> 1996</pre>
1645</YueDisplay> 1997</YueDisplay>
1646 1998
1647如果需要做显式返回,可以使用return关键字: 1999如果需要做显式返回,可以使用 return 关键字:
1648 2000
1649```moonscript 2001```moonscript
1650sum = (x, y) -> return x + y 2002sum = (x, y) -> return x + y
@@ -1670,7 +2022,7 @@ a, b = mystery 10, 20
1670 2022
1671### 粗箭头 2023### 粗箭头
1672 2024
1673因为在Lua中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含self参数的函数。 2025因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。
1674 2026
1675```moonscript 2027```moonscript
1676func = (num) => @value + num 2028func = (num) => @value + num
@@ -1683,7 +2035,7 @@ func = (num) => @value + num
1683 2035
1684### 参数默认值 2036### 参数默认值
1685 2037
1686可以为函数的参数提供默认值。如果参数的值为nil,则确定该参数为空。任何具有默认值的nil参数在函数体运行之前都会被替换。 2038可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。
1687 2039
1688```moonscript 2040```moonscript
1689my_function = (name = "某物", height = 100) -> 2041my_function = (name = "某物", height = 100) ->
@@ -1755,7 +2107,7 @@ my_func 5, 6, 7,
1755</pre> 2107</pre>
1756</YueDisplay> 2108</YueDisplay>
1757 2109
1758因为Lua表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是Lua表的一部分。 2110因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。
1759 2111
1760```moonscript 2112```moonscript
1761x = [ 2113x = [
@@ -1822,6 +2174,138 @@ if func 1, 2, 3,
1822</pre> 2174</pre>
1823</YueDisplay> 2175</YueDisplay>
1824 2176
2177### 参数解构
2178
2179月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量:
2180
2181- 使用 {} 包裹的字面量/对象形参,支持提供获得空字段时的默认值(例如 {:a, :b}、{a: a1 = 123})。
2182
2183- 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。
2184
2185```moonscript
2186f1 = (:a, :b, :c) ->
2187 print a, b, c
2188
2189f1 a: 1, b: "2", c: {}
2190
2191f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2192 print a1, b, c
2193
2194arg1 = {a: 0}
2195f2 arg1, arg2
2196```
2197<YueDisplay>
2198<pre>
2199f1 = (:a, :b, :c) ->
2200 print a, b, c
2201
2202f1 a: 1, b: "2", c: {}
2203
2204f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) ->
2205 print a1, b, c
2206
2207arg1 = {a: 0}
2208f2 arg1, arg2
2209</pre>
2210</YueDisplay>
2211
2212### 前置返回表达式
2213
2214在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下:
2215
2216```moon
2217findFirstEven = (list): nil ->
2218 for item in *list
2219 if type(item) == "table"
2220 for sub in *item
2221 if sub % 2 == 0
2222 return sub
2223```
2224<YueDisplay>
2225<pre>
2226findFirstEven = (list): nil ->
2227 for item in *list
2228 if type(item) == "table"
2229 for sub in *item
2230 if sub % 2 == 0
2231 return sub
2232</pre>
2233</YueDisplay>
2234
2235这个写法等价于:
2236
2237```moon
2238findFirstEven = (list) ->
2239 for item in *list
2240 if type(item) == "table"
2241 for sub in *item
2242 if sub % 2 == 0
2243 return sub
2244 nil
2245```
2246<YueDisplay>
2247<pre>
2248findFirstEven = (list) ->
2249 for item in *list
2250 if type(item) == "table"
2251 for sub in *item
2252 if sub % 2 == 0
2253 return sub
2254 nil
2255</pre>
2256</YueDisplay>
2257
2258唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。
2259
2260### 命名变长参数
2261
2262你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。
2263
2264```moonscript
2265f = (...t) ->
2266 print "参数个数:", t.n
2267 print "表长度:", #t
2268 for i = 1, t.n
2269 print t[i]
2270
2271f 1, 2, 3
2272f "a", "b", "c", "d"
2273f!
2274
2275-- 处理包含 nil 的情况
2276process = (...args) ->
2277 sum = 0
2278 for i = 1, args.n
2279 if args[i] != nil and type(args[i]) == "number"
2280 sum += args[i]
2281 sum
2282
2283process 1, nil, 3, nil, 5
2284```
2285<YueDisplay>
2286<pre>
2287f = (...t) ->
2288 print "参数个数:", t.n
2289 print "表长度:", #t
2290 for i = 1, t.n
2291 print t[i]
2292
2293f 1, 2, 3
2294f "a", "b", "c", "d"
2295f!
2296
2297-- 处理包含 nil 的情况
2298process = (...args) ->
2299 sum = 0
2300 for i = 1, args.n
2301 if args[i] != nil and type(args[i]) == "number"
2302 sum += args[i]
2303 sum
2304
2305process 1, nil, 3, nil, 5
2306</pre>
2307</YueDisplay>
2308
1825## 反向回调 2309## 反向回调
1826 2310
1827反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。 2311反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。
@@ -1850,7 +2334,7 @@ print @value
1850</pre> 2334</pre>
1851</YueDisplay> 2335</YueDisplay>
1852 2336
1853可以通过一个占位符指定回调函数的传参位置。 2337可以通过一个占位符指定回调函数的传参位置。
1854 2338
1855```moonscript 2339```moonscript
1856(x) <- map _, [1, 2, 3] 2340(x) <- map _, [1, 2, 3]
@@ -1863,22 +2347,22 @@ x * 2
1863</pre> 2347</pre>
1864</YueDisplay> 2348</YueDisplay>
1865 2349
1866如果您希望在反向回调处理后继续编写更多其它的代码,您可以使用do语句将不归属反向回调的代码分开。 2350如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。
1867 2351
1868```moonscript 2352```moonscript
1869result, msg = do 2353result, msg = do
1870 (data) <- readAsync "文件名.txt" 2354 data <- readAsync "文件名.txt"
1871 print data 2355 print data
1872 (info) <- processAsync data 2356 info <- processAsync data
1873 check info 2357 check info
1874print result, msg 2358print result, msg
1875``` 2359```
1876<YueDisplay> 2360<YueDisplay>
1877<pre> 2361<pre>
1878result, msg = do 2362result, msg = do
1879 (data) <- readAsync "文件名.txt" 2363 data <- readAsync "文件名.txt"
1880 print data 2364 print data
1881 (info) <- processAsync data 2365 info <- processAsync data
1882 check info 2366 check info
1883print result, msg 2367print result, msg
1884</pre> 2368</pre>
@@ -1886,7 +2370,7 @@ print result, msg
1886 2370
1887## 表格字面量 2371## 表格字面量
1888 2372
1889和Lua一样,表格可以通过花括号进行定义。 2373 Lua 一样,表格可以通过花括号进行定义。
1890 2374
1891```moonscript 2375```moonscript
1892some_values = [1, 2, 3, 4] 2376some_values = [1, 2, 3, 4]
@@ -1969,7 +2453,7 @@ y = type: "狗", legs: 4, tails: 1
1969</pre> 2453</pre>
1970</YueDisplay> 2454</YueDisplay>
1971 2455
1972表格字面量的键可以使用Lua语言的关键字,而无需转义: 2456表格字面量的键可以使用 Lua 语言的关键字,而无需转义:
1973 2457
1974```moonscript 2458```moonscript
1975tbl = { 2459tbl = {
@@ -2005,7 +2489,7 @@ print_table :hair, :height
2005</pre> 2489</pre>
2006</YueDisplay> 2490</YueDisplay>
2007 2491
2008如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在Lua中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。 2492如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。
2009 2493
2010```moonscript 2494```moonscript
2011t = { 2495t = {
@@ -2022,7 +2506,7 @@ t = {
2022</pre> 2506</pre>
2023</YueDisplay> 2507</YueDisplay>
2024 2508
2025Lua的表同时具有数组部分和哈希部分,但有时候你会希望在书写Lua表时,对Lua表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。 2509Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。
2026 2510
2027```moonscript 2511```moonscript
2028some_values = [ 1, 2, 3, 4 ] 2512some_values = [ 1, 2, 3, 4 ]
@@ -2037,11 +2521,11 @@ list_with_one_element = [ 1, ]
2037 2521
2038## 推导式 2522## 推导式
2039 2523
2040推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生Lua表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许您在每次遍历时设置新表格的键和值。 2524推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。
2041 2525
2042### 列表推导式 2526### 列表推导式
2043 2527
2044以下操作创建了一个items表的副本,但所有包含的值都翻倍了。 2528以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。
2045 2529
2046```moonscript 2530```moonscript
2047items = [1, 2, 3, 4] 2531items = [1, 2, 3, 4]
@@ -2054,7 +2538,7 @@ doubled = [item * 2 for i, item in ipairs items]
2054</pre> 2538</pre>
2055</YueDisplay> 2539</YueDisplay>
2056 2540
2057可以使用when子句筛选新表中包含的项目: 2541可以使用 `when` 子句筛选新表中包含的项目:
2058 2542
2059```moonscript 2543```moonscript
2060slice = [item for i, item in ipairs items when i > 1 and i < 3] 2544slice = [item for i, item in ipairs items when i > 1 and i < 3]
@@ -2065,7 +2549,7 @@ slice = [item for i, item in ipairs items when i > 1 and i < 3]
2065</pre> 2549</pre>
2066</YueDisplay> 2550</YueDisplay>
2067 2551
2068因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled示例可以重写为: 2552因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为:
2069 2553
2070```moonscript 2554```moonscript
2071doubled = [item * 2 for item in *items] 2555doubled = [item * 2 for item in *items]
@@ -2076,9 +2560,30 @@ doubled = [item * 2 for item in *items]
2076</pre> 2560</pre>
2077</YueDisplay> 2561</YueDisplay>
2078 2562
2079for和when子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个for子句。 2563在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
2564
2565```moonscript
2566data =
2567 a: [1, 2, 3]
2568 b: [4, 5, 6]
2569
2570flat = [...v for k,v in pairs data]
2571-- flat 现在为 [1, 2, 3, 4, 5, 6]
2572```
2573<YueDisplay>
2574<pre>
2575data =
2576 a: [1, 2, 3]
2577 b: [4, 5, 6]
2578
2579flat = [...v for k,v in pairs data]
2580-- flat 现在为 [1, 2, 3, 4, 5, 6]
2581</pre>
2582</YueDisplay>
2583
2584for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。
2080 2585
2081使用多个for子句与使用多重循环的效果相同: 2586使用多个 for 子句与使用多重循环的效果相同:
2082 2587
2083```moonscript 2588```moonscript
2084x_coords = [4, 5, 6, 7] 2589x_coords = [4, 5, 6, 7]
@@ -2097,7 +2602,7 @@ for y in *y_coords]
2097</pre> 2602</pre>
2098</YueDisplay> 2603</YueDisplay>
2099 2604
2100在推导式中也可以使用简单的数值for循环: 2605在推导式中也可以使用简单的数值 for 循环:
2101 2606
2102```moonscript 2607```moonscript
2103evens = [i for i = 1, 100 when i % 2 == 0] 2608evens = [i for i = 1, 100 when i % 2 == 0]
@@ -2112,7 +2617,7 @@ evens = [i for i = 1, 100 when i % 2 == 0]
2112 2617
2113表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。 2618表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。
2114 2619
2115以下示例生成了表格thing的副本: 2620以下示例生成了表格 thing 的副本:
2116 2621
2117```moonscript 2622```moonscript
2118thing = { 2623thing = {
@@ -2174,9 +2679,9 @@ tbl = {unpack tuple for tuple in *tuples}
2174 2679
2175### 切片 2680### 切片
2176 2681
2177当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在for循环中设置迭代边界和步长。 2682当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。
2178 2683
2179下面的案例中,我们在切片中设置最小和最大边界,取索引在1到5之间(包括1和5)的所有项目: 2684下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目:
2180 2685
2181```moonscript 2686```moonscript
2182slice = [item for item in *items[1, 5]] 2687slice = [item for item in *items[1, 5]]
@@ -2198,7 +2703,7 @@ slice = [item for item in *items[2,]]
2198</pre> 2703</pre>
2199</YueDisplay> 2704</YueDisplay>
2200 2705
2201如果省略了最小边界,便默认会设置为1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …) 2706如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …)
2202 2707
2203```moonscript 2708```moonscript
2204slice = [item for item in *items[,,2]] 2709slice = [item for item in *items[,,2]]
@@ -2210,9 +2715,48 @@ slice = [item for item in *items[,,2]]
2210</pre> 2715</pre>
2211</YueDisplay> 2716</YueDisplay>
2212 2717
2718最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。
2719
2720```moonscript
2721-- 取最后4个元素
2722slice = [item for item in *items[-4,-1]]
2723```
2724<YueDisplay>
2725<pre>
2726-- 取最后4个元素
2727slice = [item for item in *items[-4,-1]]
2728</pre>
2729</YueDisplay>
2730
2731切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。
2732
2733```moonscript
2734reverse_slice = [item for item in *items[-1,1,-1]]
2735```
2736<YueDisplay>
2737<pre>
2738reverse_slice = [item for item in *items[-1,1,-1]]
2739</pre>
2740</YueDisplay>
2741
2742#### 切片表达式
2743
2744切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。
2745
2746```moonscript
2747-- 取第2和第4个元素作为新的列表
2748sub_list = items[2, 4]
2749```
2750<YueDisplay>
2751<pre>
2752-- 取第2和第4个元素作为新的列表
2753sub_list = items[2, 4]
2754</pre>
2755</YueDisplay>
2756
2213## for 循环 2757## for 循环
2214 2758
2215Lua中有两种for循环形式,数字型和通用型: 2759Lua 中有两种 for 循环形式,数字型和通用型:
2216 2760
2217```moonscript 2761```moonscript
2218for i = 10, 20 2762for i = 10, 20
@@ -2265,7 +2809,7 @@ for j = 1, 10, 3 do print j
2265</pre> 2809</pre>
2266</YueDisplay> 2810</YueDisplay>
2267 2811
2268for循环也可以用作表达式。for循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。 2812for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。
2269 2813
2270将每个偶数加倍: 2814将每个偶数加倍:
2271 2815
@@ -2286,9 +2830,24 @@ doubled_evens = for i = 1, 20
2286</pre> 2830</pre>
2287</YueDisplay> 2831</YueDisplay>
2288 2832
2289您还可以结合for循环表达式与continue语句来过滤值。 2833此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。
2834
2835例如,查找第一个大于 10 的数字:
2836
2837```moonscript
2838first_large = for n in *numbers
2839 break n if n > 10
2840```
2841<YueDisplay>
2842<pre>
2843first_large = for n in *numbers
2844 break n if n > 10
2845</pre>
2846</YueDisplay>
2847
2848你还可以结合 for 循环表达式与 continue 语句来过滤值。
2290 2849
2291注意出现在函数体末尾的for循环,不会被当作是一个表达式,并将循环结果累积到一个列表中作为返回值(相反,函数将返回nil)。如果要函数末尾的循环转换为列表表达式,可以使用返回语句加for循环表达式。 2850注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。
2292 2851
2293```moonscript 2852```moonscript
2294func_a = -> for i = 1, 10 do print i 2853func_a = -> for i = 1, 10 do print i
@@ -2311,7 +2870,7 @@ print func_b! -- 打印 table 对象
2311 2870
2312## repeat 循环 2871## repeat 循环
2313 2872
2314repeat循环是从Lua语言中搬过来的相似语法: 2873repeat 循环是从 Lua 语言中搬过来的相似语法:
2315 2874
2316```moonscript 2875```moonscript
2317i = 10 2876i = 10
@@ -2332,7 +2891,7 @@ until i == 0
2332 2891
2333## while 循环 2892## while 循环
2334 2893
2335在月之脚本中的while循环有四种写法: 2894在月之脚本中的 while 循环有四种写法:
2336 2895
2337```moonscript 2896```moonscript
2338i = 10 2897i = 10
@@ -2371,7 +2930,7 @@ until running == false do my_function!
2371</pre> 2930</pre>
2372</YueDisplay> 2931</YueDisplay>
2373 2932
2374像for循环的语法一样,while循环也可以作为一个表达式使用。为了使函数返回while循环的累积列表值,必须明确使用返回语句返回while循环表达式。 2933像 for 循环的语法一样,while 循环也可以作为一个表达式使用。为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。
2375 2934
2376## 继续 2935## 继续
2377 2936
@@ -2489,13 +3048,14 @@ print message -- 打印: 我很高
2489</pre> 3048</pre>
2490</YueDisplay> 3049</YueDisplay>
2491 3050
2492if的反义词是unless(相当于if not,如果 vs 除非): 3051if 的反义词是 unless(相当于 if not,“如”对应“除非):
2493 3052
2494```moonscript 3053```moonscript
2495unless os.date("%A") == "Monday" 3054unless os.date("%A") == "Monday"
2496 print "今天不是星期一!" 3055 print "今天不是星期一!"
2497``` 3056```
2498<YueDisplay> 3057<YueDisplay>
3058
2499<pre> 3059<pre>
2500unless os.date("%A") == "Monday" 3060unless os.date("%A") == "Monday"
2501 print "今天不是星期一!" 3061 print "今天不是星期一!"
@@ -2513,7 +3073,7 @@ print "你真幸运!" unless math.random! > 0.1
2513 3073
2514### 范围表达式 3074### 范围表达式
2515 3075
2516可以使用范围表达式来编写进行范围检查的代码。 3076可以使用范围表达式来编写进行范围检查的代码。
2517 3077
2518```moonscript 3078```moonscript
2519a = 5 3079a = 5
@@ -2547,7 +3107,7 @@ print "你很幸运!" unless math.random! > 0.1
2547 3107
2548## 代码行修饰符 3108## 代码行修饰符
2549 3109
2550为了方便编写代码,循环语句和if语句可以应用于单行代码语句的末尾: 3110为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾:
2551 3111
2552```moonscript 3112```moonscript
2553print "你好,世界" if name == "Rob" 3113print "你好,世界" if name == "Rob"
@@ -2558,7 +3118,7 @@ print "你好,世界" if name == "Rob"
2558</pre> 3118</pre>
2559</YueDisplay> 3119</YueDisplay>
2560 3120
2561修饰for循环的示例: 3121修饰 for 循环的示例:
2562 3122
2563```moonscript 3123```moonscript
2564print "项目: ", item for item in *items 3124print "项目: ", item for item in *items
@@ -2569,7 +3129,7 @@ print "项目: ", item for item in *items
2569</pre> 3129</pre>
2570</YueDisplay> 3130</YueDisplay>
2571 3131
2572修饰while循环的示例: 3132修饰 while 循环的示例:
2573 3133
2574```moonscript 3134```moonscript
2575game\update! while game\isRunning! 3135game\update! while game\isRunning!
@@ -2586,34 +3146,32 @@ reader\parse_line! until reader\eof!
2586 3146
2587## switch 语句 3147## switch 语句
2588 3148
2589switch语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和if语句一样,switch语句在最后可以接一个else代码块来处理没有匹配的情况。在生成的Lua代码中,进行比较是使用==操作符完成的。 3149switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。
2590 3150
2591```moonscript 3151```moonscript
2592name = "Dan" 3152switch name := "Dan"
2593switch name
2594 when "Robert" 3153 when "Robert"
2595 print "你是Robert" 3154 print "你是Robert"
2596 when "Dan", "Daniel" 3155 when "Dan", "Daniel"
2597 print "你的名字是Dan" 3156 print "你的名字是Dan"
2598 else 3157 else
2599 print "我不知道你的名字" 3158 print "我不认识,你的名字是#{name}"
2600``` 3159```
2601<YueDisplay> 3160<YueDisplay>
2602<pre> 3161<pre>
2603name = "Dan" 3162switch name := "Dan"
2604switch name
2605 when "Robert" 3163 when "Robert"
2606 print "你是Robert" 3164 print "你是Robert"
2607 when "Dan", "Daniel" 3165 when "Dan", "Daniel"
2608 print "你的名字是Dan" 3166 print "你的名字是Dan"
2609 else 3167 else
2610 print "我不知道你的名字" 3168 print "我不认识,你的名字是#{name}"
2611</pre> 3169</pre>
2612</YueDisplay> 3170</YueDisplay>
2613 3171
2614switch语句的when子句中可以通过使用逗号分隔的列表来匹配多个值。 3172switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。
2615 3173
2616switch语句也可以作为表达式使用,下面我们可以将switch语句返回的结果分配给一个变量: 3174switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量:
2617 3175
2618```moonscript 3176```moonscript
2619b = 1 3177b = 1
@@ -2638,7 +3196,7 @@ next_number = switch b
2638</pre> 3196</pre>
2639</YueDisplay> 3197</YueDisplay>
2640 3198
2641我们可以使用then关键字在when子句的同一行上编写处理代码。else代码块的后续代码中要写在同一行上不需要额外的关键字。 3199我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。
2642 3200
2643```moonscript 3201```moonscript
2644msg = switch math.random(1, 5) 3202msg = switch math.random(1, 5)
@@ -2655,7 +3213,7 @@ msg = switch math.random(1, 5)
2655</pre> 3213</pre>
2656</YueDisplay> 3214</YueDisplay>
2657 3215
2658如果在编写switch语句时希望少写一个缩进,那么你可以把第一个when子句放在switch开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。 3216如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。
2659 3217
2660```moonscript 3218```moonscript
2661switch math.random(1, 5) 3219switch math.random(1, 5)
@@ -2684,11 +3242,11 @@ else
2684</pre> 3242</pre>
2685</YueDisplay> 3243</YueDisplay>
2686 3244
2687值得注意的是,在生成Lua代码时,我们要做检查的目标变量会放在==表达式的右侧。当您希望给when子句的比较对象定义一个\_\_eq元方法来重载判断逻辑时,可能会有用。 3245值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。
2688 3246
2689### 表格匹配 3247### 表格匹配
2690 3248
2691在switch的when子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非nil值,那么你可以尝试使用表格匹配的语法。 3249在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。
2692 3250
2693```moonscript 3251```moonscript
2694items = 3252items =
@@ -2744,9 +3302,126 @@ switch item
2744</pre> 3302</pre>
2745</YueDisplay> 3303</YueDisplay>
2746 3304
3305你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。
3306
3307匹配数组元素。
3308
3309```moonscript
3310switch tb
3311 when [1, 2, 3]
3312 print "1, 2, 3"
3313 when [1, b, 3]
3314 print "1, #{b}, 3"
3315 when [1, 2, b = 3] -- 变量b有默认值
3316 print "1, 2, #{b}"
3317```
3318<YueDisplay>
3319<pre>
3320switch tb
3321 when [1, 2, 3]
3322 print "1, 2, 3"
3323 when [1, b, 3]
3324 print "1, #{b}, 3"
3325 when [1, 2, b = 3] -- 变量b有默认值
3326 print "1, 2, #{b}"
3327</pre>
3328</YueDisplay>
3329
3330匹配表格字段。
3331
3332```moonscript
3333switch tb
3334 when success: true, :result
3335 print "成功", result
3336 when success: false
3337 print "失败", result
3338 else
3339 print "无效值"
3340```
3341<YueDisplay>
3342<pre>
3343switch tb
3344 when success: true, :result
3345 print "成功", result
3346 when success: false
3347 print "失败", result
3348 else
3349 print "无效值"
3350</pre>
3351</YueDisplay>
3352
3353匹配嵌套的表格结构。
3354
3355```moonscript
3356switch tb
3357 when data: {type: "success", :content}
3358 print "成功", content
3359 when data: {type: "error", :content}
3360 print "失败", content
3361 else
3362 print "无效值"
3363```
3364<YueDisplay>
3365<pre>
3366switch tb
3367 when data: {type: "success", :content}
3368 print "成功", content
3369 when data: {type: "error", :content}
3370 print "失败", content
3371 else
3372 print "无效值"
3373</pre>
3374</YueDisplay>
3375
3376匹配表格数组。
3377
3378```moonscript
3379switch tb
3380 when [
3381 {a: 1, b: 2}
3382 {a: 3, b: 4}
3383 {a: 5, b: 6}
3384 fourth
3385 ]
3386 print "匹配成功", fourth
3387```
3388<YueDisplay>
3389<pre>
3390switch tb
3391 when [
3392 {a: 1, b: 2}
3393 {a: 3, b: 4}
3394 {a: 5, b: 6}
3395 fourth
3396 ]
3397 print "匹配成功", fourth
3398</pre>
3399</YueDisplay>
3400
3401匹配一个列表并捕获特定范围内的元素。
3402
3403```moonscript
3404segments = ["admin", "users", "logs", "view"]
3405switch segments
3406 when [...groups, resource, action]
3407 print "Group:", groups -- 打印: {"admin", "users"}
3408 print "Resource:", resource -- 打印: "logs"
3409 print "Action:", action -- 打印: "view"
3410```
3411<YueDisplay>
3412<pre>
3413segments = ["admin", "users", "logs", "view"]
3414switch segments
3415 when [...groups, resource, action]
3416 print "Group:", groups -- 打印: {"admin", "users"}
3417 print "Resource:", resource -- 打印: "logs"
3418 print "Action:", action -- 打印: "view"
3419</pre>
3420</YueDisplay>
3421
2747## 面向对象编程 3422## 面向对象编程
2748 3423
2749在以下的示例中,月之脚本生成的Lua代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果您想知道关于面向对象功能的实现细节,再查看Lua代码。 3424在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。
2750 3425
2751一个简单的类: 3426一个简单的类:
2752 3427
@@ -2775,11 +3450,11 @@ class Inventory
2775</pre> 3450</pre>
2776</YueDisplay> 3451</YueDisplay>
2777 3452
2778在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合Lua表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为“new”的成员扮演了一个重要的角色,是作为构造函数来使用。 3453在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。
2779 3454
2780值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为“self”的参数。 3455值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。
2781 3456
2782此外,“@”前缀在变量名上起到了简化作用,代表“self”。例如,`@items` 就等同于 `self.items`。 3457此外,“@” 前缀在变量名上起到了简化作用,代表 “self”。例如,`@items` 就等同于 `self.items`。
2783 3458
2784为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。 3459为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。
2785 3460
@@ -2801,7 +3476,7 @@ inv\add_item "pants"
2801 3476
2802需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。 3477需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。
2803 3478
2804例如,在下面的示例中,clothes属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。 3479例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。
2805 3480
2806```moonscript 3481```moonscript
2807class Person 3482class Person
@@ -2853,7 +3528,7 @@ class Person
2853 3528
2854### 继承 3529### 继承
2855 3530
2856`extends`关键字可以在类声明中使用,以继承另一个类的属性和方法。 3531`extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。
2857 3532
2858```moonscript 3533```moonscript
2859class BackPack extends Inventory 3534class BackPack extends Inventory
@@ -2873,11 +3548,11 @@ class BackPack extends Inventory
2873</YueDisplay> 3548</YueDisplay>
2874 3549
2875 3550
2876在这一部分,我们对月之脚本中的`Inventory`类进行了扩展,加入了对可以携带物品数量的限制。 3551在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。
2877 3552
2878在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用`super`方法来调用并执行父类的构造函数。 3553在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。
2879 3554
2880此外,当一个类继承自另一个类时,它会尝试调用父类上的`__inherited`方法(如果这个方法存在的话),以此来向父类发送通知。这个`__inherited`函数接受两个参数:被继承的父类和继承的子类。 3555此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。
2881 3556
2882```moonscript 3557```moonscript
2883class Shelf 3558class Shelf
@@ -2900,15 +3575,15 @@ class Cupboard extends Shelf
2900 3575
2901### super 关键字 3576### super 关键字
2902 3577
2903`super`是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。 3578`super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。
2904 3579
2905当`super`被作为一个函数调用时,它将调用父类中与之同名的函数。此时,当前的`self`会自动作为第一个参数传递,正如上面提到的继承示例所展示的那样。 3580当 `super` 被作为一个函数调用时,它将调用父类中与之同名的函数。此时,当前的 `self` 会自动作为第一个参数传递,正如上面提到的继承示例所展示的那样。
2906 3581
2907在将`super`当作普通值使用时,它实际上是对父类对象的引用。通过这种方式,我们可以访问父类中可能被子类覆盖的值,就像访问任何普通对象一样。 3582在将 `super` 当作普通值使用时,它实际上是对父类对象的引用。通过这种方式,我们可以访问父类中可能被子类覆盖的值,就像访问任何普通对象一样。
2908 3583
2909此外,当使用`\`操作符与`super`一起使用时,`self`将被插入为第一个参数,而不是使用`super`本身的值。而在使用`.`操作符来检索函数时,则会返回父类中的原始函数。 3584此外,当使用 `\` 操作符与 `super` 一起使用时,`self`将被插入为第一个参数,而不是使用 `super` 本身的值。而在使用`.`操作符来检索函数时,则会返回父类中的原始函数。
2910 3585
2911下面是一些使用`super`的不同方法的示例: 3586下面是一些使用 `super` 的不同方法的示例:
2912 3587
2913```moonscript 3588```moonscript
2914class MyClass extends ParentClass 3589class MyClass extends ParentClass
@@ -2967,9 +3642,9 @@ print BackPack.size -- 打印 10
2967 3642
2968如果在类对象的元表中找不到某个属性,系统会从基表中检索该属性。这就意味着我们可以直接从类本身访问到其方法和属性。 3643如果在类对象的元表中找不到某个属性,系统会从基表中检索该属性。这就意味着我们可以直接从类本身访问到其方法和属性。
2969 3644
2970需要特别注意的是,对类对象的赋值并不会影响到基表,因此这不是向实例添加新方法的正确方式。相反,需要直接修改基表。关于这点,可以参考下面的“__base”字段。 3645需要特别注意的是,对类对象的赋值并不会影响到基表,因此这不是向实例添加新方法的正确方式。相反,需要直接修改基表。关于这点,可以参考下面的 “__base” 字段。
2971 3646
2972此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的“__name”字段中。 3647此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “__name” 字段中。
2973 3648
2974```moonscript 3649```moonscript
2975print BackPack.__name -- 打印 Backpack 3650print BackPack.__name -- 打印 Backpack
@@ -3051,7 +3726,7 @@ print Counter.count -- 输出 2
3051 3726
3052### 类声明语句 3727### 类声明语句
3053 3728
3054在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self等于类对象,而不是实例对象。 3729在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。
3055 3730
3056以下是创建类变量的另一种方法: 3731以下是创建类变量的另一种方法:
3057 3732
@@ -3091,9 +3766,9 @@ class MoreThings
3091 3766
3092### @ 和 @@ 值 3767### @ 和 @@ 值
3093 3768
3094当@和@@前缀在一个名字前时,它们分别代表在self和self.\_\_class中访问的那个名字。 3769 @ @@ 前缀在一个名字前时,它们分别代表在 self self.\_\_class 中访问的那个名字。
3095 3770
3096如果它们单独使用,它们是self和self.\_\_class的别名。 3771如果它们单独使用,它们是 self self.\_\_class 的别名。
3097 3772
3098```moonscript 3773```moonscript
3099assert @ == self 3774assert @ == self
@@ -3106,7 +3781,7 @@ assert @@ == self.__class
3106</pre> 3781</pre>
3107</YueDisplay> 3782</YueDisplay>
3108 3783
3109例如,使用@@从实例方法快速创建同一类的新实例的方法: 3784例如,使用 @@ 从实例方法快速创建同一类的新实例的方法:
3110 3785
3111```moonscript 3786```moonscript
3112some_instance_method = (...) => @@ ... 3787some_instance_method = (...) => @@ ...
@@ -3184,7 +3859,7 @@ x = class Bucket
3184 3859
3185### 匿名类 3860### 匿名类
3186 3861
3187声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name属性将为nil。如果出现在赋值语句中,赋值操作左侧的名称将代替nil。 3862声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。
3188 3863
3189```moonscript 3864```moonscript
3190BigBucket = class extends Bucket 3865BigBucket = class extends Bucket
@@ -3214,7 +3889,7 @@ x = class
3214 3889
3215### 类混合 3890### 类混合
3216 3891
3217您可以通过使用 `using` 关键字来实现类混合。这意味着您可以从一个普通 Lua 表格或已定义的类对象中,复制函数到您创建的新类中。当您使用普通 Lua 表格进行类混合时,您有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当您从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 3892你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。
3218 3893
3219```moonscript 3894```moonscript
3220MyIndex = __index: var: 1 3895MyIndex = __index: var: 1
@@ -3255,11 +3930,11 @@ assert y.__class.__parent ~= X -- X 不是 Y 的父类
3255 3930
3256## with 语句 3931## with 语句
3257 3932
3258在编写Lua代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。 3933在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。
3259 3934
3260这导致在代码中多次重复引用对象的名称,增加了不必要的文本噪音。一个常见的解决方案是在创建对象时,在构造函数传入一个表,该表包含要覆盖设置的键和值的集合。这样做的缺点是该对象的构造函数必须支持这种初始化形式。 3935这导致在代码中多次重复引用对象的名称,增加了不必要的文本噪音。一个常见的解决方案是在创建对象时,在构造函数传入一个表,该表包含要覆盖设置的键和值的集合。这样做的缺点是该对象的构造函数必须支持这种初始化形式。
3261 3936
3262with块有助于简化编写这样的代码。在with块内,我们可以使用以.或\开头的特殊语句,这些语句代表我们正在使用的对象的操作。 3937with 块有助于简化编写这样的代码。在 with 块内,我们可以使用以 . 或 \ 开头的特殊语句,这些语句代表我们正在使用的对象的操作。
3263 3938
3264例如,我们可以这样处理一个新创建的对象: 3939例如,我们可以这样处理一个新创建的对象:
3265 3940
@@ -3280,7 +3955,7 @@ with Person!
3280</pre> 3955</pre>
3281</YueDisplay> 3956</YueDisplay>
3282 3957
3283with语句也可以用作一个表达式,并返回它的代码块正在处理的对象。 3958with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。
3284 3959
3285```moonscript 3960```moonscript
3286file = with File "favorite_foods.txt" 3961file = with File "favorite_foods.txt"
@@ -3314,24 +3989,24 @@ me = create_person "Leaf", [dad, mother, sister]
3314</pre> 3989</pre>
3315</YueDisplay> 3990</YueDisplay>
3316 3991
3317在此用法中,with可以被视为K组合子(k-combinator)的一种特殊形式。 3992在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。
3318 3993
3319如果给表达式另外起一个名称的话,with语句中的表达式也可以是一个赋值语句。 3994如果想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。
3320 3995
3321```moonscript 3996```moonscript
3322with str = "你好" 3997with str := "你好"
3323 print "原始:", str 3998 print "原始:", str
3324 print "大写:", \upper! 3999 print "大写:", \upper!
3325``` 4000```
3326<YueDisplay> 4001<YueDisplay>
3327<pre> 4002<pre>
3328with str = "你好" 4003with str := "你好"
3329 print "原始:", str 4004 print "原始:", str
3330 print "大写:", \upper! 4005 print "大写:", \upper!
3331</pre> 4006</pre>
3332</YueDisplay> 4007</YueDisplay>
3333 4008
3334在with语句中用`[]`访问特殊键。 4009 `with` 语句中使用 `[]` 访问特殊键。
3335 4010
3336```moonscript 4011```moonscript
3337with tb 4012with tb
@@ -3354,9 +4029,22 @@ with tb
3354</pre> 4029</pre>
3355</YueDisplay> 4030</YueDisplay>
3356 4031
4032`with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。
4033
4034```moonscript
4035with? obj
4036 print obj.name
4037```
4038<YueDisplay>
4039<pre>
4040with? obj
4041 print obj.name
4042</pre>
4043</YueDisplay>
4044
3357## do 语句 4045## do 语句
3358 4046
3359当用作语句时,do语句的作用就像在Lua中差不多。 4047当用作语句时,do 语句的作用就像在 Lua 中差不多。
3360 4048
3361```moonscript 4049```moonscript
3362do 4050do
@@ -3373,7 +4061,7 @@ print var -- 这里是nil
3373</pre> 4061</pre>
3374</YueDisplay> 4062</YueDisplay>
3375 4063
3376月之脚本的 **do** 也可以用作表达式。允许您将多行代码的处理合并为一个表达式,并将do语句代码块的最后一个语句作为表达式返回的结果。 4064月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。
3377 4065
3378```moonscript 4066```moonscript
3379counter = do 4067counter = do
@@ -3557,7 +4245,7 @@ print i, k -- 这些已经被更新
3557 4245
3558## 月之脚本语言库 4246## 月之脚本语言库
3559 4247
3560使用`require("yue")`来访问。 4248使用 `require("yue")` 来访问。
3561 4249
3562### yue 4250### yue
3563 4251
@@ -3615,9 +4303,9 @@ yue_compiled: {string: string}
3615**签名:** 4303**签名:**
3616```lua 4304```lua
3617to_lua: function(code: string, config?: Config): 4305to_lua: function(code: string, config?: Config):
3618 --[[codes]] string | nil, 4306 --[[codes]] string | nil,
3619 --[[error]] string | nil, 4307 --[[error]] string | nil,
3620 --[[globals]] {{string, integer, integer}} | nil 4308 --[[globals]] {{string, integer, integer}} | nil
3621``` 4309```
3622 4310
3623**参数:** 4311**参数:**
@@ -3740,8 +4428,8 @@ remove_loader: function(): boolean
3740**签名:** 4428**签名:**
3741```lua 4429```lua
3742loadstring: function(input: string, chunkname: string, env: table, config?: Config): 4430loadstring: function(input: string, chunkname: string, env: table, config?: Config):
3743 --[[loaded function]] nil | function(...: any): (any...), 4431 --[[loaded function]] nil | function(...: any): (any...),
3744 --[[error]] string | nil 4432 --[[error]] string | nil
3745``` 4433```
3746 4434
3747**参数:** 4435**参数:**
@@ -3771,8 +4459,8 @@ loadstring: function(input: string, chunkname: string, env: table, config?: Conf
3771**签名:** 4459**签名:**
3772```lua 4460```lua
3773loadstring: function(input: string, chunkname: string, config?: Config): 4461loadstring: function(input: string, chunkname: string, config?: Config):
3774 --[[loaded function]] nil | function(...: any): (any...), 4462 --[[loaded function]] nil | function(...: any): (any...),
3775 --[[error]] string | nil 4463 --[[error]] string | nil
3776``` 4464```
3777 4465
3778**参数:** 4466**参数:**
@@ -3801,8 +4489,8 @@ loadstring: function(input: string, chunkname: string, config?: Config):
3801**签名:** 4489**签名:**
3802```lua 4490```lua
3803loadstring: function(input: string, config?: Config): 4491loadstring: function(input: string, config?: Config):
3804 --[[loaded function]] nil | function(...: any): (any...), 4492 --[[loaded function]] nil | function(...: any): (any...),
3805 --[[error]] string | nil 4493 --[[error]] string | nil
3806``` 4494```
3807 4495
3808**参数:** 4496**参数:**
@@ -3830,8 +4518,8 @@ loadstring: function(input: string, config?: Config):
3830**签名:** 4518**签名:**
3831```lua 4519```lua
3832loadfile: function(filename: string, env: table, config?: Config): 4520loadfile: function(filename: string, env: table, config?: Config):
3833 nil | function(...: any): (any...), 4521 nil | function(...: any): (any...),
3834 string | nil 4522 string | nil
3835``` 4523```
3836 4524
3837**参数:** 4525**参数:**
@@ -3860,8 +4548,8 @@ loadfile: function(filename: string, env: table, config?: Config):
3860**签名:** 4548**签名:**
3861```lua 4549```lua
3862loadfile: function(filename: string, config?: Config): 4550loadfile: function(filename: string, config?: Config):
3863 nil | function(...: any): (any...), 4551 nil | function(...: any): (any...),
3864 string | nil 4552 string | nil
3865``` 4553```
3866 4554
3867**参数:** 4555**参数:**
@@ -4116,9 +4804,9 @@ type AST = {string, integer, integer, any}
4116 4804
4117**签名:** 4805**签名:**
4118```lua 4806```lua
4119to_ast: function(code: string, flattenLevel?: number, astName?: string): 4807to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean):
4120 --[[AST]] AST | nil, 4808 --[[AST]] AST | nil,
4121 --[[error]] nil | string 4809 --[[error]] nil | string
4122``` 4810```
4123 4811
4124**参数:** 4812**参数:**
@@ -4127,6 +4815,42 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string):
4127| --- | --- | --- | 4815| --- | --- | --- |
4128| code | string | 代码。 | 4816| code | string | 代码。 |
4129| flattenLevel | integer | [可选] 扁平化级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | 4817| flattenLevel | integer | [可选] 扁平化级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 |
4818| astName | string | [可选] AST 名称。默认为 "File"。 |
4819| reserveComment | boolean | [可选] 是否保留原始注释。默认为 false。 |
4820
4821**返回值:**
4822
4823| 返回类型 | 描述 |
4824| --- | --- |
4825| AST \| nil | AST,如果转换失败则为 nil。 |
4826| string \| nil | 错误消息,如果转换成功则为 nil。 |
4827
4828#### format
4829
4830**类型:** 函数。
4831
4832**描述:**
4833
4834格式化 YueScript 代码。
4835
4836**签名:**
4837```lua
4838format: function(code: string, tabSize?: number, reserveComment?: boolean): string
4839```
4840
4841**参数:**
4842
4843| 参数名 | 类型 | 描述 |
4844| --- | --- | --- |
4845| code | string | 代码。 |
4846| tabSize | integer | [可选] 制表符大小。默认为 4。 |
4847| reserveComment | boolean | [可选] 是否保留原始注释。默认为 true。 |
4848
4849**返回值:**
4850
4851| 返回类型 | 描述 |
4852| --- | --- |
4853| string | 格式化后的代码。 |
4130 4854
4131#### __call 4855#### __call
4132 4856
@@ -4199,6 +4923,19 @@ implicit_return_root: boolean
4199reserve_line_number: boolean 4923reserve_line_number: boolean
4200``` 4924```
4201 4925
4926#### reserve_comment
4927
4928**类型:** 成员变量。
4929
4930**描述:**
4931
4932编译器是否应该在编译后的代码中保留原始注释。
4933
4934**签名:**
4935```lua
4936reserve_comment: boolean
4937```
4938
4202#### space_over_tab 4939#### space_over_tab
4203 4940
4204**类型:** 成员变量。 4941**类型:** 成员变量。
@@ -4249,11 +4986,11 @@ line_offset: integer
4249**签名:** 4986**签名:**
4250```lua 4987```lua
4251enum LuaTarget 4988enum LuaTarget
4252 "5.1" 4989 "5.1"
4253 "5.2" 4990 "5.2"
4254 "5.3" 4991 "5.3"
4255 "5.4" 4992 "5.4"
4256 "5.5" 4993 "5.5"
4257end 4994end
4258``` 4995```
4259 4996
@@ -4332,8 +5069,8 @@ simplified: boolean
4332 5069
4333版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\> 5070版权 (c) 2017-2025 李瑾 \<dragon-fly@qq.com\>
4334 5071
4335特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下: 5072特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下:
4336上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。 5073上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。
4337本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。 5074本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。
4338 5075
4339<CompilerModal /> 5076<CompilerModal />