diff options
| -rw-r--r-- | doc/yue-de.md | 5881 | ||||
| -rw-r--r-- | doc/yue-en.md | 5895 | ||||
| -rw-r--r-- | doc/yue-id-id.md | 5890 | ||||
| -rw-r--r-- | doc/yue-pt-br.md | 5890 | ||||
| -rw-r--r-- | doc/yue-zh.md | 5866 | ||||
| -rw-r--r-- | makefile | 5 | ||||
| -rw-r--r-- | spec/inputs/compile_doc.yue | 10 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_de.lua | 24 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_en.lua | 24 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_id-id.lua | 24 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_pt-br.lua | 24 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_zh.lua | 24 | ||||
| -rw-r--r-- | spec/outputs/compile_doc.lua | 26 |
13 files changed, 29573 insertions, 10 deletions
diff --git a/doc/yue-de.md b/doc/yue-de.md new file mode 100644 index 0000000..36d96cd --- /dev/null +++ b/doc/yue-de.md | |||
| @@ -0,0 +1,5881 @@ | |||
| 1 | --- | ||
| 2 | title: Referenz | ||
| 3 | --- | ||
| 4 | |||
| 5 | # YueScript-Dokumentation | ||
| 6 | |||
| 7 | <img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em; padding-bottom: 2em;"/> | ||
| 8 | |||
| 9 | Willkommen in der offiziellen <b>YueScript</b>-Dokumentation!<br/> | ||
| 10 | Hier findest du Sprachfeatures, Nutzung, Referenzbeispiele und Ressourcen.<br/> | ||
| 11 | Bitte wähle ein Kapitel in der Seitenleiste, um mit YueScript zu beginnen. | ||
| 12 | |||
| 13 | # Do | ||
| 14 | |||
| 15 | Als Statement verhält sich `do` wie in Lua. | ||
| 16 | |||
| 17 | ```yuescript | ||
| 18 | do | ||
| 19 | var = "hallo" | ||
| 20 | print var | ||
| 21 | print var -- nil hier | ||
| 22 | ``` | ||
| 23 | |||
| 24 | <YueDisplay> | ||
| 25 | |||
| 26 | ```yue | ||
| 27 | do | ||
| 28 | var = "hallo" | ||
| 29 | print var | ||
| 30 | print var -- nil hier | ||
| 31 | ``` | ||
| 32 | |||
| 33 | </YueDisplay> | ||
| 34 | |||
| 35 | YueScripts **do** kann auch als Ausdruck verwendet werden. So kannst du mehrere Zeilen in einem Ausdruck kombinieren. Das Ergebnis des `do`-Ausdrucks ist die letzte Anweisung im Block. `do`-Ausdrücke unterstützen die Verwendung von `break`, um den Kontrollfluss zu unterbrechen und mehrere Rückgabewerte vorzeitig zurückzugeben. | ||
| 36 | |||
| 37 | ```yuescript | ||
| 38 | status, value = do | ||
| 39 | n = 12 | ||
| 40 | if n > 10 | ||
| 41 | break "large", n | ||
| 42 | break "small", n | ||
| 43 | ``` | ||
| 44 | |||
| 45 | <YueDisplay> | ||
| 46 | |||
| 47 | ```yue | ||
| 48 | status, value = do | ||
| 49 | n = 12 | ||
| 50 | if n > 10 | ||
| 51 | break "large", n | ||
| 52 | break "small", n | ||
| 53 | ``` | ||
| 54 | |||
| 55 | </YueDisplay> | ||
| 56 | |||
| 57 | ```yuescript | ||
| 58 | counter = do | ||
| 59 | i = 0 | ||
| 60 | -> | ||
| 61 | i += 1 | ||
| 62 | i | ||
| 63 | |||
| 64 | print counter! | ||
| 65 | print counter! | ||
| 66 | ``` | ||
| 67 | |||
| 68 | <YueDisplay> | ||
| 69 | |||
| 70 | ```yue | ||
| 71 | counter = do | ||
| 72 | i = 0 | ||
| 73 | -> | ||
| 74 | i += 1 | ||
| 75 | i | ||
| 76 | |||
| 77 | print counter! | ||
| 78 | print counter! | ||
| 79 | ``` | ||
| 80 | |||
| 81 | </YueDisplay> | ||
| 82 | |||
| 83 | ```yuescript | ||
| 84 | tbl = { | ||
| 85 | key: do | ||
| 86 | print "Schlüssel wird zugewiesen!" | ||
| 87 | 1234 | ||
| 88 | } | ||
| 89 | ``` | ||
| 90 | |||
| 91 | <YueDisplay> | ||
| 92 | |||
| 93 | ```yue | ||
| 94 | tbl = { | ||
| 95 | key: do | ||
| 96 | print "Schlüssel wird zugewiesen!" | ||
| 97 | 1234 | ||
| 98 | } | ||
| 99 | ``` | ||
| 100 | |||
| 101 | </YueDisplay> | ||
| 102 | |||
| 103 | # Line-Decorators | ||
| 104 | |||
| 105 | Zur Vereinfachung können `for`-Schleifen und `if`-Anweisungen auf einzelne Anweisungen am Zeilenende angewendet werden: | ||
| 106 | |||
| 107 | ```yuescript | ||
| 108 | print "Hallo Welt" if name == "Rob" | ||
| 109 | ``` | ||
| 110 | |||
| 111 | <YueDisplay> | ||
| 112 | |||
| 113 | ```yue | ||
| 114 | print "Hallo Welt" if name == "Rob" | ||
| 115 | ``` | ||
| 116 | |||
| 117 | </YueDisplay> | ||
| 118 | |||
| 119 | Und mit einfachen Schleifen: | ||
| 120 | |||
| 121 | ```yuescript | ||
| 122 | print "Element: ", item for item in *items | ||
| 123 | ``` | ||
| 124 | |||
| 125 | <YueDisplay> | ||
| 126 | |||
| 127 | ```yue | ||
| 128 | print "Element: ", item for item in *items | ||
| 129 | ``` | ||
| 130 | |||
| 131 | </YueDisplay> | ||
| 132 | |||
| 133 | Und mit `while`-Schleifen: | ||
| 134 | |||
| 135 | ```yuescript | ||
| 136 | game\update! while game\isRunning! | ||
| 137 | |||
| 138 | reader\parse_line! until reader\eof! | ||
| 139 | ``` | ||
| 140 | |||
| 141 | <YueDisplay> | ||
| 142 | |||
| 143 | ```yue | ||
| 144 | game\update! while game\isRunning! | ||
| 145 | |||
| 146 | reader\parse_line! until reader\eof! | ||
| 147 | ``` | ||
| 148 | |||
| 149 | </YueDisplay> | ||
| 150 | |||
| 151 | # Makros | ||
| 152 | |||
| 153 | ## Häufige Verwendung | ||
| 154 | |||
| 155 | Makrofunktionen werden verwendet, um zur Compile-Zeit einen String auszuwerten und den generierten Code in die finale Kompilierung einzufügen. | ||
| 156 | |||
| 157 | ```yuescript | ||
| 158 | macro PI2 = -> math.pi * 2 | ||
| 159 | area = $PI2 * 5 | ||
| 160 | |||
| 161 | macro HELLO = -> "'Hallo Welt'" | ||
| 162 | print $HELLO | ||
| 163 | |||
| 164 | macro config = (debugging) -> | ||
| 165 | global debugMode = debugging == "true" | ||
| 166 | "" | ||
| 167 | |||
| 168 | macro asserts = (cond) -> | ||
| 169 | debugMode and "assert #{cond}" or "" | ||
| 170 | |||
| 171 | macro assert = (cond) -> | ||
| 172 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 173 | |||
| 174 | $config true | ||
| 175 | $asserts item ~= nil | ||
| 176 | |||
| 177 | $config false | ||
| 178 | value = $assert item | ||
| 179 | |||
| 180 | -- übergebene Ausdrücke werden als Strings behandelt | ||
| 181 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 182 | if $and f1!, f2!, f3! | ||
| 183 | print "OK" | ||
| 184 | ``` | ||
| 185 | |||
| 186 | <YueDisplay> | ||
| 187 | |||
| 188 | ```yue | ||
| 189 | macro PI2 = -> math.pi * 2 | ||
| 190 | area = $PI2 * 5 | ||
| 191 | |||
| 192 | macro HELLO = -> "'Hallo Welt'" | ||
| 193 | print $HELLO | ||
| 194 | |||
| 195 | macro config = (debugging) -> | ||
| 196 | global debugMode = debugging == "true" | ||
| 197 | "" | ||
| 198 | |||
| 199 | macro asserts = (cond) -> | ||
| 200 | debugMode and "assert #{cond}" or "" | ||
| 201 | |||
| 202 | macro assert = (cond) -> | ||
| 203 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 204 | |||
| 205 | $config true | ||
| 206 | $asserts item ~= nil | ||
| 207 | |||
| 208 | $config false | ||
| 209 | value = $assert item | ||
| 210 | |||
| 211 | -- übergebene Ausdrücke werden als Strings behandelt | ||
| 212 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 213 | if $and f1!, f2!, f3! | ||
| 214 | print "OK" | ||
| 215 | ``` | ||
| 216 | |||
| 217 | </YueDisplay> | ||
| 218 | |||
| 219 | ## Rohcode einfügen | ||
| 220 | |||
| 221 | Eine Makrofunktion kann entweder einen YueScript-String oder eine Konfigurationstabelle mit Lua-Code zurückgeben. | ||
| 222 | |||
| 223 | ```yuescript | ||
| 224 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 225 | $yueFunc funcA | ||
| 226 | funcA = -> "Zuweisung an die vom Yue-Makro definierte Variable schlägt fehl" | ||
| 227 | |||
| 228 | macro luaFunc = (var) -> { | ||
| 229 | code: "local function #{var}() end" | ||
| 230 | type: "lua" | ||
| 231 | } | ||
| 232 | $luaFunc funcB | ||
| 233 | funcB = -> "Zuweisung an die vom Lua-Makro definierte Variable schlägt fehl" | ||
| 234 | |||
| 235 | macro lua = (code) -> { | ||
| 236 | :code | ||
| 237 | type: "lua" | ||
| 238 | } | ||
| 239 | |||
| 240 | -- führende und abschließende Symbole des Raw-Strings werden automatisch getrimmt | ||
| 241 | $lua[==[ | ||
| 242 | -- Einfügen von rohem Lua-Code | ||
| 243 | if cond then | ||
| 244 | print("Ausgabe") | ||
| 245 | end | ||
| 246 | ]==] | ||
| 247 | ``` | ||
| 248 | |||
| 249 | <YueDisplay> | ||
| 250 | |||
| 251 | ```yue | ||
| 252 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 253 | $yueFunc funcA | ||
| 254 | funcA = -> "Zuweisung an die vom Yue-Makro definierte Variable schlägt fehl" | ||
| 255 | |||
| 256 | macro luaFunc = (var) -> { | ||
| 257 | code: "local function #{var}() end" | ||
| 258 | type: "lua" | ||
| 259 | } | ||
| 260 | $luaFunc funcB | ||
| 261 | funcB = -> "Zuweisung an die vom Lua-Makro definierte Variable schlägt fehl" | ||
| 262 | |||
| 263 | macro lua = (code) -> { | ||
| 264 | :code | ||
| 265 | type: "lua" | ||
| 266 | } | ||
| 267 | |||
| 268 | -- führende und abschließende Symbole des Raw-Strings werden automatisch getrimmt | ||
| 269 | $lua[==[ | ||
| 270 | -- Einfügen von rohem Lua-Code | ||
| 271 | if cond then | ||
| 272 | print("Ausgabe") | ||
| 273 | end | ||
| 274 | ]==] | ||
| 275 | ``` | ||
| 276 | |||
| 277 | </YueDisplay> | ||
| 278 | |||
| 279 | ## Makros exportieren | ||
| 280 | |||
| 281 | Makrofunktionen können aus einem Modul exportiert und in ein anderes Modul importiert werden. Exportierte Makros müssen in einer einzelnen Datei liegen, und im Export-Modul dürfen nur Makrodefinitionen, Makro-Imports und Makro-Expansionen stehen. | ||
| 282 | |||
| 283 | ```yuescript | ||
| 284 | -- Datei: utils.yue | ||
| 285 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 286 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 287 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 288 | #{action}" | ||
| 289 | |||
| 290 | -- Datei main.yue | ||
| 291 | import "utils" as { | ||
| 292 | $, -- Symbol zum Importieren aller Makros | ||
| 293 | $foreach: $each -- Makro $foreach in $each umbenennen | ||
| 294 | } | ||
| 295 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 296 | ``` | ||
| 297 | |||
| 298 | <YueDisplay> | ||
| 299 | |||
| 300 | ```yue | ||
| 301 | -- Datei: utils.yue | ||
| 302 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 303 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 304 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 305 | #{action}" | ||
| 306 | |||
| 307 | -- Datei main.yue | ||
| 308 | -- Import-Funktion im Browser nicht verfügbar, in echter Umgebung testen | ||
| 309 | --[[ | ||
| 310 | import "utils" as { | ||
| 311 | $, -- Symbol zum Importieren aller Makros | ||
| 312 | $foreach: $each -- Makro $foreach in $each umbenennen | ||
| 313 | } | ||
| 314 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 315 | ]] | ||
| 316 | ``` | ||
| 317 | |||
| 318 | </YueDisplay> | ||
| 319 | |||
| 320 | ## Eingebaute Makros | ||
| 321 | |||
| 322 | Es gibt einige eingebaute Makros, aber du kannst sie überschreiben, indem du Makros mit denselben Namen deklarierst. | ||
| 323 | |||
| 324 | ```yuescript | ||
| 325 | print $FILE -- String des aktuellen Modulnamens | ||
| 326 | print $LINE -- gibt 2 aus | ||
| 327 | ``` | ||
| 328 | |||
| 329 | <YueDisplay> | ||
| 330 | |||
| 331 | ```yue | ||
| 332 | print $FILE -- String des aktuellen Modulnamens | ||
| 333 | print $LINE -- gibt 2 aus | ||
| 334 | ``` | ||
| 335 | |||
| 336 | </YueDisplay> | ||
| 337 | |||
| 338 | ## Makros mit Makros erzeugen | ||
| 339 | |||
| 340 | In YueScript erlauben Makrofunktionen Codegenerierung zur Compile-Zeit. Durch das Verschachteln von Makrofunktionen kannst du komplexere Generierungsmuster erzeugen. Damit kannst du eine Makrofunktion definieren, die eine andere Makrofunktion erzeugt. | ||
| 341 | |||
| 342 | ```yuescript | ||
| 343 | macro Enum = (...) -> | ||
| 344 | items = {...} | ||
| 345 | itemSet = {item, true for item in *items} | ||
| 346 | (item) -> | ||
| 347 | error "erhalten: \"#{item}\", erwartet eines von #{table.concat items, ', '}" unless itemSet[item] | ||
| 348 | "\"#{item}\"" | ||
| 349 | |||
| 350 | macro BodyType = $Enum( | ||
| 351 | Static | ||
| 352 | Dynamic | ||
| 353 | Kinematic | ||
| 354 | ) | ||
| 355 | |||
| 356 | print "Gültiger Enum-Typ:", $BodyType Static | ||
| 357 | -- print "Kompilierungsfehler bei Enum-Typ:", $BodyType Unknown | ||
| 358 | ``` | ||
| 359 | |||
| 360 | <YueDisplay> | ||
| 361 | |||
| 362 | ```yue | ||
| 363 | macro Enum = (...) -> | ||
| 364 | items = {...} | ||
| 365 | itemSet = {item, true for item in *items} | ||
| 366 | (item) -> | ||
| 367 | error "erhalten: \"#{item}\", erwartet eines von #{table.concat items, ', '}" unless itemSet[item] | ||
| 368 | "\"#{item}\"" | ||
| 369 | |||
| 370 | macro BodyType = $Enum( | ||
| 371 | Static | ||
| 372 | Dynamic | ||
| 373 | Kinematic | ||
| 374 | ) | ||
| 375 | |||
| 376 | print "Gültiger Enum-Typ:", $BodyType Static | ||
| 377 | -- print "Kompilierungsfehler bei Enum-Typ:", $BodyType Unknown | ||
| 378 | ``` | ||
| 379 | |||
| 380 | </YueDisplay> | ||
| 381 | |||
| 382 | ## Argument-Validierung | ||
| 383 | |||
| 384 | Du kannst erwartete AST-Knotentypen in der Argumentliste deklarieren und zur Compile-Zeit prüfen, ob die übergebenen Makroargumente den Erwartungen entsprechen. | ||
| 385 | |||
| 386 | ```yuescript | ||
| 387 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 388 | print( | ||
| 389 | #{num} | ||
| 390 | #{str} | ||
| 391 | ) | ||
| 392 | |||
| 393 | $printNumAndStr 123, "hallo" | ||
| 394 | ``` | ||
| 395 | |||
| 396 | <YueDisplay> | ||
| 397 | |||
| 398 | ```yue | ||
| 399 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 400 | print( | ||
| 401 | #{num} | ||
| 402 | #{str} | ||
| 403 | ) | ||
| 404 | |||
| 405 | $printNumAndStr 123, "hallo" | ||
| 406 | ``` | ||
| 407 | |||
| 408 | </YueDisplay> | ||
| 409 | |||
| 410 | Wenn du flexiblere Argumentprüfungen brauchst, kannst du das eingebaute Makro `$is_ast` verwenden, um manuell an der passenden Stelle zu prüfen. | ||
| 411 | |||
| 412 | ```yuescript | ||
| 413 | macro printNumAndStr = (num, str) -> | ||
| 414 | error "als erstes Argument Num erwartet" unless $is_ast Num, num | ||
| 415 | error "als zweites Argument String erwartet" unless $is_ast String, str | ||
| 416 | "print(#{num}, #{str})" | ||
| 417 | |||
| 418 | $printNumAndStr 123, "hallo" | ||
| 419 | ``` | ||
| 420 | |||
| 421 | <YueDisplay> | ||
| 422 | |||
| 423 | ```yue | ||
| 424 | macro printNumAndStr = (num, str) -> | ||
| 425 | error "als erstes Argument Num erwartet" unless $is_ast Num, num | ||
| 426 | error "als zweites Argument String erwartet" unless $is_ast String, str | ||
| 427 | "print(#{num}, #{str})" | ||
| 428 | |||
| 429 | $printNumAndStr 123, "hallo" | ||
| 430 | ``` | ||
| 431 | |||
| 432 | </YueDisplay> | ||
| 433 | |||
| 434 | Weitere Details zu verfügbaren AST-Knoten findest du in den großgeschriebenen Definitionen in `yue_parser.cpp`. | ||
| 435 | |||
| 436 | # Try | ||
| 437 | |||
| 438 | Die Syntax für Fehlerbehandlung in Lua in einer gängigen Form. | ||
| 439 | |||
| 440 | ```yuescript | ||
| 441 | try | ||
| 442 | func 1, 2, 3 | ||
| 443 | catch err | ||
| 444 | print yue.traceback err | ||
| 445 | |||
| 446 | success, result = try | ||
| 447 | func 1, 2, 3 | ||
| 448 | catch err | ||
| 449 | yue.traceback err | ||
| 450 | |||
| 451 | try func 1, 2, 3 | ||
| 452 | catch err | ||
| 453 | print yue.traceback err | ||
| 454 | |||
| 455 | success, result = try func 1, 2, 3 | ||
| 456 | |||
| 457 | try | ||
| 458 | print "Versuche" | ||
| 459 | func 1, 2, 3 | ||
| 460 | |||
| 461 | -- Verwendung mit if-Zuweisungsmuster | ||
| 462 | if success, result := try func 1, 2, 3 | ||
| 463 | catch err | ||
| 464 | print yue.traceback err | ||
| 465 | print result | ||
| 466 | ``` | ||
| 467 | |||
| 468 | <YueDisplay> | ||
| 469 | |||
| 470 | ```yue | ||
| 471 | try | ||
| 472 | func 1, 2, 3 | ||
| 473 | catch err | ||
| 474 | print yue.traceback err | ||
| 475 | |||
| 476 | success, result = try | ||
| 477 | func 1, 2, 3 | ||
| 478 | catch err | ||
| 479 | yue.traceback err | ||
| 480 | |||
| 481 | try func 1, 2, 3 | ||
| 482 | catch err | ||
| 483 | print yue.traceback err | ||
| 484 | |||
| 485 | success, result = try func 1, 2, 3 | ||
| 486 | |||
| 487 | try | ||
| 488 | print "Versuche" | ||
| 489 | func 1, 2, 3 | ||
| 490 | |||
| 491 | -- Verwendung mit if-Zuweisungsmuster | ||
| 492 | if success, result := try func 1, 2, 3 | ||
| 493 | catch err | ||
| 494 | print yue.traceback err | ||
| 495 | print result | ||
| 496 | ``` | ||
| 497 | |||
| 498 | </YueDisplay> | ||
| 499 | |||
| 500 | ## Try? | ||
| 501 | |||
| 502 | `try?` ist eine vereinfachte Fehlerbehandlungs-Syntax, die den booleschen Status aus dem `try`-Statement weglässt. Bei Erfolg gibt sie das Ergebnis des `try`-Blocks zurück, ansonsten `nil` statt eines Fehlerobjekts. | ||
| 503 | |||
| 504 | ```yuescript | ||
| 505 | a, b, c = try? func! | ||
| 506 | |||
| 507 | -- mit Nil-Verschmelzungs-Operator | ||
| 508 | a = (try? func!) ?? "Standardwert" | ||
| 509 | |||
| 510 | -- als Funktionsargument | ||
| 511 | f try? func! | ||
| 512 | |||
| 513 | -- mit catch-Block | ||
| 514 | f try? | ||
| 515 | print 123 | ||
| 516 | func! | ||
| 517 | catch e | ||
| 518 | print e | ||
| 519 | e | ||
| 520 | ``` | ||
| 521 | |||
| 522 | <YueDisplay> | ||
| 523 | |||
| 524 | ```yue | ||
| 525 | a, b, c = try? func! | ||
| 526 | |||
| 527 | -- mit Nil-Verschmelzungs-Operator | ||
| 528 | a = (try? func!) ?? "Standardwert" | ||
| 529 | |||
| 530 | -- als Funktionsargument | ||
| 531 | f try? func! | ||
| 532 | |||
| 533 | -- mit catch-Block | ||
| 534 | f try? | ||
| 535 | print 123 | ||
| 536 | func! | ||
| 537 | catch e | ||
| 538 | print e | ||
| 539 | e | ||
| 540 | ``` | ||
| 541 | |||
| 542 | </YueDisplay> | ||
| 543 | |||
| 544 | # Tabellenliterale | ||
| 545 | |||
| 546 | Wie in Lua werden Tabellen mit geschweiften Klammern definiert. | ||
| 547 | |||
| 548 | ```yuescript | ||
| 549 | some_values = [1, 2, 3, 4] | ||
| 550 | ``` | ||
| 551 | |||
| 552 | <YueDisplay> | ||
| 553 | |||
| 554 | ```yue | ||
| 555 | some_values = [1, 2, 3, 4] | ||
| 556 | ``` | ||
| 557 | |||
| 558 | </YueDisplay> | ||
| 559 | |||
| 560 | Anders als in Lua weist man einem Schlüssel in einer Tabelle mit **:** (statt **=**) einen Wert zu. | ||
| 561 | |||
| 562 | ```yuescript | ||
| 563 | some_values = { | ||
| 564 | name: "Bill", | ||
| 565 | age: 200, | ||
| 566 | ["Lieblingsessen"]: "Reis" | ||
| 567 | } | ||
| 568 | ``` | ||
| 569 | |||
| 570 | <YueDisplay> | ||
| 571 | |||
| 572 | ```yue | ||
| 573 | some_values = { | ||
| 574 | name: "Bill", | ||
| 575 | age: 200, | ||
| 576 | ["Lieblingsessen"]: "Reis" | ||
| 577 | } | ||
| 578 | ``` | ||
| 579 | |||
| 580 | </YueDisplay> | ||
| 581 | |||
| 582 | Die geschweiften Klammern können weggelassen werden, wenn eine einzelne Tabelle aus Schlüssel-Wert-Paaren zugewiesen wird. | ||
| 583 | |||
| 584 | ```yuescript | ||
| 585 | profile = | ||
| 586 | height: "4 Fuß", | ||
| 587 | shoe_size: 13, | ||
| 588 | favorite_foods: ["Eis", "Donuts"] | ||
| 589 | ``` | ||
| 590 | |||
| 591 | <YueDisplay> | ||
| 592 | |||
| 593 | ```yue | ||
| 594 | profile = | ||
| 595 | height: "4 Fuß", | ||
| 596 | shoe_size: 13, | ||
| 597 | favorite_foods: ["Eis", "Donuts"] | ||
| 598 | ``` | ||
| 599 | |||
| 600 | </YueDisplay> | ||
| 601 | |||
| 602 | Zeilenumbrüche können Werte statt eines Kommas trennen (oder zusätzlich): | ||
| 603 | |||
| 604 | ```yuescript | ||
| 605 | values = { | ||
| 606 | 1, 2, 3, 4 | ||
| 607 | 5, 6, 7, 8 | ||
| 608 | name: "Superman" | ||
| 609 | occupation: "Verbrechensbekämpfung" | ||
| 610 | } | ||
| 611 | ``` | ||
| 612 | |||
| 613 | <YueDisplay> | ||
| 614 | |||
| 615 | ```yue | ||
| 616 | values = { | ||
| 617 | 1, 2, 3, 4 | ||
| 618 | 5, 6, 7, 8 | ||
| 619 | name: "Superman" | ||
| 620 | occupation: "Verbrechensbekämpfung" | ||
| 621 | } | ||
| 622 | ``` | ||
| 623 | |||
| 624 | </YueDisplay> | ||
| 625 | |||
| 626 | Beim Erstellen eines einzeiligen Tabellenliterals können die geschweiften Klammern ebenfalls weggelassen werden: | ||
| 627 | |||
| 628 | ```yuescript | ||
| 629 | my_function dance: "Tango", partner: "keiner" | ||
| 630 | |||
| 631 | y = type: "Hund", legs: 4, tails: 1 | ||
| 632 | ``` | ||
| 633 | |||
| 634 | <YueDisplay> | ||
| 635 | |||
| 636 | ```yue | ||
| 637 | my_function dance: "Tango", partner: "keiner" | ||
| 638 | |||
| 639 | y = type: "Hund", legs: 4, tails: 1 | ||
| 640 | ``` | ||
| 641 | |||
| 642 | </YueDisplay> | ||
| 643 | |||
| 644 | Die Schlüssel eines Tabellenliterals können Sprach-Schlüsselwörter sein, ohne sie zu escapen: | ||
| 645 | |||
| 646 | ```yuescript | ||
| 647 | tbl = { | ||
| 648 | do: "etwas" | ||
| 649 | end: "Hunger" | ||
| 650 | } | ||
| 651 | ``` | ||
| 652 | |||
| 653 | <YueDisplay> | ||
| 654 | |||
| 655 | ```yue | ||
| 656 | tbl = { | ||
| 657 | do: "etwas" | ||
| 658 | end: "Hunger" | ||
| 659 | } | ||
| 660 | ``` | ||
| 661 | |||
| 662 | </YueDisplay> | ||
| 663 | |||
| 664 | Wenn du eine Tabelle aus Variablen konstruierst und die Schlüssel den Variablennamen entsprechen sollen, kannst du den Präfix-Operator **:** verwenden: | ||
| 665 | |||
| 666 | ```yuescript | ||
| 667 | hair = "golden" | ||
| 668 | height = 200 | ||
| 669 | person = { :hair, :height, shoe_size: 40 } | ||
| 670 | |||
| 671 | print_table :hair, :height | ||
| 672 | ``` | ||
| 673 | |||
| 674 | <YueDisplay> | ||
| 675 | |||
| 676 | ```yue | ||
| 677 | hair = "golden" | ||
| 678 | height = 200 | ||
| 679 | person = { :hair, :height, shoe_size: 40 } | ||
| 680 | |||
| 681 | print_table :hair, :height | ||
| 682 | ``` | ||
| 683 | |||
| 684 | </YueDisplay> | ||
| 685 | |||
| 686 | Wenn der Schlüssel eines Feldes das Ergebnis eines Ausdrucks sein soll, kannst du ihn wie in Lua in **[ ]** setzen. Du kannst auch ein String-Literal direkt als Schlüssel verwenden und die eckigen Klammern weglassen. Das ist nützlich, wenn dein Schlüssel Sonderzeichen enthält. | ||
| 687 | |||
| 688 | ```yuescript | ||
| 689 | t = { | ||
| 690 | [1 + 2]: "hallo" | ||
| 691 | "Hallo Welt": true | ||
| 692 | } | ||
| 693 | ``` | ||
| 694 | |||
| 695 | <YueDisplay> | ||
| 696 | |||
| 697 | ```yue | ||
| 698 | t = { | ||
| 699 | [1 + 2]: "hallo" | ||
| 700 | "Hallo Welt": true | ||
| 701 | } | ||
| 702 | ``` | ||
| 703 | |||
| 704 | </YueDisplay> | ||
| 705 | |||
| 706 | Lua-Tabellen haben einen Array-Teil und einen Hash-Teil, aber manchmal möchte man beim Schreiben von Lua-Tabellen eine semantische Unterscheidung zwischen Array- und Hash-Nutzung machen. Dann kannst du eine Lua-Tabelle mit **[ ]** statt **{ }** schreiben, um eine Array-Tabelle darzustellen, und das Schreiben von Schlüssel-Wert-Paaren in einer Listentabelle ist nicht erlaubt. | ||
| 707 | |||
| 708 | ```yuescript | ||
| 709 | some_values = [1, 2, 3, 4] | ||
| 710 | list_with_one_element = [1, ] | ||
| 711 | ``` | ||
| 712 | |||
| 713 | <YueDisplay> | ||
| 714 | |||
| 715 | ```yue | ||
| 716 | some_values = [1, 2, 3, 4] | ||
| 717 | list_with_one_element = [1, ] | ||
| 718 | ``` | ||
| 719 | |||
| 720 | </YueDisplay> | ||
| 721 | |||
| 722 | # Comprehensions | ||
| 723 | |||
| 724 | Comprehensions bieten eine bequeme Syntax, um eine neue Tabelle zu erzeugen, indem man über ein bestehendes Objekt iteriert und einen Ausdruck auf seine Werte anwendet. Es gibt zwei Arten: Listen-Comprehensions und Tabellen-Comprehensions. Beide erzeugen Lua-Tabellen; Listen-Comprehensions sammeln Werte in einer array-ähnlichen Tabelle, und Tabellen-Comprehensions erlauben es, Schlüssel und Wert pro Iteration zu setzen. | ||
| 725 | |||
| 726 | ## Listen-Comprehensions | ||
| 727 | |||
| 728 | Das folgende Beispiel erstellt eine Kopie der `items`-Tabelle, aber mit verdoppelten Werten. | ||
| 729 | |||
| 730 | ```yuescript | ||
| 731 | items = [ 1, 2, 3, 4 ] | ||
| 732 | doubled = [item * 2 for i, item in ipairs items] | ||
| 733 | ``` | ||
| 734 | |||
| 735 | <YueDisplay> | ||
| 736 | |||
| 737 | ```yue | ||
| 738 | items = [ 1, 2, 3, 4 ] | ||
| 739 | doubled = [item * 2 for i, item in ipairs items] | ||
| 740 | ``` | ||
| 741 | |||
| 742 | </YueDisplay> | ||
| 743 | |||
| 744 | Die Elemente in der neuen Tabelle können mit einer `when`-Klausel eingeschränkt werden: | ||
| 745 | |||
| 746 | ```yuescript | ||
| 747 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 748 | ``` | ||
| 749 | |||
| 750 | <YueDisplay> | ||
| 751 | |||
| 752 | ```yue | ||
| 753 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 754 | ``` | ||
| 755 | |||
| 756 | </YueDisplay> | ||
| 757 | |||
| 758 | Da es üblich ist, über die Werte einer numerisch indizierten Tabelle zu iterieren, gibt es den **\***-Operator. Das Verdopplungsbeispiel kann so umgeschrieben werden: | ||
| 759 | |||
| 760 | ```yuescript | ||
| 761 | doubled = [item * 2 for item in *items] | ||
| 762 | ``` | ||
| 763 | |||
| 764 | <YueDisplay> | ||
| 765 | |||
| 766 | ```yue | ||
| 767 | doubled = [item * 2 for item in *items] | ||
| 768 | ``` | ||
| 769 | |||
| 770 | </YueDisplay> | ||
| 771 | |||
| 772 | In Listen-Comprehensions kannst du außerdem den Spread-Operator `...` verwenden, um verschachtelte Listen zu flatten und einen Flat-Map-Effekt zu erzielen: | ||
| 773 | |||
| 774 | ```yuescript | ||
| 775 | data = | ||
| 776 | a: [1, 2, 3] | ||
| 777 | b: [4, 5, 6] | ||
| 778 | |||
| 779 | flat = [...v for k,v in pairs data] | ||
| 780 | -- flat ist jetzt [1, 2, 3, 4, 5, 6] | ||
| 781 | ``` | ||
| 782 | |||
| 783 | <YueDisplay> | ||
| 784 | |||
| 785 | ```yue | ||
| 786 | data = | ||
| 787 | a: [1, 2, 3] | ||
| 788 | b: [4, 5, 6] | ||
| 789 | |||
| 790 | flat = [...v for k,v in pairs data] | ||
| 791 | -- flat ist jetzt [1, 2, 3, 4, 5, 6] | ||
| 792 | ``` | ||
| 793 | |||
| 794 | </YueDisplay> | ||
| 795 | |||
| 796 | Die `for`- und `when`-Klauseln können beliebig oft verkettet werden. Die einzige Anforderung ist, dass eine Comprehension mindestens eine `for`-Klausel enthält. | ||
| 797 | |||
| 798 | Mehrere `for`-Klauseln entsprechen verschachtelten Schleifen: | ||
| 799 | |||
| 800 | ```yuescript | ||
| 801 | x_coords = [4, 5, 6, 7] | ||
| 802 | y_coords = [9, 2, 3] | ||
| 803 | |||
| 804 | points = [ [x, y] for x in *x_coords \ | ||
| 805 | for y in *y_coords] | ||
| 806 | ``` | ||
| 807 | |||
| 808 | <YueDisplay> | ||
| 809 | |||
| 810 | ```yue | ||
| 811 | x_coords = [4, 5, 6, 7] | ||
| 812 | y_coords = [9, 2, 3] | ||
| 813 | |||
| 814 | points = [ [x, y] for x in *x_coords \ | ||
| 815 | for y in *y_coords] | ||
| 816 | ``` | ||
| 817 | |||
| 818 | </YueDisplay> | ||
| 819 | |||
| 820 | Numerische `for`-Schleifen können ebenfalls in Comprehensions verwendet werden: | ||
| 821 | |||
| 822 | ```yuescript | ||
| 823 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 824 | ``` | ||
| 825 | |||
| 826 | <YueDisplay> | ||
| 827 | |||
| 828 | ```yue | ||
| 829 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 830 | ``` | ||
| 831 | |||
| 832 | </YueDisplay> | ||
| 833 | |||
| 834 | ## Tabellen-Comprehensions | ||
| 835 | |||
| 836 | Die Syntax für Tabellen-Comprehensions ist sehr ähnlich, unterscheidet sich jedoch dadurch, dass **{** und **}** verwendet werden und pro Iteration zwei Werte erzeugt werden. | ||
| 837 | |||
| 838 | Dieses Beispiel erstellt eine Kopie von `thing`: | ||
| 839 | |||
| 840 | ```yuescript | ||
| 841 | thing = { | ||
| 842 | color: "rot" | ||
| 843 | name: "schnell" | ||
| 844 | width: 123 | ||
| 845 | } | ||
| 846 | |||
| 847 | thing_copy = {k, v for k, v in pairs thing} | ||
| 848 | ``` | ||
| 849 | |||
| 850 | <YueDisplay> | ||
| 851 | |||
| 852 | ```yue | ||
| 853 | thing = { | ||
| 854 | color: "rot" | ||
| 855 | name: "schnell" | ||
| 856 | width: 123 | ||
| 857 | } | ||
| 858 | |||
| 859 | thing_copy = {k, v for k, v in pairs thing} | ||
| 860 | ``` | ||
| 861 | |||
| 862 | </YueDisplay> | ||
| 863 | |||
| 864 | ```yuescript | ||
| 865 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 866 | ``` | ||
| 867 | |||
| 868 | <YueDisplay> | ||
| 869 | |||
| 870 | ```yue | ||
| 871 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 872 | ``` | ||
| 873 | |||
| 874 | </YueDisplay> | ||
| 875 | |||
| 876 | Der **\***-Operator wird ebenfalls unterstützt. Hier erstellen wir eine Nachschlagetabelle für Quadratwurzeln einiger Zahlen. | ||
| 877 | |||
| 878 | ```yuescript | ||
| 879 | numbers = [1, 2, 3, 4] | ||
| 880 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 881 | ``` | ||
| 882 | |||
| 883 | <YueDisplay> | ||
| 884 | |||
| 885 | ```yue | ||
| 886 | numbers = [1, 2, 3, 4] | ||
| 887 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 888 | ``` | ||
| 889 | |||
| 890 | </YueDisplay> | ||
| 891 | |||
| 892 | Das Schlüssel-Wert-Tupel in einer Tabellen-Comprehension kann auch aus einem einzelnen Ausdruck stammen; der Ausdruck muss dann zwei Werte zurückgeben. Der erste wird als Schlüssel und der zweite als Wert verwendet: | ||
| 893 | |||
| 894 | In diesem Beispiel konvertieren wir ein Array von Paaren in eine Tabelle, wobei das erste Element des Paars der Schlüssel und das zweite der Wert ist. | ||
| 895 | |||
| 896 | ```yuescript | ||
| 897 | tuples = [ ["hallo", "Welt"], ["foo", "bar"]] | ||
| 898 | tbl = {unpack tuple for tuple in *tuples} | ||
| 899 | ``` | ||
| 900 | |||
| 901 | <YueDisplay> | ||
| 902 | |||
| 903 | ```yue | ||
| 904 | tuples = [ ["hallo", "Welt"], ["foo", "bar"]] | ||
| 905 | tbl = {unpack tuple for tuple in *tuples} | ||
| 906 | ``` | ||
| 907 | |||
| 908 | </YueDisplay> | ||
| 909 | |||
| 910 | ## Slicing | ||
| 911 | |||
| 912 | Eine spezielle Syntax erlaubt es, die iterierten Elemente bei Verwendung des **\***-Operators einzuschränken. Das ist äquivalent zum Setzen von Iterationsgrenzen und Schrittweite in einer `for`-Schleife. | ||
| 913 | |||
| 914 | Hier setzen wir die minimalen und maximalen Grenzen und nehmen alle Elemente mit Indizes zwischen 1 und 5 (inklusive): | ||
| 915 | |||
| 916 | ```yuescript | ||
| 917 | slice = [item for item in *items[1, 5]] | ||
| 918 | ``` | ||
| 919 | |||
| 920 | <YueDisplay> | ||
| 921 | |||
| 922 | ```yue | ||
| 923 | slice = [item for item in *items[1, 5]] | ||
| 924 | ``` | ||
| 925 | |||
| 926 | </YueDisplay> | ||
| 927 | |||
| 928 | Jedes der Slice-Argumente kann weggelassen werden, um einen sinnvollen Standard zu verwenden. Wenn der maximale Index weggelassen wird, entspricht er der Länge der Tabelle. Dieses Beispiel nimmt alles außer dem ersten Element: | ||
| 929 | |||
| 930 | ```yuescript | ||
| 931 | slice = [item for item in *items[2,]] | ||
| 932 | ``` | ||
| 933 | |||
| 934 | <YueDisplay> | ||
| 935 | |||
| 936 | ```yue | ||
| 937 | slice = [item for item in *items[2,]] | ||
| 938 | ``` | ||
| 939 | |||
| 940 | </YueDisplay> | ||
| 941 | |||
| 942 | Wenn die Mindestgrenze weggelassen wird, ist sie standardmäßig 1. Hier geben wir nur die Schrittweite an und lassen die anderen Grenzen leer. Das nimmt alle ungerad indizierten Elemente (1, 3, 5, …): | ||
| 943 | |||
| 944 | ```yuescript | ||
| 945 | slice = [item for item in *items[,,2]] | ||
| 946 | ``` | ||
| 947 | |||
| 948 | <YueDisplay> | ||
| 949 | |||
| 950 | ```yue | ||
| 951 | slice = [item for item in *items[,,2]] | ||
| 952 | ``` | ||
| 953 | |||
| 954 | </YueDisplay> | ||
| 955 | |||
| 956 | Sowohl die Mindest- als auch die Maximalgrenze können negativ sein; dann werden die Grenzen vom Ende der Tabelle gezählt. | ||
| 957 | |||
| 958 | ```yuescript | ||
| 959 | -- die letzten 4 Elemente nehmen | ||
| 960 | slice = [item for item in *items[-4,-1]] | ||
| 961 | ``` | ||
| 962 | |||
| 963 | <YueDisplay> | ||
| 964 | |||
| 965 | ```yue | ||
| 966 | -- die letzten 4 Elemente nehmen | ||
| 967 | slice = [item for item in *items[-4,-1]] | ||
| 968 | ``` | ||
| 969 | |||
| 970 | </YueDisplay> | ||
| 971 | |||
| 972 | Die Schrittweite kann ebenfalls negativ sein, wodurch die Elemente in umgekehrter Reihenfolge genommen werden. | ||
| 973 | |||
| 974 | ```yuescript | ||
| 975 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 976 | ``` | ||
| 977 | |||
| 978 | <YueDisplay> | ||
| 979 | |||
| 980 | ```yue | ||
| 981 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 982 | ``` | ||
| 983 | |||
| 984 | </YueDisplay> | ||
| 985 | |||
| 986 | ### Slicing-Ausdruck | ||
| 987 | |||
| 988 | Slicing kann auch als Ausdruck verwendet werden. Das ist nützlich, um eine Teilliste einer Tabelle zu erhalten. | ||
| 989 | |||
| 990 | ```yuescript | ||
| 991 | -- das 2. und 4. Element als neue Liste nehmen | ||
| 992 | sub_list = items[2, 4] | ||
| 993 | |||
| 994 | -- die letzten 4 Elemente nehmen | ||
| 995 | last_four_items = items[-4, -1] | ||
| 996 | ``` | ||
| 997 | |||
| 998 | <YueDisplay> | ||
| 999 | |||
| 1000 | ```yue | ||
| 1001 | -- das 2. und 4. Element als neue Liste nehmen | ||
| 1002 | sub_list = items[2, 4] | ||
| 1003 | |||
| 1004 | -- die letzten 4 Elemente nehmen | ||
| 1005 | last_four_items = items[-4, -1] | ||
| 1006 | ``` | ||
| 1007 | |||
| 1008 | </YueDisplay> | ||
| 1009 | |||
| 1010 | # Objektorientierte Programmierung | ||
| 1011 | |||
| 1012 | In diesen Beispielen kann der generierte Lua-Code überwältigend wirken. Am besten konzentrierst du dich zunächst auf die Bedeutung des YueScript-Codes und schaust dir den Lua-Code nur an, wenn du die Implementierungsdetails wissen möchtest. | ||
| 1013 | |||
| 1014 | Eine einfache Klasse: | ||
| 1015 | |||
| 1016 | ```yuescript | ||
| 1017 | class Inventory | ||
| 1018 | new: => | ||
| 1019 | @items = {} | ||
| 1020 | |||
| 1021 | add_item: (name) => | ||
| 1022 | if @items[name] | ||
| 1023 | @items[name] += 1 | ||
| 1024 | else | ||
| 1025 | @items[name] = 1 | ||
| 1026 | ``` | ||
| 1027 | |||
| 1028 | <YueDisplay> | ||
| 1029 | |||
| 1030 | ```yue | ||
| 1031 | class Inventory | ||
| 1032 | new: => | ||
| 1033 | @items = {} | ||
| 1034 | |||
| 1035 | add_item: (name) => | ||
| 1036 | if @items[name] | ||
| 1037 | @items[name] += 1 | ||
| 1038 | else | ||
| 1039 | @items[name] = 1 | ||
| 1040 | ``` | ||
| 1041 | |||
| 1042 | </YueDisplay> | ||
| 1043 | |||
| 1044 | Eine Klasse wird mit einem `class`-Statement deklariert, gefolgt von einer tabellenähnlichen Deklaration mit allen Methoden und Eigenschaften. | ||
| 1045 | |||
| 1046 | Die Eigenschaft `new` ist besonders, da sie zum Konstruktor wird. | ||
| 1047 | |||
| 1048 | Beachte, dass alle Methoden in der Klasse die Fat-Arrow-Syntax verwenden. Beim Aufruf von Methoden auf einer Instanz wird die Instanz selbst als erstes Argument übergeben. Der Fat-Arrow übernimmt die Erstellung des `self`-Arguments. | ||
| 1049 | |||
| 1050 | Das `@`-Präfix ist Kurzform für `self.`. `@items` wird zu `self.items`. | ||
| 1051 | |||
| 1052 | Eine Instanz der Klasse wird erstellt, indem man den Klassennamen wie eine Funktion aufruft. | ||
| 1053 | |||
| 1054 | ```yuescript | ||
| 1055 | inv = Inventory! | ||
| 1056 | inv\add_item "T-Shirt" | ||
| 1057 | inv\add_item "Hose" | ||
| 1058 | ``` | ||
| 1059 | |||
| 1060 | <YueDisplay> | ||
| 1061 | |||
| 1062 | ```yue | ||
| 1063 | inv = Inventory! | ||
| 1064 | inv\add_item "T-Shirt" | ||
| 1065 | inv\add_item "Hose" | ||
| 1066 | ``` | ||
| 1067 | |||
| 1068 | </YueDisplay> | ||
| 1069 | |||
| 1070 | Da die Instanz bei Methodenaufrufen an die Methoden übergeben werden muss, wird der `\`-Operator verwendet. | ||
| 1071 | |||
| 1072 | Alle Eigenschaften einer Klasse werden von allen Instanzen gemeinsam genutzt. Für Funktionen ist das ok, aber bei anderen Objekten kann das zu unerwünschten Ergebnissen führen. | ||
| 1073 | |||
| 1074 | Im folgenden Beispiel wird die Eigenschaft `clothes` von allen Instanzen geteilt, sodass Änderungen in einer Instanz in einer anderen sichtbar werden: | ||
| 1075 | |||
| 1076 | ```yuescript | ||
| 1077 | class Person | ||
| 1078 | clothes: [] | ||
| 1079 | give_item: (name) => | ||
| 1080 | table.insert @clothes, name | ||
| 1081 | |||
| 1082 | a = Person! | ||
| 1083 | b = Person! | ||
| 1084 | |||
| 1085 | a\give_item "Hose" | ||
| 1086 | b\give_item "Hemd" | ||
| 1087 | |||
| 1088 | -- gibt sowohl Hose als auch Hemd aus | ||
| 1089 | print item for item in *a.clothes | ||
| 1090 | ``` | ||
| 1091 | |||
| 1092 | <YueDisplay> | ||
| 1093 | |||
| 1094 | ```yue | ||
| 1095 | class Person | ||
| 1096 | clothes: [] | ||
| 1097 | give_item: (name) => | ||
| 1098 | table.insert @clothes, name | ||
| 1099 | |||
| 1100 | a = Person! | ||
| 1101 | b = Person! | ||
| 1102 | |||
| 1103 | a\give_item "Hose" | ||
| 1104 | b\give_item "Hemd" | ||
| 1105 | |||
| 1106 | -- gibt sowohl Hose als auch Hemd aus | ||
| 1107 | print item for item in *a.clothes | ||
| 1108 | ``` | ||
| 1109 | |||
| 1110 | </YueDisplay> | ||
| 1111 | |||
| 1112 | Der richtige Weg, das zu vermeiden, ist, den veränderlichen Zustand im Konstruktor zu erstellen: | ||
| 1113 | |||
| 1114 | ```yuescript | ||
| 1115 | class Person | ||
| 1116 | new: => | ||
| 1117 | @clothes = [] | ||
| 1118 | ``` | ||
| 1119 | |||
| 1120 | <YueDisplay> | ||
| 1121 | |||
| 1122 | ```yue | ||
| 1123 | class Person | ||
| 1124 | new: => | ||
| 1125 | @clothes = [] | ||
| 1126 | ``` | ||
| 1127 | |||
| 1128 | </YueDisplay> | ||
| 1129 | |||
| 1130 | ## Vererbung | ||
| 1131 | |||
| 1132 | Das Schlüsselwort `extends` kann in einer Klassendeklaration verwendet werden, um Eigenschaften und Methoden von einer anderen Klasse zu erben. | ||
| 1133 | |||
| 1134 | ```yuescript | ||
| 1135 | class BackPack extends Inventory | ||
| 1136 | size: 10 | ||
| 1137 | add_item: (name) => | ||
| 1138 | if #@items > size then error "Rucksack ist voll" | ||
| 1139 | super name | ||
| 1140 | ``` | ||
| 1141 | |||
| 1142 | <YueDisplay> | ||
| 1143 | |||
| 1144 | ```yue | ||
| 1145 | class BackPack extends Inventory | ||
| 1146 | size: 10 | ||
| 1147 | add_item: (name) => | ||
| 1148 | if #@items > size then error "Rucksack ist voll" | ||
| 1149 | super name | ||
| 1150 | ``` | ||
| 1151 | |||
| 1152 | </YueDisplay> | ||
| 1153 | |||
| 1154 | Hier erweitern wir unsere `Inventory`-Klasse und begrenzen die Anzahl der Elemente. | ||
| 1155 | |||
| 1156 | In diesem Beispiel definieren wir keinen Konstruktor in der Subklasse, daher wird der Konstruktor der Elternklasse beim Erstellen einer neuen Instanz aufgerufen. Definieren wir einen Konstruktor, können wir mit `super` den Elternkonstruktor aufrufen. | ||
| 1157 | |||
| 1158 | Wenn eine Klasse von einer anderen erbt, sendet sie eine Nachricht an die Elternklasse, indem die Methode `__inherited` der Elternklasse aufgerufen wird, falls vorhanden. Die Funktion erhält zwei Argumente: die Klasse, die vererbt wird, und die Kindklasse. | ||
| 1159 | |||
| 1160 | ```yuescript | ||
| 1161 | class Shelf | ||
| 1162 | @__inherited: (child) => | ||
| 1163 | print @__name, "wurde vererbt von", child.__name | ||
| 1164 | |||
| 1165 | -- gibt aus: Shelf wurde von Cupboard geerbt | ||
| 1166 | class Cupboard extends Shelf | ||
| 1167 | ``` | ||
| 1168 | |||
| 1169 | <YueDisplay> | ||
| 1170 | |||
| 1171 | ```yue | ||
| 1172 | class Shelf | ||
| 1173 | @__inherited: (child) => | ||
| 1174 | print @__name, "wurde vererbt von", child.__name | ||
| 1175 | |||
| 1176 | -- gibt aus: Shelf wurde von Cupboard geerbt | ||
| 1177 | class Cupboard extends Shelf | ||
| 1178 | ``` | ||
| 1179 | |||
| 1180 | </YueDisplay> | ||
| 1181 | |||
| 1182 | ## Super | ||
| 1183 | |||
| 1184 | **super** ist ein spezielles Schlüsselwort, das auf zwei Arten verwendet werden kann: als Objekt oder als Funktionsaufruf. Es hat besondere Funktionalität nur innerhalb einer Klasse. | ||
| 1185 | |||
| 1186 | Wenn es als Funktion aufgerufen wird, ruft es die gleichnamige Funktion in der Elternklasse auf. `self` wird automatisch als erstes Argument übergeben (wie im Vererbungsbeispiel oben). | ||
| 1187 | |||
| 1188 | Wenn `super` als normaler Wert verwendet wird, ist es eine Referenz auf das Objekt der Elternklasse. | ||
| 1189 | |||
| 1190 | Du kannst es wie jedes andere Objekt verwenden, um Werte der Elternklasse zu lesen, die von der Kindklasse überschattet wurden. | ||
| 1191 | |||
| 1192 | Wenn der `\`-Aufrufoperator mit `super` verwendet wird, wird `self` als erstes Argument eingefügt statt des Wertes von `super`. Wenn man `.` zum Abrufen einer Funktion verwendet, wird die rohe Funktion zurückgegeben. | ||
| 1193 | |||
| 1194 | Ein paar Beispiele für `super` in unterschiedlichen Formen: | ||
| 1195 | |||
| 1196 | ```yuescript | ||
| 1197 | class MyClass extends ParentClass | ||
| 1198 | a_method: => | ||
| 1199 | -- Folgendes hat dieselbe Wirkung: | ||
| 1200 | super "hallo", "Welt" | ||
| 1201 | super\a_method "hallo", "Welt" | ||
| 1202 | super.a_method self, "hallo", "Welt" | ||
| 1203 | |||
| 1204 | -- super als Wert entspricht der Elternklasse: | ||
| 1205 | assert super == ParentClass | ||
| 1206 | ``` | ||
| 1207 | |||
| 1208 | <YueDisplay> | ||
| 1209 | |||
| 1210 | ```yue | ||
| 1211 | class MyClass extends ParentClass | ||
| 1212 | a_method: => | ||
| 1213 | -- Folgendes hat dieselbe Wirkung: | ||
| 1214 | super "hallo", "Welt" | ||
| 1215 | super\a_method "hallo", "Welt" | ||
| 1216 | super.a_method self, "hallo", "Welt" | ||
| 1217 | |||
| 1218 | -- super als Wert entspricht der Elternklasse: | ||
| 1219 | assert super == ParentClass | ||
| 1220 | ``` | ||
| 1221 | |||
| 1222 | </YueDisplay> | ||
| 1223 | |||
| 1224 | **super** kann auch links einer Funktions-Stub verwendet werden. Der einzige große Unterschied ist, dass die resultierende Funktion statt an `super` an `self` gebunden wird. | ||
| 1225 | |||
| 1226 | ## Typen | ||
| 1227 | |||
| 1228 | Jede Instanz einer Klasse trägt ihren Typ in sich. Dieser wird in der speziellen Eigenschaft `__class` gespeichert. Diese Eigenschaft enthält das Klassenobjekt. Das Klassenobjekt wird aufgerufen, um eine neue Instanz zu erstellen. Wir können das Klassenobjekt auch indizieren, um Klassenmethoden und Eigenschaften abzurufen. | ||
| 1229 | |||
| 1230 | ```yuescript | ||
| 1231 | b = BackPack! | ||
| 1232 | assert b.__class == BackPack | ||
| 1233 | |||
| 1234 | print BackPack.size -- gibt 10 aus | ||
| 1235 | ``` | ||
| 1236 | |||
| 1237 | <YueDisplay> | ||
| 1238 | |||
| 1239 | ```yue | ||
| 1240 | b = BackPack! | ||
| 1241 | assert b.__class == BackPack | ||
| 1242 | |||
| 1243 | print BackPack.size -- gibt 10 aus | ||
| 1244 | ``` | ||
| 1245 | |||
| 1246 | </YueDisplay> | ||
| 1247 | |||
| 1248 | ## Klassenobjekte | ||
| 1249 | |||
| 1250 | Das Klassenobjekt entsteht, wenn wir ein `class`-Statement verwenden. Es wird in einer Variablen mit dem Klassennamen gespeichert. | ||
| 1251 | |||
| 1252 | Das Klassenobjekt kann wie eine Funktion aufgerufen werden, um neue Instanzen zu erstellen. So haben wir die Instanzen in den Beispielen oben erstellt. | ||
| 1253 | |||
| 1254 | Eine Klasse besteht aus zwei Tabellen: der Klassentabelle selbst und der Basistabelle. Die Basis wird als Metatable für alle Instanzen verwendet. Alle in der Klassendeklaration aufgeführten Eigenschaften werden in der Basis platziert. | ||
| 1255 | |||
| 1256 | Das Metatable des Klassenobjekts liest Eigenschaften aus der Basis, wenn sie im Klassenobjekt nicht existieren. Das bedeutet, dass wir Funktionen und Eigenschaften direkt von der Klasse aus aufrufen können. | ||
| 1257 | |||
| 1258 | Wichtig: Zuweisungen an das Klassenobjekt schreiben nicht in die Basis. Das ist keine gültige Methode, um neue Methoden zu Instanzen hinzuzufügen. Stattdessen muss die Basis explizit geändert werden. Siehe das Feld `__base` unten. | ||
| 1259 | |||
| 1260 | Das Klassenobjekt hat einige spezielle Eigenschaften: | ||
| 1261 | |||
| 1262 | Der Name der Klasse, wie sie deklariert wurde, wird im Feld `__name` gespeichert. | ||
| 1263 | |||
| 1264 | ```yuescript | ||
| 1265 | print BackPack.__name -- gibt Backpack aus | ||
| 1266 | ``` | ||
| 1267 | |||
| 1268 | <YueDisplay> | ||
| 1269 | |||
| 1270 | ```yue | ||
| 1271 | print BackPack.__name -- gibt Backpack aus | ||
| 1272 | ``` | ||
| 1273 | |||
| 1274 | </YueDisplay> | ||
| 1275 | |||
| 1276 | Die Basistabelle ist in `__base` gespeichert. Du kannst diese Tabelle ändern, um Instanzen Funktionalität hinzuzufügen, die bereits existieren oder noch erstellt werden. | ||
| 1277 | |||
| 1278 | Wenn die Klasse von etwas erbt, ist das Elternklassenobjekt in `__parent` gespeichert. | ||
| 1279 | |||
| 1280 | ## Klassenvariablen | ||
| 1281 | |||
| 1282 | Du kannst Variablen direkt im Klassenobjekt statt in der Basis erstellen, indem du in der Klassendeklaration `@` vor den Eigenschaftsnamen setzt. | ||
| 1283 | |||
| 1284 | ```yuescript | ||
| 1285 | class Things | ||
| 1286 | @some_func: => print "Hallo von", @__name | ||
| 1287 | |||
| 1288 | Things\some_func! | ||
| 1289 | |||
| 1290 | -- Klassenvariablen in Instanzen nicht sichtbar | ||
| 1291 | assert Things().some_func == nil | ||
| 1292 | ``` | ||
| 1293 | |||
| 1294 | <YueDisplay> | ||
| 1295 | |||
| 1296 | ```yue | ||
| 1297 | class Things | ||
| 1298 | @some_func: => print "Hallo von", @__name | ||
| 1299 | |||
| 1300 | Things\some_func! | ||
| 1301 | |||
| 1302 | -- Klassenvariablen in Instanzen nicht sichtbar | ||
| 1303 | assert Things().some_func == nil | ||
| 1304 | ``` | ||
| 1305 | |||
| 1306 | </YueDisplay> | ||
| 1307 | |||
| 1308 | In Ausdrücken können wir `@@` verwenden, um auf einen Wert zuzugreifen, der in `self.__class` gespeichert ist. `@@hello` ist also eine Kurzform für `self.__class.hello`. | ||
| 1309 | |||
| 1310 | ```yuescript | ||
| 1311 | class Counter | ||
| 1312 | @count: 0 | ||
| 1313 | |||
| 1314 | new: => | ||
| 1315 | @@count += 1 | ||
| 1316 | |||
| 1317 | Counter! | ||
| 1318 | Counter! | ||
| 1319 | |||
| 1320 | print Counter.count -- gibt 2 aus | ||
| 1321 | ``` | ||
| 1322 | |||
| 1323 | <YueDisplay> | ||
| 1324 | |||
| 1325 | ```yue | ||
| 1326 | class Counter | ||
| 1327 | @count: 0 | ||
| 1328 | |||
| 1329 | new: => | ||
| 1330 | @@count += 1 | ||
| 1331 | |||
| 1332 | Counter! | ||
| 1333 | Counter! | ||
| 1334 | |||
| 1335 | print Counter.count -- gibt 2 aus | ||
| 1336 | ``` | ||
| 1337 | |||
| 1338 | </YueDisplay> | ||
| 1339 | |||
| 1340 | Die Aufrufsemantik von `@@` ist ähnlich wie bei `@`. Wenn du einen `@@`-Namen aufrufst, wird die Klasse als erstes Argument übergeben (Lua-`:`-Syntax). | ||
| 1341 | |||
| 1342 | ```yuescript | ||
| 1343 | @@hello 1,2,3,4 | ||
| 1344 | ``` | ||
| 1345 | |||
| 1346 | <YueDisplay> | ||
| 1347 | |||
| 1348 | ```yue | ||
| 1349 | @@hello 1,2,3,4 | ||
| 1350 | ``` | ||
| 1351 | |||
| 1352 | </YueDisplay> | ||
| 1353 | |||
| 1354 | ## Klassendeklarations-Statements | ||
| 1355 | |||
| 1356 | Im Rumpf einer Klassendeklaration können wir normale Ausdrücke zusätzlich zu Schlüssel/Wert-Paaren haben. In diesem Kontext ist `self` gleich dem Klassenobjekt. | ||
| 1357 | |||
| 1358 | Hier ist eine alternative Möglichkeit, eine Klassenvariable zu erstellen: | ||
| 1359 | |||
| 1360 | ```yuescript | ||
| 1361 | class Things | ||
| 1362 | @class_var = "Hallo Welt" | ||
| 1363 | ``` | ||
| 1364 | |||
| 1365 | <YueDisplay> | ||
| 1366 | |||
| 1367 | ```yue | ||
| 1368 | class Things | ||
| 1369 | @class_var = "Hallo Welt" | ||
| 1370 | ``` | ||
| 1371 | |||
| 1372 | </YueDisplay> | ||
| 1373 | |||
| 1374 | Diese Ausdrücke werden ausgeführt, nachdem alle Eigenschaften zur Basis hinzugefügt wurden. | ||
| 1375 | |||
| 1376 | Alle Variablen, die im Klassenkörper deklariert werden, sind lokal zu den Klasseneigenschaften. Das ist praktisch, um private Werte oder Hilfsfunktionen zu platzieren, auf die nur die Klassenmethoden zugreifen können: | ||
| 1377 | |||
| 1378 | ```yuescript | ||
| 1379 | class MoreThings | ||
| 1380 | secret = 123 | ||
| 1381 | log = (msg) -> print "LOG:", msg | ||
| 1382 | |||
| 1383 | some_method: => | ||
| 1384 | log "Hallo Welt: " .. secret | ||
| 1385 | ``` | ||
| 1386 | |||
| 1387 | <YueDisplay> | ||
| 1388 | |||
| 1389 | ```yue | ||
| 1390 | class MoreThings | ||
| 1391 | secret = 123 | ||
| 1392 | log = (msg) -> print "LOG:", msg | ||
| 1393 | |||
| 1394 | some_method: => | ||
| 1395 | log "Hallo Welt: " .. secret | ||
| 1396 | ``` | ||
| 1397 | |||
| 1398 | </YueDisplay> | ||
| 1399 | |||
| 1400 | ## @- und @@-Werte | ||
| 1401 | |||
| 1402 | Wenn `@` und `@@` vor einem Namen stehen, repräsentieren sie den Namen in `self` bzw. `self.__class`. | ||
| 1403 | |||
| 1404 | Wenn sie alleine verwendet werden, sind sie Aliase für `self` und `self.__class`. | ||
| 1405 | |||
| 1406 | ```yuescript | ||
| 1407 | assert @ == self | ||
| 1408 | assert @@ == self.__class | ||
| 1409 | ``` | ||
| 1410 | |||
| 1411 | <YueDisplay> | ||
| 1412 | |||
| 1413 | ```yue | ||
| 1414 | assert @ == self | ||
| 1415 | assert @@ == self.__class | ||
| 1416 | ``` | ||
| 1417 | |||
| 1418 | </YueDisplay> | ||
| 1419 | |||
| 1420 | Zum Beispiel kannst du mit `@@` in einer Instanzmethode schnell eine neue Instanz derselben Klasse erzeugen: | ||
| 1421 | |||
| 1422 | ```yuescript | ||
| 1423 | some_instance_method = (...) => @@ ... | ||
| 1424 | ``` | ||
| 1425 | |||
| 1426 | <YueDisplay> | ||
| 1427 | |||
| 1428 | ```yue | ||
| 1429 | some_instance_method = (...) => @@ ... | ||
| 1430 | ``` | ||
| 1431 | |||
| 1432 | </YueDisplay> | ||
| 1433 | |||
| 1434 | ## Konstruktor-Property-Promotion | ||
| 1435 | |||
| 1436 | Um Boilerplate beim Definieren einfacher Value-Objekte zu reduzieren, kannst du eine Klasse so schreiben: | ||
| 1437 | |||
| 1438 | ```yuescript | ||
| 1439 | class Something | ||
| 1440 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1441 | |||
| 1442 | -- Kurzform für | ||
| 1443 | |||
| 1444 | class Something | ||
| 1445 | new: (foo, bar, biz, baz) => | ||
| 1446 | @foo = foo | ||
| 1447 | @bar = bar | ||
| 1448 | @@biz = biz | ||
| 1449 | @@baz = baz | ||
| 1450 | ``` | ||
| 1451 | |||
| 1452 | <YueDisplay> | ||
| 1453 | |||
| 1454 | ```yue | ||
| 1455 | class Something | ||
| 1456 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1457 | |||
| 1458 | -- Kurzform für | ||
| 1459 | |||
| 1460 | class Something | ||
| 1461 | new: (foo, bar, biz, baz) => | ||
| 1462 | @foo = foo | ||
| 1463 | @bar = bar | ||
| 1464 | @@biz = biz | ||
| 1465 | @@baz = baz | ||
| 1466 | ``` | ||
| 1467 | |||
| 1468 | </YueDisplay> | ||
| 1469 | |||
| 1470 | Du kannst diese Syntax auch für eine gemeinsame Funktion verwenden, um Objektfelder zu initialisieren. | ||
| 1471 | |||
| 1472 | ```yuescript | ||
| 1473 | new = (@fieldA, @fieldB) => @ | ||
| 1474 | obj = new {}, 123, "abc" | ||
| 1475 | print obj | ||
| 1476 | ``` | ||
| 1477 | |||
| 1478 | <YueDisplay> | ||
| 1479 | |||
| 1480 | ```yue | ||
| 1481 | new = (@fieldA, @fieldB) => @ | ||
| 1482 | obj = new {}, 123, "abc" | ||
| 1483 | print obj | ||
| 1484 | ``` | ||
| 1485 | |||
| 1486 | </YueDisplay> | ||
| 1487 | |||
| 1488 | ## Klassenausdrücke | ||
| 1489 | |||
| 1490 | Die `class`-Syntax kann auch als Ausdruck verwendet werden, der einer Variable zugewiesen oder explizit zurückgegeben wird. | ||
| 1491 | |||
| 1492 | ```yuescript | ||
| 1493 | x = class Bucket | ||
| 1494 | drops: 0 | ||
| 1495 | add_drop: => @drops += 1 | ||
| 1496 | ``` | ||
| 1497 | |||
| 1498 | <YueDisplay> | ||
| 1499 | |||
| 1500 | ```yue | ||
| 1501 | x = class Bucket | ||
| 1502 | drops: 0 | ||
| 1503 | add_drop: => @drops += 1 | ||
| 1504 | ``` | ||
| 1505 | |||
| 1506 | </YueDisplay> | ||
| 1507 | |||
| 1508 | ## Anonyme Klassen | ||
| 1509 | |||
| 1510 | Der Name kann beim Deklarieren einer Klasse weggelassen werden. Das `__name`-Attribut ist dann `nil`, es sei denn, der Klassenausdruck steht in einer Zuweisung. In diesem Fall wird der Name auf der linken Seite statt `nil` verwendet. | ||
| 1511 | |||
| 1512 | ```yuescript | ||
| 1513 | BigBucket = class extends Bucket | ||
| 1514 | add_drop: => @drops += 10 | ||
| 1515 | |||
| 1516 | assert Bucket.__name == "BigBucket" | ||
| 1517 | ``` | ||
| 1518 | |||
| 1519 | <YueDisplay> | ||
| 1520 | |||
| 1521 | ```yue | ||
| 1522 | BigBucket = class extends Bucket | ||
| 1523 | add_drop: => @drops += 10 | ||
| 1524 | |||
| 1525 | assert Bucket.__name == "BigBucket" | ||
| 1526 | ``` | ||
| 1527 | |||
| 1528 | </YueDisplay> | ||
| 1529 | |||
| 1530 | Du kannst sogar den Körper weglassen und eine leere anonyme Klasse schreiben: | ||
| 1531 | |||
| 1532 | ```yuescript | ||
| 1533 | x = class | ||
| 1534 | ``` | ||
| 1535 | |||
| 1536 | <YueDisplay> | ||
| 1537 | |||
| 1538 | ```yue | ||
| 1539 | x = class | ||
| 1540 | ``` | ||
| 1541 | |||
| 1542 | </YueDisplay> | ||
| 1543 | |||
| 1544 | ## Class Mixing | ||
| 1545 | |||
| 1546 | Du kannst mit dem Schlüsselwort `using` mischen, um Funktionen aus einer einfachen Tabelle oder einem vordefinierten Klassenobjekt in deine neue Klasse zu kopieren. Beim Mischen mit einer einfachen Tabelle kannst du die Klassen-Indexing-Funktion (Metamethod `__index`) überschreiben. Beim Mischen mit einem bestehenden Klassenobjekt werden dessen Metamethoden nicht kopiert. | ||
| 1547 | |||
| 1548 | ```yuescript | ||
| 1549 | MyIndex = __index: var: 1 | ||
| 1550 | |||
| 1551 | class X using MyIndex | ||
| 1552 | func: => | ||
| 1553 | print 123 | ||
| 1554 | |||
| 1555 | x = X! | ||
| 1556 | print x.var | ||
| 1557 | |||
| 1558 | class Y using X | ||
| 1559 | |||
| 1560 | y = Y! | ||
| 1561 | y\func! | ||
| 1562 | |||
| 1563 | assert y.__class.__parent ~= X -- X ist nicht die Elternklasse von Y | ||
| 1564 | ``` | ||
| 1565 | |||
| 1566 | <YueDisplay> | ||
| 1567 | |||
| 1568 | ```yue | ||
| 1569 | MyIndex = __index: var: 1 | ||
| 1570 | |||
| 1571 | class X using MyIndex | ||
| 1572 | func: => | ||
| 1573 | print 123 | ||
| 1574 | |||
| 1575 | x = X! | ||
| 1576 | print x.var | ||
| 1577 | |||
| 1578 | class Y using X | ||
| 1579 | |||
| 1580 | y = Y! | ||
| 1581 | y\func! | ||
| 1582 | |||
| 1583 | assert y.__class.__parent ~= X -- X ist nicht die Elternklasse von Y | ||
| 1584 | ``` | ||
| 1585 | |||
| 1586 | </YueDisplay> | ||
| 1587 | |||
| 1588 | # With-Statement | ||
| 1589 | |||
| 1590 | Ein häufiges Muster bei der Erstellung eines Objekts ist, unmittelbar danach eine Reihe von Funktionen aufzurufen und Eigenschaften zu setzen. | ||
| 1591 | |||
| 1592 | Das führt dazu, dass der Objektname mehrfach wiederholt wird und unnötiges Rauschen entsteht. Eine gängige Lösung ist, eine Tabelle als Argument zu übergeben, die eine Sammlung von Schlüsseln und Werten enthält, die überschrieben werden sollen. Der Nachteil ist, dass der Konstruktor dieses Objekts diese Form unterstützen muss. | ||
| 1593 | |||
| 1594 | Der `with`-Block hilft, das zu vermeiden. Innerhalb eines `with`-Blocks können wir spezielle Anweisungen verwenden, die mit `.` oder `\` beginnen und die Operationen auf das Objekt anwenden, mit dem wir gerade arbeiten. | ||
| 1595 | |||
| 1596 | Zum Beispiel arbeiten wir mit einem neu erstellten Objekt: | ||
| 1597 | |||
| 1598 | ```yuescript | ||
| 1599 | with Person! | ||
| 1600 | .name = "Oswald" | ||
| 1601 | \add_relative my_dad | ||
| 1602 | \save! | ||
| 1603 | print .name | ||
| 1604 | ``` | ||
| 1605 | |||
| 1606 | <YueDisplay> | ||
| 1607 | |||
| 1608 | ```yue | ||
| 1609 | with Person! | ||
| 1610 | .name = "Oswald" | ||
| 1611 | \add_relative my_dad | ||
| 1612 | \save! | ||
| 1613 | print .name | ||
| 1614 | ``` | ||
| 1615 | |||
| 1616 | </YueDisplay> | ||
| 1617 | |||
| 1618 | Das `with`-Statement kann auch als Ausdruck verwendet werden und gibt den Wert zurück, auf den es Zugriff gewährt. | ||
| 1619 | |||
| 1620 | ```yuescript | ||
| 1621 | file = with File "Lieblingsessen.txt" | ||
| 1622 | \set_encoding "utf8" | ||
| 1623 | ``` | ||
| 1624 | |||
| 1625 | <YueDisplay> | ||
| 1626 | |||
| 1627 | ```yue | ||
| 1628 | file = with File "Lieblingsessen.txt" | ||
| 1629 | \set_encoding "utf8" | ||
| 1630 | ``` | ||
| 1631 | |||
| 1632 | </YueDisplay> | ||
| 1633 | |||
| 1634 | `with`-Ausdrücke unterstützen `break` mit genau einem Wert: | ||
| 1635 | |||
| 1636 | ```yuescript | ||
| 1637 | result = with obj | ||
| 1638 | break .value | ||
| 1639 | ``` | ||
| 1640 | |||
| 1641 | <YueDisplay> | ||
| 1642 | |||
| 1643 | ```yue | ||
| 1644 | result = with obj | ||
| 1645 | break .value | ||
| 1646 | ``` | ||
| 1647 | |||
| 1648 | </YueDisplay> | ||
| 1649 | |||
| 1650 | Sobald `break value` in `with` verwendet wird, gibt der `with`-Ausdruck nicht mehr sein Zielobjekt zurück, sondern den von `break` gelieferten Wert. | ||
| 1651 | |||
| 1652 | ```yuescript | ||
| 1653 | a = with obj | ||
| 1654 | .x = 1 | ||
| 1655 | -- a ist obj | ||
| 1656 | |||
| 1657 | b = with obj | ||
| 1658 | break .x | ||
| 1659 | -- b ist .x, nicht obj | ||
| 1660 | ``` | ||
| 1661 | |||
| 1662 | <YueDisplay> | ||
| 1663 | |||
| 1664 | ```yue | ||
| 1665 | a = with obj | ||
| 1666 | .x = 1 | ||
| 1667 | -- a ist obj | ||
| 1668 | |||
| 1669 | b = with obj | ||
| 1670 | break .x | ||
| 1671 | -- b ist .x, nicht obj | ||
| 1672 | ``` | ||
| 1673 | |||
| 1674 | </YueDisplay> | ||
| 1675 | |||
| 1676 | Im Unterschied zu `for` / `while` / `repeat` / `do` unterstützt `with` nur einen `break`-Wert. | ||
| 1677 | |||
| 1678 | Oder … | ||
| 1679 | |||
| 1680 | ```yuescript | ||
| 1681 | create_person = (name, relatives) -> | ||
| 1682 | with Person! | ||
| 1683 | .name = name | ||
| 1684 | \add_relative relative for relative in *relatives | ||
| 1685 | |||
| 1686 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1687 | ``` | ||
| 1688 | |||
| 1689 | <YueDisplay> | ||
| 1690 | |||
| 1691 | ```yue | ||
| 1692 | create_person = (name, relatives) -> | ||
| 1693 | with Person! | ||
| 1694 | .name = name | ||
| 1695 | \add_relative relative for relative in *relatives | ||
| 1696 | |||
| 1697 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1698 | ``` | ||
| 1699 | |||
| 1700 | </YueDisplay> | ||
| 1701 | |||
| 1702 | In dieser Verwendung kann `with` als spezielle Form des K-Kombinators gesehen werden. | ||
| 1703 | |||
| 1704 | Der Ausdruck im `with`-Statement kann auch eine Zuweisung sein, wenn du dem Ausdruck einen Namen geben willst. | ||
| 1705 | |||
| 1706 | ```yuescript | ||
| 1707 | with str := "Hallo" | ||
| 1708 | print "Original:", str | ||
| 1709 | print "Großbuchstaben:", \upper! | ||
| 1710 | ``` | ||
| 1711 | |||
| 1712 | <YueDisplay> | ||
| 1713 | |||
| 1714 | ```yue | ||
| 1715 | with str := "Hallo" | ||
| 1716 | print "Original:", str | ||
| 1717 | print "Großbuchstaben:", \upper! | ||
| 1718 | ``` | ||
| 1719 | |||
| 1720 | </YueDisplay> | ||
| 1721 | |||
| 1722 | Du kannst in einem `with`-Statement über `[]` auf spezielle Schlüssel zugreifen. | ||
| 1723 | |||
| 1724 | ```yuescript | ||
| 1725 | with tb | ||
| 1726 | [1] = 1 | ||
| 1727 | print [2] | ||
| 1728 | with [abc] | ||
| 1729 | [3] = [2]\func! | ||
| 1730 | ["key-name"] = value | ||
| 1731 | [] = "abc" -- an "tb" anhängen | ||
| 1732 | ``` | ||
| 1733 | |||
| 1734 | <YueDisplay> | ||
| 1735 | |||
| 1736 | ```yue | ||
| 1737 | with tb | ||
| 1738 | [1] = 1 | ||
| 1739 | print [2] | ||
| 1740 | with [abc] | ||
| 1741 | [3] = [2]\func! | ||
| 1742 | ["key-name"] = value | ||
| 1743 | [] = "abc" -- an "tb" anhängen | ||
| 1744 | ``` | ||
| 1745 | |||
| 1746 | </YueDisplay> | ||
| 1747 | |||
| 1748 | `with?` ist eine erweiterte Version der `with`-Syntax, die einen Existenz-Check einführt, um Objekte, die `nil` sein könnten, sicher zuzugreifen, ohne explizite Nullprüfungen. | ||
| 1749 | |||
| 1750 | ```yuescript | ||
| 1751 | with? obj | ||
| 1752 | print obj.name | ||
| 1753 | ``` | ||
| 1754 | |||
| 1755 | <YueDisplay> | ||
| 1756 | |||
| 1757 | ```yue | ||
| 1758 | with? obj | ||
| 1759 | print obj.name | ||
| 1760 | ``` | ||
| 1761 | |||
| 1762 | </YueDisplay> | ||
| 1763 | |||
| 1764 | # Zuweisung | ||
| 1765 | |||
| 1766 | Variablen sind dynamisch typisiert und standardmäßig `local`. Du kannst den Geltungsbereich mit den Statements **local** und **global** ändern. | ||
| 1767 | |||
| 1768 | ```yuescript | ||
| 1769 | hello = "world" | ||
| 1770 | a, b, c = 1, 2, 3 | ||
| 1771 | hello = 123 -- nutzt die bestehende Variable | ||
| 1772 | ``` | ||
| 1773 | |||
| 1774 | <YueDisplay> | ||
| 1775 | |||
| 1776 | ```yue | ||
| 1777 | hello = "world" | ||
| 1778 | a, b, c = 1, 2, 3 | ||
| 1779 | hello = 123 -- nutzt die bestehende Variable | ||
| 1780 | ``` | ||
| 1781 | |||
| 1782 | </YueDisplay> | ||
| 1783 | |||
| 1784 | ## Update-Zuweisung | ||
| 1785 | |||
| 1786 | Du kannst Update-Zuweisungen mit vielen binären Operatoren durchführen. | ||
| 1787 | |||
| 1788 | ```yuescript | ||
| 1789 | x = 1 | ||
| 1790 | x += 1 | ||
| 1791 | x -= 1 | ||
| 1792 | x *= 10 | ||
| 1793 | x /= 10 | ||
| 1794 | x %= 10 | ||
| 1795 | s ..= "world" -- legt eine neue lokale Variable an, wenn sie nicht existiert | ||
| 1796 | arg or= "default value" | ||
| 1797 | ``` | ||
| 1798 | |||
| 1799 | <YueDisplay> | ||
| 1800 | |||
| 1801 | ```yue | ||
| 1802 | x = 1 | ||
| 1803 | x += 1 | ||
| 1804 | x -= 1 | ||
| 1805 | x *= 10 | ||
| 1806 | x /= 10 | ||
| 1807 | x %= 10 | ||
| 1808 | s ..= "world" -- legt eine neue lokale Variable an, wenn sie nicht existiert | ||
| 1809 | arg or= "default value" | ||
| 1810 | ``` | ||
| 1811 | |||
| 1812 | </YueDisplay> | ||
| 1813 | |||
| 1814 | ## Verkettete Zuweisung | ||
| 1815 | |||
| 1816 | Mit verketteten Zuweisungen kannst du mehrere Variablen auf denselben Wert setzen. | ||
| 1817 | |||
| 1818 | ```yuescript | ||
| 1819 | a = b = c = d = e = 0 | ||
| 1820 | x = y = z = f! | ||
| 1821 | ``` | ||
| 1822 | |||
| 1823 | <YueDisplay> | ||
| 1824 | |||
| 1825 | ```yue | ||
| 1826 | a = b = c = d = e = 0 | ||
| 1827 | x = y = z = f! | ||
| 1828 | ``` | ||
| 1829 | |||
| 1830 | </YueDisplay> | ||
| 1831 | |||
| 1832 | ## Explizite Locals | ||
| 1833 | |||
| 1834 | ```yuescript | ||
| 1835 | do | ||
| 1836 | local a = 1 | ||
| 1837 | local * | ||
| 1838 | print "forward declare all variables as locals" | ||
| 1839 | x = -> 1 + y + z | ||
| 1840 | y, z = 2, 3 | ||
| 1841 | global instance = Item\new! | ||
| 1842 | |||
| 1843 | do | ||
| 1844 | local X = 1 | ||
| 1845 | local ^ | ||
| 1846 | print "only forward declare upper case variables" | ||
| 1847 | a = 1 | ||
| 1848 | B = 2 | ||
| 1849 | ``` | ||
| 1850 | |||
| 1851 | <YueDisplay> | ||
| 1852 | |||
| 1853 | ```yue | ||
| 1854 | do | ||
| 1855 | local a = 1 | ||
| 1856 | local * | ||
| 1857 | print "forward declare all variables as locals" | ||
| 1858 | x = -> 1 + y + z | ||
| 1859 | y, z = 2, 3 | ||
| 1860 | global instance = Item\new! | ||
| 1861 | |||
| 1862 | do | ||
| 1863 | local X = 1 | ||
| 1864 | local ^ | ||
| 1865 | print "only forward declare upper case variables" | ||
| 1866 | a = 1 | ||
| 1867 | B = 2 | ||
| 1868 | ``` | ||
| 1869 | |||
| 1870 | </YueDisplay> | ||
| 1871 | |||
| 1872 | ## Explizite Globals | ||
| 1873 | |||
| 1874 | ```yuescript | ||
| 1875 | do | ||
| 1876 | global a = 1 | ||
| 1877 | global * | ||
| 1878 | print "declare all variables as globals" | ||
| 1879 | x = -> 1 + y + z | ||
| 1880 | y, z = 2, 3 | ||
| 1881 | |||
| 1882 | do | ||
| 1883 | global X = 1 | ||
| 1884 | global ^ | ||
| 1885 | print "only declare upper case variables as globals" | ||
| 1886 | a = 1 | ||
| 1887 | B = 2 | ||
| 1888 | local Temp = "a local value" | ||
| 1889 | ``` | ||
| 1890 | |||
| 1891 | <YueDisplay> | ||
| 1892 | |||
| 1893 | ```yue | ||
| 1894 | do | ||
| 1895 | global a = 1 | ||
| 1896 | global * | ||
| 1897 | print "declare all variables as globals" | ||
| 1898 | x = -> 1 + y + z | ||
| 1899 | y, z = 2, 3 | ||
| 1900 | |||
| 1901 | do | ||
| 1902 | global X = 1 | ||
| 1903 | global ^ | ||
| 1904 | print "only declare upper case variables as globals" | ||
| 1905 | a = 1 | ||
| 1906 | B = 2 | ||
| 1907 | local Temp = "a local value" | ||
| 1908 | ``` | ||
| 1909 | |||
| 1910 | </YueDisplay> | ||
| 1911 | |||
| 1912 | # Varargs-Zuweisung | ||
| 1913 | |||
| 1914 | Du kannst Rückgabewerte einer Funktion dem Varargs-Symbol `...` zuweisen und dann den Inhalt auf die Lua-Weise auslesen. | ||
| 1915 | |||
| 1916 | ```yuescript | ||
| 1917 | list = [1, 2, 3, 4, 5] | ||
| 1918 | fn = (ok) -> ok, table.unpack list | ||
| 1919 | ok, ... = fn true | ||
| 1920 | count = select '#', ... | ||
| 1921 | first = select 1, ... | ||
| 1922 | print ok, count, first | ||
| 1923 | ``` | ||
| 1924 | |||
| 1925 | <YueDisplay> | ||
| 1926 | |||
| 1927 | ```yue | ||
| 1928 | list = [1, 2, 3, 4, 5] | ||
| 1929 | fn = (ok) -> ok, table.unpack list | ||
| 1930 | ok, ... = fn true | ||
| 1931 | count = select '#', ... | ||
| 1932 | first = select 1, ... | ||
| 1933 | print ok, count, first | ||
| 1934 | ``` | ||
| 1935 | |||
| 1936 | </YueDisplay> | ||
| 1937 | |||
| 1938 | # If-Zuweisung | ||
| 1939 | |||
| 1940 | `if`- und `elseif`-Blöcke können eine Zuweisung anstelle eines Bedingungsausdrucks enthalten. Beim Auswerten der Bedingung findet die Zuweisung statt, und der zugewiesene Wert wird als Bedingung verwendet. Die zugewiesene Variable ist nur im Geltungsbereich des Bedingungsblocks verfügbar, d. h. sie ist nicht verfügbar, wenn der Wert nicht truthy ist. Für die Zuweisung musst du den "Walrus-Operator" `:=` statt `=` verwenden. | ||
| 1941 | |||
| 1942 | ```yuescript | ||
| 1943 | if user := database.find_user "moon" | ||
| 1944 | print user.name | ||
| 1945 | ``` | ||
| 1946 | |||
| 1947 | <YueDisplay> | ||
| 1948 | |||
| 1949 | ```yue | ||
| 1950 | if user := database.find_user "moon" | ||
| 1951 | print user.name | ||
| 1952 | ``` | ||
| 1953 | |||
| 1954 | </YueDisplay> | ||
| 1955 | |||
| 1956 | ```yuescript | ||
| 1957 | if hello := os.getenv "hello" | ||
| 1958 | print "Du hast hello", hello | ||
| 1959 | elseif world := os.getenv "world" | ||
| 1960 | print "Du hast world", world | ||
| 1961 | else | ||
| 1962 | print "nichts :(" | ||
| 1963 | ``` | ||
| 1964 | |||
| 1965 | <YueDisplay> | ||
| 1966 | |||
| 1967 | ```yue | ||
| 1968 | if hello := os.getenv "hello" | ||
| 1969 | print "Du hast hello", hello | ||
| 1970 | elseif world := os.getenv "world" | ||
| 1971 | print "Du hast world", world | ||
| 1972 | else | ||
| 1973 | print "nichts :(" | ||
| 1974 | ``` | ||
| 1975 | |||
| 1976 | </YueDisplay> | ||
| 1977 | |||
| 1978 | If-Zuweisung mit mehreren Rückgabewerten. Nur der erste Wert wird geprüft, andere Werte bleiben im Scope. | ||
| 1979 | |||
| 1980 | ```yuescript | ||
| 1981 | if success, result := pcall -> "Ergebnis ohne Probleme erhalten" | ||
| 1982 | print result -- Variable result ist im Scope | ||
| 1983 | print "OK" | ||
| 1984 | ``` | ||
| 1985 | |||
| 1986 | <YueDisplay> | ||
| 1987 | |||
| 1988 | ```yue | ||
| 1989 | if success, result := pcall -> "Ergebnis ohne Probleme erhalten" | ||
| 1990 | print result -- Variable result ist im Scope | ||
| 1991 | print "OK" | ||
| 1992 | ``` | ||
| 1993 | |||
| 1994 | </YueDisplay> | ||
| 1995 | |||
| 1996 | ## While-Zuweisung | ||
| 1997 | |||
| 1998 | Du kannst if-Zuweisung auch in einer while-Schleife verwenden, um den Wert als Schleifenbedingung zu nutzen. | ||
| 1999 | |||
| 2000 | ```yuescript | ||
| 2001 | while byte := stream\read_one! | ||
| 2002 | -- mit dem Byte etwas anfangen | ||
| 2003 | print byte | ||
| 2004 | ``` | ||
| 2005 | |||
| 2006 | <YueDisplay> | ||
| 2007 | |||
| 2008 | ```yue | ||
| 2009 | while byte := stream\read_one! | ||
| 2010 | -- mit dem Byte etwas anfangen | ||
| 2011 | print byte | ||
| 2012 | ``` | ||
| 2013 | |||
| 2014 | </YueDisplay> | ||
| 2015 | |||
| 2016 | # Destructuring-Zuweisung | ||
| 2017 | |||
| 2018 | Destructuring-Zuweisung ist eine Möglichkeit, schnell Werte aus einer Tabelle nach Name oder Position in array-basierten Tabellen zu extrahieren. | ||
| 2019 | |||
| 2020 | Normalerweise steht ein Tabellenliteral wie `{1,2,3}` auf der rechten Seite einer Zuweisung, weil es ein Wert ist. Destructuring-Zuweisung tauscht die Rolle des Tabellenliterals und setzt es auf die linke Seite der Zuweisung. | ||
| 2021 | |||
| 2022 | Am besten lässt sich das mit Beispielen erklären. So entpackst du die ersten zwei Werte einer Tabelle: | ||
| 2023 | |||
| 2024 | ```yuescript | ||
| 2025 | thing = [1, 2] | ||
| 2026 | |||
| 2027 | [a, b] = thing | ||
| 2028 | print a, b | ||
| 2029 | ``` | ||
| 2030 | |||
| 2031 | <YueDisplay> | ||
| 2032 | |||
| 2033 | ```yue | ||
| 2034 | thing = [1, 2] | ||
| 2035 | |||
| 2036 | [a, b] = thing | ||
| 2037 | print a, b | ||
| 2038 | ``` | ||
| 2039 | |||
| 2040 | </YueDisplay> | ||
| 2041 | |||
| 2042 | Im Destructuring-Tabellenliteral repräsentiert der Schlüssel den zu lesenden Schlüssel der rechten Seite, und der Wert ist der Name, dem der gelesene Wert zugewiesen wird. | ||
| 2043 | |||
| 2044 | ```yuescript | ||
| 2045 | obj = { | ||
| 2046 | hello: "Welt" | ||
| 2047 | day: "Dienstag" | ||
| 2048 | length: 20 | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | {hello: hello, day: the_day} = obj | ||
| 2052 | print hello, the_day | ||
| 2053 | |||
| 2054 | :day = obj -- einfache Destructuring-Zuweisung ohne Klammern ist ok | ||
| 2055 | ``` | ||
| 2056 | |||
| 2057 | <YueDisplay> | ||
| 2058 | |||
| 2059 | ```yue | ||
| 2060 | obj = { | ||
| 2061 | hello: "Welt" | ||
| 2062 | day: "Dienstag" | ||
| 2063 | length: 20 | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | {hello: hello, day: the_day} = obj | ||
| 2067 | print hello, the_day | ||
| 2068 | |||
| 2069 | :day = obj -- einfache Destructuring-Zuweisung ohne Klammern ist ok | ||
| 2070 | ``` | ||
| 2071 | |||
| 2072 | </YueDisplay> | ||
| 2073 | |||
| 2074 | Das funktioniert auch mit verschachtelten Datenstrukturen: | ||
| 2075 | |||
| 2076 | ```yuescript | ||
| 2077 | obj2 = { | ||
| 2078 | numbers: [1, 2, 3, 4] | ||
| 2079 | properties: { | ||
| 2080 | color: "grün" | ||
| 2081 | height: 13.5 | ||
| 2082 | } | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2086 | print first, second, color | ||
| 2087 | ``` | ||
| 2088 | |||
| 2089 | <YueDisplay> | ||
| 2090 | |||
| 2091 | ```yue | ||
| 2092 | obj2 = { | ||
| 2093 | numbers: [1, 2, 3, 4] | ||
| 2094 | properties: { | ||
| 2095 | color: "grün" | ||
| 2096 | height: 13.5 | ||
| 2097 | } | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2101 | print first, second, color | ||
| 2102 | ``` | ||
| 2103 | |||
| 2104 | </YueDisplay> | ||
| 2105 | |||
| 2106 | Wenn die Destructuring-Anweisung kompliziert ist, kannst du sie gerne auf mehrere Zeilen verteilen. Ein etwas komplexeres Beispiel: | ||
| 2107 | |||
| 2108 | ```yuescript | ||
| 2109 | { | ||
| 2110 | numbers: [first, second] | ||
| 2111 | properties: { | ||
| 2112 | color: color | ||
| 2113 | } | ||
| 2114 | } = obj2 | ||
| 2115 | ``` | ||
| 2116 | |||
| 2117 | <YueDisplay> | ||
| 2118 | |||
| 2119 | ```yue | ||
| 2120 | { | ||
| 2121 | numbers: [first, second] | ||
| 2122 | properties: { | ||
| 2123 | color: color | ||
| 2124 | } | ||
| 2125 | } = obj2 | ||
| 2126 | ``` | ||
| 2127 | |||
| 2128 | </YueDisplay> | ||
| 2129 | |||
| 2130 | Es ist üblich, Werte aus einer Tabelle zu extrahieren und ihnen lokale Variablen mit demselben Namen wie der Schlüssel zuzuweisen. Um Wiederholungen zu vermeiden, kannst du den Präfix-Operator **:** verwenden: | ||
| 2131 | |||
| 2132 | ```yuescript | ||
| 2133 | {:concat, :insert} = table | ||
| 2134 | ``` | ||
| 2135 | |||
| 2136 | <YueDisplay> | ||
| 2137 | |||
| 2138 | ```yue | ||
| 2139 | {:concat, :insert} = table | ||
| 2140 | ``` | ||
| 2141 | |||
| 2142 | </YueDisplay> | ||
| 2143 | |||
| 2144 | Das ist effektiv dasselbe wie `import`, aber du kannst Felder umbenennen, indem du die Syntax mischst: | ||
| 2145 | |||
| 2146 | ```yuescript | ||
| 2147 | {:mix, :max, random: rand} = math | ||
| 2148 | ``` | ||
| 2149 | |||
| 2150 | <YueDisplay> | ||
| 2151 | |||
| 2152 | ```yue | ||
| 2153 | {:mix, :max, random: rand} = math | ||
| 2154 | ``` | ||
| 2155 | |||
| 2156 | </YueDisplay> | ||
| 2157 | |||
| 2158 | Du kannst Standardwerte beim Destructuring angeben, z. B.: | ||
| 2159 | |||
| 2160 | ```yuescript | ||
| 2161 | {:name = "namenlos", :job = "arbeitlos"} = person | ||
| 2162 | ``` | ||
| 2163 | |||
| 2164 | <YueDisplay> | ||
| 2165 | |||
| 2166 | ```yue | ||
| 2167 | {:name = "namenlos", :job = "arbeitlos"} = person | ||
| 2168 | ``` | ||
| 2169 | |||
| 2170 | </YueDisplay> | ||
| 2171 | |||
| 2172 | Du kannst `_` als Platzhalter verwenden, wenn du eine Listen-Destructuring-Zuweisung machst: | ||
| 2173 | |||
| 2174 | ```yuescript | ||
| 2175 | [_, two, _, four] = items | ||
| 2176 | ``` | ||
| 2177 | |||
| 2178 | <YueDisplay> | ||
| 2179 | |||
| 2180 | ```yue | ||
| 2181 | [_, two, _, four] = items | ||
| 2182 | ``` | ||
| 2183 | |||
| 2184 | </YueDisplay> | ||
| 2185 | |||
| 2186 | ## Bereichs-Destructuring | ||
| 2187 | |||
| 2188 | Du kannst den Spread-Operator `...` in Listen-Destructuring verwenden, um einen Wertebereich zu erfassen. Das ist nützlich, wenn du bestimmte Elemente am Anfang und Ende einer Liste extrahieren und den Rest dazwischen sammeln willst. | ||
| 2189 | |||
| 2190 | ```yuescript | ||
| 2191 | orders = ["erster", "zweiter", "dritter", "vierter", "letzter"] | ||
| 2192 | [first, ...bulk, last] = orders | ||
| 2193 | print first -- gibt aus: erster | ||
| 2194 | print bulk -- gibt aus: {"zweiter", "dritter", "vierter"} | ||
| 2195 | print last -- gibt aus: letzter | ||
| 2196 | ``` | ||
| 2197 | |||
| 2198 | <YueDisplay> | ||
| 2199 | |||
| 2200 | ```yue | ||
| 2201 | orders = ["erster", "zweiter", "dritter", "vierter", "letzter"] | ||
| 2202 | [first, ...bulk, last] = orders | ||
| 2203 | print first -- gibt aus: erster | ||
| 2204 | print bulk -- gibt aus: {"zweiter", "dritter", "vierter"} | ||
| 2205 | print last -- gibt aus: letzter | ||
| 2206 | ``` | ||
| 2207 | |||
| 2208 | </YueDisplay> | ||
| 2209 | |||
| 2210 | Der Spread-Operator kann an unterschiedlichen Positionen verwendet werden, um unterschiedliche Bereiche zu erfassen, und du kannst `_` als Platzhalter für Werte verwenden, die du nicht erfassen willst: | ||
| 2211 | |||
| 2212 | ```yuescript | ||
| 2213 | -- Alles nach dem ersten Element erfassen | ||
| 2214 | [first, ...rest] = orders | ||
| 2215 | |||
| 2216 | -- Alles vor dem letzten Element erfassen | ||
| 2217 | [...start, last] = orders | ||
| 2218 | |||
| 2219 | -- Alles außer den mittleren Elementen erfassen | ||
| 2220 | [first, ..._, last] = orders | ||
| 2221 | ``` | ||
| 2222 | |||
| 2223 | <YueDisplay> | ||
| 2224 | |||
| 2225 | ```yue | ||
| 2226 | -- Alles nach dem ersten Element erfassen | ||
| 2227 | [first, ...rest] = orders | ||
| 2228 | |||
| 2229 | -- Alles vor dem letzten Element erfassen | ||
| 2230 | [...start, last] = orders | ||
| 2231 | |||
| 2232 | -- Alles außer den mittleren Elementen erfassen | ||
| 2233 | [first, ..._, last] = orders | ||
| 2234 | ``` | ||
| 2235 | |||
| 2236 | </YueDisplay> | ||
| 2237 | |||
| 2238 | ## Destructuring an anderen Stellen | ||
| 2239 | |||
| 2240 | Destructuring kann auch an Stellen vorkommen, an denen eine Zuweisung implizit erfolgt. Ein Beispiel ist eine `for`-Schleife: | ||
| 2241 | |||
| 2242 | ```yuescript | ||
| 2243 | tuples = [ | ||
| 2244 | ["hallo", "Welt"] | ||
| 2245 | ["Ei", "Kopf"] | ||
| 2246 | ] | ||
| 2247 | |||
| 2248 | for [left, right] in *tuples | ||
| 2249 | print left, right | ||
| 2250 | ``` | ||
| 2251 | |||
| 2252 | <YueDisplay> | ||
| 2253 | |||
| 2254 | ```yue | ||
| 2255 | tuples = [ | ||
| 2256 | ["hallo", "Welt"] | ||
| 2257 | ["Ei", "Kopf"] | ||
| 2258 | ] | ||
| 2259 | |||
| 2260 | for [left, right] in *tuples | ||
| 2261 | print left, right | ||
| 2262 | ``` | ||
| 2263 | |||
| 2264 | </YueDisplay> | ||
| 2265 | |||
| 2266 | Wir wissen, dass jedes Element der Array-Tabelle ein 2er-Tupel ist, daher können wir es direkt in der Namensliste der `for`-Anweisung mittels Destructuring entpacken. | ||
| 2267 | |||
| 2268 | # Die Using-Klausel: Destruktive Zuweisung kontrollieren | ||
| 2269 | |||
| 2270 | Lexikalisches Scoping kann die Komplexität des Codes stark reduzieren, aber mit wachsendem Codeumfang kann es unübersichtlich werden. Betrachte folgendes Beispiel: | ||
| 2271 | |||
| 2272 | ```yuescript | ||
| 2273 | i = 100 | ||
| 2274 | |||
| 2275 | -- viele Zeilen Code... | ||
| 2276 | |||
| 2277 | my_func = -> | ||
| 2278 | i = 10 | ||
| 2279 | while i > 0 | ||
| 2280 | print i | ||
| 2281 | i -= 1 | ||
| 2282 | |||
| 2283 | my_func! | ||
| 2284 | |||
| 2285 | print i -- wird 0 ausgeben | ||
| 2286 | ``` | ||
| 2287 | |||
| 2288 | <YueDisplay> | ||
| 2289 | |||
| 2290 | ```yue | ||
| 2291 | i = 100 | ||
| 2292 | |||
| 2293 | -- viele Zeilen Code... | ||
| 2294 | |||
| 2295 | my_func = -> | ||
| 2296 | i = 10 | ||
| 2297 | while i > 0 | ||
| 2298 | print i | ||
| 2299 | i -= 1 | ||
| 2300 | |||
| 2301 | my_func! | ||
| 2302 | |||
| 2303 | print i -- wird 0 ausgeben | ||
| 2304 | ``` | ||
| 2305 | |||
| 2306 | </YueDisplay> | ||
| 2307 | |||
| 2308 | In `my_func` haben wir den Wert von `i` versehentlich überschrieben. In diesem Beispiel ist es offensichtlich, aber in einer großen oder fremden Codebasis ist oft nicht klar, welche Namen bereits deklariert wurden. | ||
| 2309 | |||
| 2310 | Es wäre hilfreich, anzugeben, welche Variablen aus dem umschließenden Scope wir verändern wollen, um versehentliche Änderungen zu vermeiden. | ||
| 2311 | |||
| 2312 | Das Schlüsselwort `using` ermöglicht das. `using nil` stellt sicher, dass keine geschlossenen Variablen bei Zuweisungen überschrieben werden. Die `using`-Klausel steht nach der Argumentliste einer Funktion oder ersetzt sie, wenn es keine Argumente gibt. | ||
| 2313 | |||
| 2314 | ```yuescript | ||
| 2315 | i = 100 | ||
| 2316 | |||
| 2317 | my_func = (using nil) -> | ||
| 2318 | i = "hello" -- hier wird eine neue lokale Variable erstellt | ||
| 2319 | |||
| 2320 | my_func! | ||
| 2321 | print i -- gibt 100 aus, i bleibt unverändert | ||
| 2322 | ``` | ||
| 2323 | |||
| 2324 | <YueDisplay> | ||
| 2325 | |||
| 2326 | ```yue | ||
| 2327 | i = 100 | ||
| 2328 | |||
| 2329 | my_func = (using nil) -> | ||
| 2330 | i = "hello" -- hier wird eine neue lokale Variable erstellt | ||
| 2331 | |||
| 2332 | my_func! | ||
| 2333 | print i -- gibt 100 aus, i bleibt unverändert | ||
| 2334 | ``` | ||
| 2335 | |||
| 2336 | </YueDisplay> | ||
| 2337 | |||
| 2338 | Mehrere Namen können durch Kommas getrennt werden. Closure-Werte können weiterhin gelesen, aber nicht verändert werden: | ||
| 2339 | |||
| 2340 | ```yuescript | ||
| 2341 | tmp = 1213 | ||
| 2342 | i, k = 100, 50 | ||
| 2343 | |||
| 2344 | my_func = (add using k, i) -> | ||
| 2345 | tmp = tmp + add -- ein neues lokales tmp wird erstellt | ||
| 2346 | i += tmp | ||
| 2347 | k += tmp | ||
| 2348 | |||
| 2349 | my_func(22) | ||
| 2350 | print i, k -- diese wurden aktualisiert | ||
| 2351 | ``` | ||
| 2352 | |||
| 2353 | <YueDisplay> | ||
| 2354 | |||
| 2355 | ```yue | ||
| 2356 | tmp = 1213 | ||
| 2357 | i, k = 100, 50 | ||
| 2358 | |||
| 2359 | my_func = (add using k, i) -> | ||
| 2360 | tmp = tmp + add -- ein neues lokales tmp wird erstellt | ||
| 2361 | i += tmp | ||
| 2362 | k += tmp | ||
| 2363 | |||
| 2364 | my_func(22) | ||
| 2365 | print i, k -- diese wurden aktualisiert | ||
| 2366 | ``` | ||
| 2367 | |||
| 2368 | </YueDisplay> | ||
| 2369 | |||
| 2370 | # Verwendung | ||
| 2371 | |||
| 2372 | ## Lua-Modul | ||
| 2373 | |||
| 2374 | YueScript-Modul in Lua verwenden: | ||
| 2375 | |||
| 2376 | - **Fall 1** | ||
| 2377 | |||
| 2378 | "your_yuescript_entry.yue" in Lua require'n. | ||
| 2379 | |||
| 2380 | ```Lua | ||
| 2381 | require("yue")("your_yuescript_entry") | ||
| 2382 | ``` | ||
| 2383 | |||
| 2384 | Dieser Code funktioniert weiterhin, wenn du "your_yuescript_entry.yue" im gleichen Pfad zu "your_yuescript_entry.lua" kompilierst. In den restlichen YueScript-Dateien verwendest du einfach normales **require** oder **import**. Die Zeilennummern in Fehlermeldungen werden korrekt behandelt. | ||
| 2385 | |||
| 2386 | - **Fall 2** | ||
| 2387 | |||
| 2388 | YueScript-Modul require'n und das Fehlermapping manuell umschreiben. | ||
| 2389 | |||
| 2390 | ```lua | ||
| 2391 | local yue = require("yue") | ||
| 2392 | yue.insert_loader() | ||
| 2393 | local success, result = xpcall(function() | ||
| 2394 | return require("yuescript_module_name") | ||
| 2395 | end, function(err) | ||
| 2396 | return yue.traceback(err) | ||
| 2397 | end) | ||
| 2398 | ``` | ||
| 2399 | |||
| 2400 | - **Fall 3** | ||
| 2401 | |||
| 2402 | Die YueScript-Compilerfunktion in Lua verwenden. | ||
| 2403 | |||
| 2404 | ```lua | ||
| 2405 | local yue = require("yue") | ||
| 2406 | local codes, err, globals = yue.to_lua([[ | ||
| 2407 | f = -> | ||
| 2408 | print "Hallo Welt" | ||
| 2409 | f! | ||
| 2410 | ]],{ | ||
| 2411 | implicit_return_root = true, | ||
| 2412 | reserve_line_number = true, | ||
| 2413 | lint_global = true, | ||
| 2414 | space_over_tab = false, | ||
| 2415 | options = { | ||
| 2416 | target = "5.4", | ||
| 2417 | path = "/script" | ||
| 2418 | } | ||
| 2419 | }) | ||
| 2420 | ``` | ||
| 2421 | |||
| 2422 | ## YueScript-Tool | ||
| 2423 | |||
| 2424 | YueScript-Tool verwenden mit: | ||
| 2425 | |||
| 2426 | ```shell | ||
| 2427 | > yue -h | ||
| 2428 | Verwendung: yue | ||
| 2429 | [Optionen] [<Datei/Verzeichnis>] ... | ||
| 2430 | yue -e <code_oder_datei> [argumente...] | ||
| 2431 | yue -w [<verzeichnis>] [optionen] | ||
| 2432 | yue - | ||
| 2433 | |||
| 2434 | Hinweise: | ||
| 2435 | - '-' / '--' muss das erste und einzige Argument sein. | ||
| 2436 | - '-o/--output' kann nicht mit mehreren Eingabedateien verwendet werden. | ||
| 2437 | - '-w/--watch' kann nicht mit Dateieingabe verwendet werden (nur Verzeichnisse). | ||
| 2438 | - Mit '-e/--execute' werden verbleibende Tokens als Skriptargumente behandelt. | ||
| 2439 | |||
| 2440 | Optionen: | ||
| 2441 | -h, --help Zeigt diese Hilfemeldung an und beendet das Programm. | ||
| 2442 | -e <str>, --execute <str> Datei oder Quellcode ausführen | ||
| 2443 | -m, --minify Minimierten Code erzeugen | ||
| 2444 | -r, --rewrite Ausgabe so umschreiben, dass die Zeilennummern dem Original entsprechen | ||
| 2445 | -t <ziel>, --output-to <ziel> | ||
| 2446 | Ziel für kompilierte Dateien angeben | ||
| 2447 | -o <datei>, --output <datei> | ||
| 2448 | Schreibe die Ausgabe in eine Datei | ||
| 2449 | -p, --print Schreibe die Ausgabe auf die Standardausgabe | ||
| 2450 | -b, --benchmark Gibt die Kompilierungszeit aus (keine Ausgabe schreiben) | ||
| 2451 | -g, --globals Gibt verwendete globale Variablen im Format NAME ZEILE SPALTE aus | ||
| 2452 | -s, --spaces Verwende Leerzeichen anstelle von Tabs im generierten Code | ||
| 2453 | -l, --line-numbers Schreibe Zeilennummern aus dem Quellcode | ||
| 2454 | -j, --no-implicit-return Deaktiviert implizites Rückgabe am Datei-Ende | ||
| 2455 | -c, --reserve-comments Kommentare aus dem Quellcode vor Anweisungen beibehalten | ||
| 2456 | -w [<verz>], --watch [<verz>] | ||
| 2457 | Änderungen beobachten und alle Dateien im Verzeichnis kompilieren | ||
| 2458 | -v, --version Version ausgeben | ||
| 2459 | - Lese von Standardinput, schreibe auf Standardausgabe | ||
| 2460 | (muss das erste und einzige Argument sein) | ||
| 2461 | -- Wie '-', bleibt zur Abwärtskompatibilität bestehen | ||
| 2462 | |||
| 2463 | --target <version> Gib an, welche Lua-Version erzeugt werden soll | ||
| 2464 | (Version nur von 5.1 bis 5.5 möglich) | ||
| 2465 | --path <pfad_str> Füge einen zusätzlichen Lua-Suchpfad zu package.path hinzu | ||
| 2466 | --<schlüssel>=<wert> Übertrage Compileroption im Schlüssel=Wert-Format (bestehendes Verhalten) | ||
| 2467 | |||
| 2468 | Ohne Optionen wird die REPL gestartet, gebe das Symbol '$' | ||
| 2469 | in eine einzelne Zeile ein, um den Multi-Line-Modus zu starten/beenden | ||
| 2470 | ``` | ||
| 2471 | |||
| 2472 | Anwendungsfälle: | ||
| 2473 | |||
| 2474 | Rekursiv jede YueScript-Datei mit der Endung **.yue** unter dem aktuellen Pfad kompilieren: **yue .** | ||
| 2475 | |||
| 2476 | Kompilieren und Ergebnisse in einen Zielpfad schreiben: **yue -t /target/path/ .** | ||
| 2477 | |||
| 2478 | Kompilieren und Debug-Infos beibehalten: **yue -l .** | ||
| 2479 | |||
| 2480 | Kompilieren und minifizierten Code erzeugen: **yue -m .** | ||
| 2481 | |||
| 2482 | Rohcode ausführen: **yue -e 'print 123'** | ||
| 2483 | |||
| 2484 | Eine YueScript-Datei ausführen: **yue -e main.yue** | ||
| 2485 | |||
| 2486 | # Einführung | ||
| 2487 | |||
| 2488 | YueScript ist eine dynamische Sprache, die zu Lua kompiliert. Sie ist ein Dialekt von [MoonScript](https://github.com/leafo/moonscript). Code, der in YueScript geschrieben wird, ist ausdrucksstark und sehr kompakt. YueScript eignet sich zum Schreiben von veränderlicher Anwendungslogik mit besser wartbarem Code und läuft in eingebetteten Lua-Umgebungen wie Spielen oder Webservern. | ||
| 2489 | |||
| 2490 | Yue (月) ist das chinesische Wort für Mond und wird als [jyɛ] ausgesprochen. | ||
| 2491 | |||
| 2492 | ## Ein Überblick über YueScript | ||
| 2493 | |||
| 2494 | ```yuescript | ||
| 2495 | -- Import-Syntax | ||
| 2496 | import p, to_lua from "yue" | ||
| 2497 | |||
| 2498 | -- Objekt-Literale | ||
| 2499 | inventory = | ||
| 2500 | equipment: | ||
| 2501 | - "Schwert" | ||
| 2502 | - "Schild" | ||
| 2503 | items: | ||
| 2504 | - name: "Trank" | ||
| 2505 | count: 10 | ||
| 2506 | - name: "Brot" | ||
| 2507 | count: 3 | ||
| 2508 | |||
| 2509 | -- Listen-Abstraktion | ||
| 2510 | map = (arr, action) -> | ||
| 2511 | [action item for item in *arr] | ||
| 2512 | |||
| 2513 | filter = (arr, cond) -> | ||
| 2514 | [item for item in *arr when cond item] | ||
| 2515 | |||
| 2516 | reduce = (arr, init, action): init -> | ||
| 2517 | init = action init, item for item in *arr | ||
| 2518 | |||
| 2519 | -- Pipe-Operator | ||
| 2520 | [1, 2, 3] | ||
| 2521 | |> map (x) -> x * 2 | ||
| 2522 | |> filter (x) -> x > 4 | ||
| 2523 | |> reduce 0, (a, b) -> a + b | ||
| 2524 | |||
| 2525 | |||
| 2526 | -- Metatable-Manipulation | ||
| 2527 | apple = | ||
| 2528 | size: 15 | ||
| 2529 | <index>: | ||
| 2530 | color: 0x00ffff | ||
| 2531 | |||
| 2532 | with apple | ||
| 2533 | p .size, .color, .<index> if .<>? | ||
| 2534 | |||
| 2535 | -- export-Syntax (ähnlich wie in JavaScript) | ||
| 2536 | export 🌛 = "Skript des Mondes" | ||
| 2537 | ``` | ||
| 2538 | |||
| 2539 | <YueDisplay> | ||
| 2540 | |||
| 2541 | ```yue | ||
| 2542 | -- Import-Syntax | ||
| 2543 | import p, to_lua from "yue" | ||
| 2544 | |||
| 2545 | -- Objekt-Literale | ||
| 2546 | inventory = | ||
| 2547 | equipment: | ||
| 2548 | - "Schwert" | ||
| 2549 | - "Schild" | ||
| 2550 | items: | ||
| 2551 | - name: "Trank" | ||
| 2552 | count: 10 | ||
| 2553 | - name: "Brot" | ||
| 2554 | count: 3 | ||
| 2555 | |||
| 2556 | -- Listen-Abstraktion | ||
| 2557 | map = (arr, action) -> | ||
| 2558 | [action item for item in *arr] | ||
| 2559 | |||
| 2560 | filter = (arr, cond) -> | ||
| 2561 | [item for item in *arr when cond item] | ||
| 2562 | |||
| 2563 | reduce = (arr, init, action): init -> | ||
| 2564 | init = action init, item for item in *arr | ||
| 2565 | |||
| 2566 | -- Pipe-Operator | ||
| 2567 | [1, 2, 3] | ||
| 2568 | |> map (x) -> x * 2 | ||
| 2569 | |> filter (x) -> x > 4 | ||
| 2570 | |> reduce 0, (a, b) -> a + b | ||
| 2571 | |||
| 2572 | |||
| 2573 | -- Metatable-Manipulation | ||
| 2574 | apple = | ||
| 2575 | size: 15 | ||
| 2576 | <index>: | ||
| 2577 | color: 0x00ffff | ||
| 2578 | |||
| 2579 | with apple | ||
| 2580 | p .size, .color, .<index> if .<>? | ||
| 2581 | |||
| 2582 | -- export-Syntax (ähnlich wie in JavaScript) | ||
| 2583 | export 🌛 = "Skript des Mondes" | ||
| 2584 | ``` | ||
| 2585 | |||
| 2586 | </YueDisplay> | ||
| 2587 | |||
| 2588 | ## Über Dora SSR | ||
| 2589 | |||
| 2590 | YueScript wird zusammen mit der Open-Source-Spiel-Engine [Dora SSR](https://github.com/Dora-SSR/Dora-SSR) entwickelt und gepflegt. Es wird zum Erstellen von Engine-Tools, Spiel-Demos und Prototypen eingesetzt und hat seine Leistungsfähigkeit in realen Szenarien unter Beweis gestellt, während es gleichzeitig die Dora-SSR-Entwicklungserfahrung verbessert. | ||
| 2591 | |||
| 2592 | # Installation | ||
| 2593 | |||
| 2594 | ## Lua-Modul | ||
| 2595 | |||
| 2596 | Installiere [luarocks](https://luarocks.org), einen Paketmanager für Lua-Module. Installiere YueScript dann als Lua-Modul und ausführbare Datei mit: | ||
| 2597 | |||
| 2598 | ```shell | ||
| 2599 | luarocks install yuescript | ||
| 2600 | ``` | ||
| 2601 | |||
| 2602 | Oder du kannst die Datei `yue.so` bauen mit: | ||
| 2603 | |||
| 2604 | ```shell | ||
| 2605 | make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua | ||
| 2606 | ``` | ||
| 2607 | |||
| 2608 | Anschließend findest du die Binärdatei unter **bin/shared/yue.so**. | ||
| 2609 | |||
| 2610 | ## Binär-Tool bauen | ||
| 2611 | |||
| 2612 | Klone dieses Repo und baue/installiere die ausführbare Datei mit: | ||
| 2613 | |||
| 2614 | ```shell | ||
| 2615 | make install | ||
| 2616 | ``` | ||
| 2617 | |||
| 2618 | YueScript-Tool ohne Makro-Feature bauen: | ||
| 2619 | |||
| 2620 | ```shell | ||
| 2621 | make install NO_MACRO=true | ||
| 2622 | ``` | ||
| 2623 | |||
| 2624 | YueScript-Tool ohne eingebautes Lua-Binary bauen: | ||
| 2625 | |||
| 2626 | ```shell | ||
| 2627 | make install NO_LUA=true | ||
| 2628 | ``` | ||
| 2629 | |||
| 2630 | ## Vorgefertigtes Binary herunterladen | ||
| 2631 | |||
| 2632 | Du kannst vorkompilierte Binärdateien herunterladen, inklusive ausführbarer Dateien für unterschiedliche Lua-Versionen und Bibliotheksdateien. | ||
| 2633 | |||
| 2634 | Lade vorkompilierte Binärdateien von [hier](https://github.com/IppClub/YueScript/releases) herunter. | ||
| 2635 | |||
| 2636 | # Bedingungen | ||
| 2637 | |||
| 2638 | ```yuescript | ||
| 2639 | have_coins = false | ||
| 2640 | if have_coins | ||
| 2641 | print "Münzen erhalten" | ||
| 2642 | else | ||
| 2643 | print "Keine Münzen" | ||
| 2644 | ``` | ||
| 2645 | |||
| 2646 | <YueDisplay> | ||
| 2647 | |||
| 2648 | ```yue | ||
| 2649 | have_coins = false | ||
| 2650 | if have_coins | ||
| 2651 | print "Münzen erhalten" | ||
| 2652 | else | ||
| 2653 | print "Keine Münzen" | ||
| 2654 | ``` | ||
| 2655 | |||
| 2656 | </YueDisplay> | ||
| 2657 | |||
| 2658 | Eine Kurzsyntax für einzelne Anweisungen kann ebenfalls verwendet werden: | ||
| 2659 | |||
| 2660 | ```yuescript | ||
| 2661 | have_coins = false | ||
| 2662 | if have_coins then print "Münzen erhalten" else print "Keine Münzen" | ||
| 2663 | ``` | ||
| 2664 | |||
| 2665 | <YueDisplay> | ||
| 2666 | |||
| 2667 | ```yue | ||
| 2668 | have_coins = false | ||
| 2669 | if have_coins then print "Münzen erhalten" else print "Keine Münzen" | ||
| 2670 | ``` | ||
| 2671 | |||
| 2672 | </YueDisplay> | ||
| 2673 | |||
| 2674 | Da `if`-Anweisungen als Ausdrücke verwendet werden können, kann man das auch so schreiben: | ||
| 2675 | |||
| 2676 | ```yuescript | ||
| 2677 | have_coins = false | ||
| 2678 | print if have_coins then "Münzen erhalten" else "Keine Münzen" | ||
| 2679 | ``` | ||
| 2680 | |||
| 2681 | <YueDisplay> | ||
| 2682 | |||
| 2683 | ```yue | ||
| 2684 | have_coins = false | ||
| 2685 | print if have_coins then "Münzen erhalten" else "Keine Münzen" | ||
| 2686 | ``` | ||
| 2687 | |||
| 2688 | </YueDisplay> | ||
| 2689 | |||
| 2690 | Bedingungen können auch in `return`-Anweisungen und Zuweisungen verwendet werden: | ||
| 2691 | |||
| 2692 | ```yuescript | ||
| 2693 | is_tall = (name) -> | ||
| 2694 | if name == "Rob" | ||
| 2695 | true | ||
| 2696 | else | ||
| 2697 | false | ||
| 2698 | |||
| 2699 | message = if is_tall "Rob" | ||
| 2700 | "Ich bin sehr groß" | ||
| 2701 | else | ||
| 2702 | "Ich bin nicht so groß" | ||
| 2703 | |||
| 2704 | print message -- gibt aus: Ich bin sehr groß | ||
| 2705 | ``` | ||
| 2706 | |||
| 2707 | <YueDisplay> | ||
| 2708 | |||
| 2709 | ```yue | ||
| 2710 | is_tall = (name) -> | ||
| 2711 | if name == "Rob" | ||
| 2712 | true | ||
| 2713 | else | ||
| 2714 | false | ||
| 2715 | |||
| 2716 | message = if is_tall "Rob" | ||
| 2717 | "Ich bin sehr groß" | ||
| 2718 | else | ||
| 2719 | "Ich bin nicht so groß" | ||
| 2720 | |||
| 2721 | print message -- gibt aus: Ich bin sehr groß | ||
| 2722 | ``` | ||
| 2723 | |||
| 2724 | </YueDisplay> | ||
| 2725 | |||
| 2726 | Das Gegenteil von `if` ist `unless`: | ||
| 2727 | |||
| 2728 | ```yuescript | ||
| 2729 | unless os.date("%A") == "Monday" | ||
| 2730 | print "Es ist nicht Montag!" | ||
| 2731 | ``` | ||
| 2732 | |||
| 2733 | <YueDisplay> | ||
| 2734 | |||
| 2735 | ```yue | ||
| 2736 | unless os.date("%A") == "Monday" | ||
| 2737 | print "Es ist nicht Montag!" | ||
| 2738 | ``` | ||
| 2739 | |||
| 2740 | </YueDisplay> | ||
| 2741 | |||
| 2742 | ```yuescript | ||
| 2743 | print "You're lucky!" unless math.random! > 0.1 | ||
| 2744 | ``` | ||
| 2745 | |||
| 2746 | <YueDisplay> | ||
| 2747 | |||
| 2748 | ```yue | ||
| 2749 | print "You're lucky!" unless math.random! > 0.1 | ||
| 2750 | ``` | ||
| 2751 | |||
| 2752 | </YueDisplay> | ||
| 2753 | |||
| 2754 | ## In-Ausdruck | ||
| 2755 | |||
| 2756 | Mit einem `in`-Ausdruck kannst du Bereichsprüfungen schreiben. | ||
| 2757 | |||
| 2758 | ```yuescript | ||
| 2759 | a = 5 | ||
| 2760 | |||
| 2761 | if a in [1, 3, 5, 7] | ||
| 2762 | print "Gleichheitsprüfung mit diskreten Werten" | ||
| 2763 | |||
| 2764 | if a in list | ||
| 2765 | print "Prüfen, ob `a` in einer Liste ist" | ||
| 2766 | ``` | ||
| 2767 | |||
| 2768 | <YueDisplay> | ||
| 2769 | |||
| 2770 | ```yue | ||
| 2771 | a = 5 | ||
| 2772 | |||
| 2773 | if a in [1, 3, 5, 7] | ||
| 2774 | print "Gleichheitsprüfung mit diskreten Werten" | ||
| 2775 | |||
| 2776 | if a in list | ||
| 2777 | print "Prüfen, ob `a` in einer Liste ist" | ||
| 2778 | ``` | ||
| 2779 | |||
| 2780 | </YueDisplay> | ||
| 2781 | |||
| 2782 | # For-Schleife | ||
| 2783 | |||
| 2784 | Es gibt zwei Formen der `for`-Schleife, genau wie in Lua: eine numerische und eine generische. | ||
| 2785 | |||
| 2786 | ```yuescript | ||
| 2787 | for i = 10, 20 | ||
| 2788 | print i | ||
| 2789 | |||
| 2790 | for k = 1, 15, 2 -- ein optionaler Schritt | ||
| 2791 | print k | ||
| 2792 | |||
| 2793 | for key, value in pairs object | ||
| 2794 | print key, value | ||
| 2795 | ``` | ||
| 2796 | |||
| 2797 | <YueDisplay> | ||
| 2798 | |||
| 2799 | ```yue | ||
| 2800 | for i = 10, 20 | ||
| 2801 | print i | ||
| 2802 | |||
| 2803 | for k = 1, 15, 2 -- ein optionaler Schritt | ||
| 2804 | print k | ||
| 2805 | |||
| 2806 | for key, value in pairs object | ||
| 2807 | print key, value | ||
| 2808 | ``` | ||
| 2809 | |||
| 2810 | </YueDisplay> | ||
| 2811 | |||
| 2812 | Die Slicing- und **\***-Operatoren können verwendet werden, genau wie bei Comprehensions: | ||
| 2813 | |||
| 2814 | ```yuescript | ||
| 2815 | for item in *items[2, 4] | ||
| 2816 | print item | ||
| 2817 | ``` | ||
| 2818 | |||
| 2819 | <YueDisplay> | ||
| 2820 | |||
| 2821 | ```yue | ||
| 2822 | for item in *items[2, 4] | ||
| 2823 | print item | ||
| 2824 | ``` | ||
| 2825 | |||
| 2826 | </YueDisplay> | ||
| 2827 | |||
| 2828 | Eine kürzere Syntax ist für alle Varianten verfügbar, wenn der Rumpf nur eine Zeile hat: | ||
| 2829 | |||
| 2830 | ```yuescript | ||
| 2831 | for item in *items do print item | ||
| 2832 | |||
| 2833 | for j = 1, 10, 3 do print j | ||
| 2834 | ``` | ||
| 2835 | |||
| 2836 | <YueDisplay> | ||
| 2837 | |||
| 2838 | ```yue | ||
| 2839 | for item in *items do print item | ||
| 2840 | |||
| 2841 | for j = 1, 10, 3 do print j | ||
| 2842 | ``` | ||
| 2843 | |||
| 2844 | </YueDisplay> | ||
| 2845 | |||
| 2846 | Eine `for`-Schleife kann auch als Ausdruck verwendet werden. Die letzte Anweisung im Schleifenrumpf wird in einen Ausdruck umgewandelt und an eine wachsende Array-Tabelle angehängt. | ||
| 2847 | |||
| 2848 | Alle geraden Zahlen verdoppeln: | ||
| 2849 | |||
| 2850 | ```yuescript | ||
| 2851 | doubled_evens = for i = 1, 20 | ||
| 2852 | if i % 2 == 0 | ||
| 2853 | i * 2 | ||
| 2854 | else | ||
| 2855 | i | ||
| 2856 | ``` | ||
| 2857 | |||
| 2858 | <YueDisplay> | ||
| 2859 | |||
| 2860 | ```yue | ||
| 2861 | doubled_evens = for i = 1, 20 | ||
| 2862 | if i % 2 == 0 | ||
| 2863 | i * 2 | ||
| 2864 | else | ||
| 2865 | i | ||
| 2866 | ``` | ||
| 2867 | |||
| 2868 | </YueDisplay> | ||
| 2869 | |||
| 2870 | Zusätzlich unterstützen `for`-Schleifen `break` mit Rückgabewerten, sodass die Schleife selbst als Ausdruck verwendet werden kann, der früh mit einem sinnvollen Ergebnis endet. `for`-Ausdrücke unterstützen mehrere `break`-Werte. | ||
| 2871 | |||
| 2872 | Beispiel: die erste Zahl größer als 10 finden: | ||
| 2873 | |||
| 2874 | ```yuescript | ||
| 2875 | first_large = for n in *numbers | ||
| 2876 | break n if n > 10 | ||
| 2877 | ``` | ||
| 2878 | |||
| 2879 | <YueDisplay> | ||
| 2880 | |||
| 2881 | ```yue | ||
| 2882 | first_large = for n in *numbers | ||
| 2883 | break n if n > 10 | ||
| 2884 | ``` | ||
| 2885 | |||
| 2886 | </YueDisplay> | ||
| 2887 | |||
| 2888 | Diese `break`-mit-Wert-Syntax ermöglicht knappe und ausdrucksstarke Such- bzw. Early-Exit-Muster direkt in Schleifenausdrücken. | ||
| 2889 | |||
| 2890 | ```yuescript | ||
| 2891 | key, score = for k, v in pairs data | ||
| 2892 | break k, v * 10 if k == "target" | ||
| 2893 | ``` | ||
| 2894 | |||
| 2895 | <YueDisplay> | ||
| 2896 | |||
| 2897 | ```yue | ||
| 2898 | key, score = for k, v in pairs data | ||
| 2899 | break k, v * 10 if k == "target" | ||
| 2900 | ``` | ||
| 2901 | |||
| 2902 | </YueDisplay> | ||
| 2903 | |||
| 2904 | Du kannst Werte auch filtern, indem du den `for`-Ausdruck mit `continue` kombinierst. | ||
| 2905 | |||
| 2906 | `for`-Schleifen am Ende eines Funktionsrumpfs werden nicht in eine Tabelle für einen Rückgabewert gesammelt (stattdessen gibt die Funktion `nil` zurück). Du kannst entweder explizit `return` verwenden oder die Schleife in eine Listen-Comprehension umwandeln. | ||
| 2907 | |||
| 2908 | ```yuescript | ||
| 2909 | func_a = -> for i = 1, 10 do print i | ||
| 2910 | func_b = -> return for i = 1, 10 do i | ||
| 2911 | |||
| 2912 | print func_a! -- gibt nil aus | ||
| 2913 | print func_b! -- gibt Tabellenobjekt aus | ||
| 2914 | ``` | ||
| 2915 | |||
| 2916 | <YueDisplay> | ||
| 2917 | |||
| 2918 | ```yue | ||
| 2919 | func_a = -> for i = 1, 10 do print i | ||
| 2920 | func_b = -> return for i = 1, 10 do i | ||
| 2921 | |||
| 2922 | print func_a! -- gibt nil aus | ||
| 2923 | print func_b! -- gibt Tabellenobjekt aus | ||
| 2924 | ``` | ||
| 2925 | |||
| 2926 | </YueDisplay> | ||
| 2927 | |||
| 2928 | Das verhindert die unnötige Erstellung von Tabellen in Funktionen, die die Ergebnisse der Schleife nicht zurückgeben müssen. | ||
| 2929 | |||
| 2930 | # Continue | ||
| 2931 | |||
| 2932 | Eine `continue`-Anweisung überspringt die aktuelle Iteration einer Schleife. | ||
| 2933 | |||
| 2934 | ```yuescript | ||
| 2935 | i = 0 | ||
| 2936 | while i < 10 | ||
| 2937 | i += 1 | ||
| 2938 | continue if i % 2 == 0 | ||
| 2939 | print i | ||
| 2940 | ``` | ||
| 2941 | |||
| 2942 | <YueDisplay> | ||
| 2943 | |||
| 2944 | ```yue | ||
| 2945 | i = 0 | ||
| 2946 | while i < 10 | ||
| 2947 | i += 1 | ||
| 2948 | continue if i % 2 == 0 | ||
| 2949 | print i | ||
| 2950 | ``` | ||
| 2951 | |||
| 2952 | </YueDisplay> | ||
| 2953 | |||
| 2954 | `continue` kann auch mit Schleifenausdrücken verwendet werden, um zu verhindern, dass diese Iteration in das Ergebnis akkumuliert wird. Dieses Beispiel filtert die Array-Tabelle auf gerade Zahlen: | ||
| 2955 | |||
| 2956 | ```yuescript | ||
| 2957 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2958 | odds = for x in *my_numbers | ||
| 2959 | continue if x % 2 == 1 | ||
| 2960 | x | ||
| 2961 | ``` | ||
| 2962 | |||
| 2963 | <YueDisplay> | ||
| 2964 | |||
| 2965 | ```yue | ||
| 2966 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2967 | odds = for x in *my_numbers | ||
| 2968 | continue if x % 2 == 1 | ||
| 2969 | x | ||
| 2970 | ``` | ||
| 2971 | |||
| 2972 | </YueDisplay> | ||
| 2973 | |||
| 2974 | # Switch | ||
| 2975 | |||
| 2976 | Die `switch`-Anweisung ist eine Kurzform für eine Reihe von `if`-Anweisungen, die gegen denselben Wert prüfen. Der Wert wird nur einmal ausgewertet. Wie bei `if` kann `switch` einen `else`-Block haben, wenn keine Übereinstimmung gefunden wird. Verglichen wird mit dem Operator `==`. In einer `switch`-Anweisung kannst du auch eine Zuweisung verwenden, um den temporären Wert zu speichern. | ||
| 2977 | |||
| 2978 | ```yuescript | ||
| 2979 | switch name := "Dan" | ||
| 2980 | when "Robert" | ||
| 2981 | print "Du bist Robert" | ||
| 2982 | when "Dan", "Daniel" | ||
| 2983 | print "Dein Name ist Dan" | ||
| 2984 | else | ||
| 2985 | print "Ich kenne dich nicht mit dem Namen #{name}" | ||
| 2986 | ``` | ||
| 2987 | |||
| 2988 | <YueDisplay> | ||
| 2989 | |||
| 2990 | ```yue | ||
| 2991 | switch name := "Dan" | ||
| 2992 | when "Robert" | ||
| 2993 | print "Du bist Robert" | ||
| 2994 | when "Dan", "Daniel" | ||
| 2995 | print "Dein Name ist Dan" | ||
| 2996 | else | ||
| 2997 | print "Ich kenne dich nicht mit dem Namen #{name}" | ||
| 2998 | ``` | ||
| 2999 | |||
| 3000 | </YueDisplay> | ||
| 3001 | |||
| 3002 | Eine `when`-Klausel kann mehrere Werte prüfen, indem sie kommasepariert aufgelistet werden. | ||
| 3003 | |||
| 3004 | `switch` kann auch als Ausdruck verwendet werden. Hier wird das Ergebnis der `switch`-Anweisung einer Variable zugewiesen: | ||
| 3005 | |||
| 3006 | ```yuescript | ||
| 3007 | b = 1 | ||
| 3008 | next_number = switch b | ||
| 3009 | when 1 | ||
| 3010 | 2 | ||
| 3011 | when 2 | ||
| 3012 | 3 | ||
| 3013 | else | ||
| 3014 | error "so hoch kann ich nicht zählen!" | ||
| 3015 | ``` | ||
| 3016 | |||
| 3017 | <YueDisplay> | ||
| 3018 | |||
| 3019 | ```yue | ||
| 3020 | b = 1 | ||
| 3021 | next_number = switch b | ||
| 3022 | when 1 | ||
| 3023 | 2 | ||
| 3024 | when 2 | ||
| 3025 | 3 | ||
| 3026 | else | ||
| 3027 | error "so hoch kann ich nicht zählen!" | ||
| 3028 | ``` | ||
| 3029 | |||
| 3030 | </YueDisplay> | ||
| 3031 | |||
| 3032 | Du kannst das Schlüsselwort `then` verwenden, um einen `when`-Block in einer Zeile zu schreiben. Für den `else`-Block braucht es kein zusätzliches Schlüsselwort. | ||
| 3033 | |||
| 3034 | ```yuescript | ||
| 3035 | msg = switch math.random(1, 5) | ||
| 3036 | when 1 then "Du hast Glück" | ||
| 3037 | when 2 then "Du hast fast Glück" | ||
| 3038 | else "nicht so viel Glück" | ||
| 3039 | ``` | ||
| 3040 | |||
| 3041 | <YueDisplay> | ||
| 3042 | |||
| 3043 | ```yue | ||
| 3044 | msg = switch math.random(1, 5) | ||
| 3045 | when 1 then "Du hast Glück" | ||
| 3046 | when 2 then "Du hast fast Glück" | ||
| 3047 | else "nicht so viel Glück" | ||
| 3048 | ``` | ||
| 3049 | |||
| 3050 | </YueDisplay> | ||
| 3051 | |||
| 3052 | Wenn du eine Einrückung weniger möchtest, kannst du die erste `when`-Klausel in die Startzeile der Anweisung setzen und alle weiteren Klauseln mit einer Einrückung weniger schreiben. | ||
| 3053 | |||
| 3054 | ```yuescript | ||
| 3055 | switch math.random(1, 5) | ||
| 3056 | when 1 | ||
| 3057 | print "Du hast Glück" -- zwei Einrückungen | ||
| 3058 | else | ||
| 3059 | print "nicht so viel Glück" | ||
| 3060 | |||
| 3061 | switch math.random(1, 5) when 1 | ||
| 3062 | print "Du hast Glück" -- eine Einrückung | ||
| 3063 | else | ||
| 3064 | print "nicht so viel Glück" | ||
| 3065 | ``` | ||
| 3066 | |||
| 3067 | <YueDisplay> | ||
| 3068 | |||
| 3069 | ```yue | ||
| 3070 | switch math.random(1, 5) | ||
| 3071 | when 1 | ||
| 3072 | print "Du hast Glück" -- zwei Einrückungen | ||
| 3073 | else | ||
| 3074 | print "nicht so viel Glück" | ||
| 3075 | |||
| 3076 | switch math.random(1, 5) when 1 | ||
| 3077 | print "Du hast Glück" -- eine Einrückung | ||
| 3078 | else | ||
| 3079 | print "nicht so viel Glück" | ||
| 3080 | ``` | ||
| 3081 | |||
| 3082 | </YueDisplay> | ||
| 3083 | |||
| 3084 | Beachte die Reihenfolge des Case-Vergleichsausdrucks. Der Case-Ausdruck steht auf der linken Seite. Das kann nützlich sein, wenn der Case-Ausdruck die Vergleichslogik über eine `__eq`-Metamethod selbst definiert. | ||
| 3085 | |||
| 3086 | ## Tabellen-Matching | ||
| 3087 | |||
| 3088 | Du kannst in einer `switch`-`when`-Klausel Tabellen-Matching verwenden, wenn die Tabelle durch eine bestimmte Struktur destrukturiert werden kann und dabei nicht-`nil`-Werte liefert. | ||
| 3089 | |||
| 3090 | ```yuescript | ||
| 3091 | items = | ||
| 3092 | * x: 100 | ||
| 3093 | y: 200 | ||
| 3094 | * width: 300 | ||
| 3095 | height: 400 | ||
| 3096 | |||
| 3097 | for item in *items | ||
| 3098 | switch item | ||
| 3099 | when :x, :y | ||
| 3100 | print "Vec2 #{x}, #{y}" | ||
| 3101 | when :width, :height | ||
| 3102 | print "Größe #{width}, #{height}" | ||
| 3103 | ``` | ||
| 3104 | |||
| 3105 | <YueDisplay> | ||
| 3106 | |||
| 3107 | ```yue | ||
| 3108 | items = | ||
| 3109 | * x: 100 | ||
| 3110 | y: 200 | ||
| 3111 | * width: 300 | ||
| 3112 | height: 400 | ||
| 3113 | |||
| 3114 | for item in *items | ||
| 3115 | switch item | ||
| 3116 | when :x, :y | ||
| 3117 | print "Vec2 #{x}, #{y}" | ||
| 3118 | when :width, :height | ||
| 3119 | print "Größe #{width}, #{height}" | ||
| 3120 | ``` | ||
| 3121 | |||
| 3122 | </YueDisplay> | ||
| 3123 | |||
| 3124 | Du kannst Standardwerte verwenden, um bestimmte Felder optional zu destrukturieren. | ||
| 3125 | |||
| 3126 | ```yuescript | ||
| 3127 | item = {} | ||
| 3128 | |||
| 3129 | {pos: {:x = 50, :y = 200}} = item -- Fehler: Versuch, einen nil-Wert zu indexieren (Feld 'pos') | ||
| 3130 | |||
| 3131 | switch item | ||
| 3132 | when {pos: {:x = 50, :y = 200}} | ||
| 3133 | print "Vec2 #{x}, #{y}" -- Tabellen-Destrukturierung greift trotzdem | ||
| 3134 | ``` | ||
| 3135 | |||
| 3136 | <YueDisplay> | ||
| 3137 | |||
| 3138 | ```yue | ||
| 3139 | item = {} | ||
| 3140 | |||
| 3141 | {pos: {:x = 50, :y = 200}} = item -- Fehler: Versuch, einen nil-Wert zu indexieren (Feld 'pos') | ||
| 3142 | |||
| 3143 | switch item | ||
| 3144 | when {pos: {:x = 50, :y = 200}} | ||
| 3145 | print "Vec2 #{x}, #{y}" -- Tabellen-Destrukturierung greift trotzdem | ||
| 3146 | ``` | ||
| 3147 | |||
| 3148 | </YueDisplay> | ||
| 3149 | |||
| 3150 | Du kannst auch gegen Array-Elemente, Tabellenfelder und sogar verschachtelte Strukturen mit Array- oder Tabellenliteralen matchen. | ||
| 3151 | |||
| 3152 | Matchen gegen Array-Elemente. | ||
| 3153 | |||
| 3154 | ```yuescript | ||
| 3155 | switch tb | ||
| 3156 | when [1, 2, 3] | ||
| 3157 | print "1, 2, 3" | ||
| 3158 | when [1, b, 3] | ||
| 3159 | print "1, #{b}, 3" | ||
| 3160 | when [1, 2, b = 3] -- b hat einen Standardwert | ||
| 3161 | print "1, 2, #{b}" | ||
| 3162 | ``` | ||
| 3163 | |||
| 3164 | <YueDisplay> | ||
| 3165 | |||
| 3166 | ```yue | ||
| 3167 | switch tb | ||
| 3168 | when [1, 2, 3] | ||
| 3169 | print "1, 2, 3" | ||
| 3170 | when [1, b, 3] | ||
| 3171 | print "1, #{b}, 3" | ||
| 3172 | when [1, 2, b = 3] -- b hat einen Standardwert | ||
| 3173 | print "1, 2, #{b}" | ||
| 3174 | ``` | ||
| 3175 | |||
| 3176 | </YueDisplay> | ||
| 3177 | |||
| 3178 | Matchen gegen Tabellenfelder mit Destructuring. | ||
| 3179 | |||
| 3180 | ```yuescript | ||
| 3181 | switch tb | ||
| 3182 | when success: true, :result | ||
| 3183 | print "Erfolg", result | ||
| 3184 | when success: false | ||
| 3185 | print "fehlgeschlagen", result | ||
| 3186 | else | ||
| 3187 | print "ungültig" | ||
| 3188 | ``` | ||
| 3189 | |||
| 3190 | <YueDisplay> | ||
| 3191 | |||
| 3192 | ```yue | ||
| 3193 | switch tb | ||
| 3194 | when success: true, :result | ||
| 3195 | print "Erfolg", result | ||
| 3196 | when success: false | ||
| 3197 | print "fehlgeschlagen", result | ||
| 3198 | else | ||
| 3199 | print "ungültig" | ||
| 3200 | ``` | ||
| 3201 | |||
| 3202 | </YueDisplay> | ||
| 3203 | |||
| 3204 | Matchen gegen verschachtelte Tabellenstrukturen. | ||
| 3205 | |||
| 3206 | ```yuescript | ||
| 3207 | switch tb | ||
| 3208 | when data: {type: "success", :content} | ||
| 3209 | print "Erfolg", content | ||
| 3210 | when data: {type: "error", :content} | ||
| 3211 | print "fehlgeschlagen", content | ||
| 3212 | else | ||
| 3213 | print "ungültig" | ||
| 3214 | ``` | ||
| 3215 | |||
| 3216 | <YueDisplay> | ||
| 3217 | |||
| 3218 | ```yue | ||
| 3219 | switch tb | ||
| 3220 | when data: {type: "success", :content} | ||
| 3221 | print "Erfolg", content | ||
| 3222 | when data: {type: "error", :content} | ||
| 3223 | print "fehlgeschlagen", content | ||
| 3224 | else | ||
| 3225 | print "ungültig" | ||
| 3226 | ``` | ||
| 3227 | |||
| 3228 | </YueDisplay> | ||
| 3229 | |||
| 3230 | Matchen gegen Array von Tabellen. | ||
| 3231 | |||
| 3232 | ```yuescript | ||
| 3233 | switch tb | ||
| 3234 | when [ | ||
| 3235 | {a: 1, b: 2} | ||
| 3236 | {a: 3, b: 4} | ||
| 3237 | {a: 5, b: 6} | ||
| 3238 | fourth | ||
| 3239 | ] | ||
| 3240 | print "getroffen", fourth | ||
| 3241 | ``` | ||
| 3242 | |||
| 3243 | <YueDisplay> | ||
| 3244 | |||
| 3245 | ```yue | ||
| 3246 | switch tb | ||
| 3247 | when [ | ||
| 3248 | {a: 1, b: 2} | ||
| 3249 | {a: 3, b: 4} | ||
| 3250 | {a: 5, b: 6} | ||
| 3251 | fourth | ||
| 3252 | ] | ||
| 3253 | print "getroffen", fourth | ||
| 3254 | ``` | ||
| 3255 | |||
| 3256 | </YueDisplay> | ||
| 3257 | |||
| 3258 | Matchen gegen eine Liste und einen Bereich von Elementen erfassen. | ||
| 3259 | |||
| 3260 | ```yuescript | ||
| 3261 | segments = ["admin", "users", "logs", "view"] | ||
| 3262 | switch segments | ||
| 3263 | when [...groups, resource, action] | ||
| 3264 | print "Gruppe:", groups -- gibt aus: {"admin", "users"} | ||
| 3265 | print "Ressource:", resource -- gibt aus: "logs" | ||
| 3266 | print "Aktion:", action -- gibt aus: "view" | ||
| 3267 | ``` | ||
| 3268 | |||
| 3269 | <YueDisplay> | ||
| 3270 | |||
| 3271 | ```yue | ||
| 3272 | segments = ["admin", "users", "logs", "view"] | ||
| 3273 | switch segments | ||
| 3274 | when [...groups, resource, action] | ||
| 3275 | print "Gruppe:", groups -- gibt aus: {"admin", "users"} | ||
| 3276 | print "Ressource:", resource -- gibt aus: "logs" | ||
| 3277 | print "Aktion:", action -- gibt aus: "view" | ||
| 3278 | ``` | ||
| 3279 | |||
| 3280 | </YueDisplay> | ||
| 3281 | |||
| 3282 | # While-Schleife | ||
| 3283 | |||
| 3284 | Die `while`-Schleife gibt es ebenfalls in vier Variationen: | ||
| 3285 | |||
| 3286 | ```yuescript | ||
| 3287 | i = 10 | ||
| 3288 | while i > 0 | ||
| 3289 | print i | ||
| 3290 | i -= 1 | ||
| 3291 | |||
| 3292 | while running == true do my_function! | ||
| 3293 | ``` | ||
| 3294 | |||
| 3295 | <YueDisplay> | ||
| 3296 | |||
| 3297 | ```yue | ||
| 3298 | i = 10 | ||
| 3299 | while i > 0 | ||
| 3300 | print i | ||
| 3301 | i -= 1 | ||
| 3302 | |||
| 3303 | while running == true do my_function! | ||
| 3304 | ``` | ||
| 3305 | |||
| 3306 | </YueDisplay> | ||
| 3307 | |||
| 3308 | ```yuescript | ||
| 3309 | i = 10 | ||
| 3310 | until i == 0 | ||
| 3311 | print i | ||
| 3312 | i -= 1 | ||
| 3313 | |||
| 3314 | until running == false do my_function! | ||
| 3315 | ``` | ||
| 3316 | |||
| 3317 | <YueDisplay> | ||
| 3318 | |||
| 3319 | ```yue | ||
| 3320 | i = 10 | ||
| 3321 | until i == 0 | ||
| 3322 | print i | ||
| 3323 | i -= 1 | ||
| 3324 | until running == false do my_function! | ||
| 3325 | ``` | ||
| 3326 | |||
| 3327 | </YueDisplay> | ||
| 3328 | |||
| 3329 | Wie bei `for`-Schleifen kann die `while`-Schleife auch als Ausdruck verwendet werden. `while`- und `until`-Ausdrücke unterstützen `break` mit mehreren Rückgabewerten. | ||
| 3330 | |||
| 3331 | ```yuescript | ||
| 3332 | value, doubled = while true | ||
| 3333 | n = get_next! | ||
| 3334 | break n, n * 2 if n > 10 | ||
| 3335 | ``` | ||
| 3336 | |||
| 3337 | <YueDisplay> | ||
| 3338 | |||
| 3339 | ```yue | ||
| 3340 | value, doubled = while true | ||
| 3341 | n = get_next! | ||
| 3342 | break n, n * 2 if n > 10 | ||
| 3343 | ``` | ||
| 3344 | |||
| 3345 | </YueDisplay> | ||
| 3346 | |||
| 3347 | Damit eine Funktion den akkumulierten Wert einer `while`-Schleife zurückgibt, muss die Anweisung explizit mit `return` zurückgegeben werden. | ||
| 3348 | |||
| 3349 | ## Repeat-Schleife | ||
| 3350 | |||
| 3351 | Die `repeat`-Schleife stammt aus Lua: | ||
| 3352 | |||
| 3353 | ```yuescript | ||
| 3354 | i = 10 | ||
| 3355 | repeat | ||
| 3356 | print i | ||
| 3357 | i -= 1 | ||
| 3358 | until i == 0 | ||
| 3359 | ``` | ||
| 3360 | |||
| 3361 | <YueDisplay> | ||
| 3362 | |||
| 3363 | ```yue | ||
| 3364 | i = 10 | ||
| 3365 | repeat | ||
| 3366 | print i | ||
| 3367 | i -= 1 | ||
| 3368 | until i == 0 | ||
| 3369 | ``` | ||
| 3370 | |||
| 3371 | </YueDisplay> | ||
| 3372 | |||
| 3373 | `repeat`-Ausdrücke unterstützen ebenfalls `break` mit mehreren Rückgabewerten: | ||
| 3374 | |||
| 3375 | ```yuescript | ||
| 3376 | i = 1 | ||
| 3377 | value, scaled = repeat | ||
| 3378 | break i, i * 100 if i > 3 | ||
| 3379 | i += 1 | ||
| 3380 | until false | ||
| 3381 | ``` | ||
| 3382 | |||
| 3383 | <YueDisplay> | ||
| 3384 | |||
| 3385 | ```yue | ||
| 3386 | i = 1 | ||
| 3387 | value, scaled = repeat | ||
| 3388 | break i, i * 100 if i > 3 | ||
| 3389 | i += 1 | ||
| 3390 | until false | ||
| 3391 | ``` | ||
| 3392 | |||
| 3393 | </YueDisplay> | ||
| 3394 | |||
| 3395 | # Funktions-Stubs | ||
| 3396 | |||
| 3397 | Es ist üblich, eine Funktion eines Objekts als Wert weiterzureichen, z. B. eine Instanzmethode als Callback. Wenn die Funktion das Objekt, auf dem sie arbeitet, als erstes Argument erwartet, musst du dieses Objekt irgendwie mit der Funktion bündeln, damit sie korrekt aufgerufen werden kann. | ||
| 3398 | |||
| 3399 | Die Funktions-Stub-Syntax ist eine Kurzform, um eine neue Closure-Funktion zu erstellen, die sowohl Objekt als auch Funktion bündelt. Diese neue Funktion ruft die umschlossene Funktion im richtigen Kontext des Objekts auf. | ||
| 3400 | |||
| 3401 | Die Syntax entspricht dem Aufruf einer Instanzmethode mit dem `\`-Operator, jedoch ohne Argumentliste. | ||
| 3402 | |||
| 3403 | ```yuescript | ||
| 3404 | my_object = { | ||
| 3405 | value: 1000 | ||
| 3406 | write: => print "der Wert:", @value | ||
| 3407 | } | ||
| 3408 | |||
| 3409 | run_callback = (func) -> | ||
| 3410 | print "Callback wird ausgeführt..." | ||
| 3411 | func! | ||
| 3412 | |||
| 3413 | -- das funktioniert nicht: | ||
| 3414 | -- die Funktion darf keine Referenz auf my_object haben | ||
| 3415 | run_callback my_object.write | ||
| 3416 | |||
| 3417 | -- Funktions-Stub-Syntax | ||
| 3418 | -- bindet das Objekt in eine neue Funktion ein | ||
| 3419 | run_callback my_object\write | ||
| 3420 | ``` | ||
| 3421 | |||
| 3422 | <YueDisplay> | ||
| 3423 | |||
| 3424 | ```yue | ||
| 3425 | my_object = { | ||
| 3426 | value: 1000 | ||
| 3427 | write: => print "der Wert:", @value | ||
| 3428 | } | ||
| 3429 | |||
| 3430 | run_callback = (func) -> | ||
| 3431 | print "Callback wird ausgeführt..." | ||
| 3432 | func! | ||
| 3433 | |||
| 3434 | -- das funktioniert nicht: | ||
| 3435 | -- die Funktion darf keine Referenz auf my_object haben | ||
| 3436 | run_callback my_object.write | ||
| 3437 | |||
| 3438 | -- Funktions-Stub-Syntax | ||
| 3439 | -- bindet das Objekt in eine neue Funktion ein | ||
| 3440 | run_callback my_object\write | ||
| 3441 | ``` | ||
| 3442 | |||
| 3443 | </YueDisplay> | ||
| 3444 | |||
| 3445 | # Backcalls | ||
| 3446 | |||
| 3447 | Backcalls werden verwendet, um Callbacks zu entkoppeln (unnesting). Sie werden mit Pfeilen nach links definiert und füllen standardmäßig als letzter Parameter einen Funktionsaufruf. Die Syntax ist weitgehend wie bei normalen Pfeilfunktionen, nur dass der Pfeil in die andere Richtung zeigt und der Funktionskörper keine Einrückung benötigt. | ||
| 3448 | |||
| 3449 | ```yuescript | ||
| 3450 | x <- f | ||
| 3451 | print "hallo" .. x | ||
| 3452 | ``` | ||
| 3453 | |||
| 3454 | <YueDisplay> | ||
| 3455 | |||
| 3456 | ```yue | ||
| 3457 | x <- f | ||
| 3458 | print "hallo" .. x | ||
| 3459 | ``` | ||
| 3460 | |||
| 3461 | </YueDisplay> | ||
| 3462 | |||
| 3463 | Fat-Arrow-Funktionen sind ebenfalls verfügbar. | ||
| 3464 | |||
| 3465 | ```yuescript | ||
| 3466 | <= f | ||
| 3467 | print @value | ||
| 3468 | ``` | ||
| 3469 | |||
| 3470 | <YueDisplay> | ||
| 3471 | |||
| 3472 | ```yue | ||
| 3473 | <= f | ||
| 3474 | print @value | ||
| 3475 | ``` | ||
| 3476 | |||
| 3477 | </YueDisplay> | ||
| 3478 | |||
| 3479 | Du kannst einen Platzhalter angeben, an welcher Stelle die Backcall-Funktion als Parameter eingesetzt werden soll. | ||
| 3480 | |||
| 3481 | ```yuescript | ||
| 3482 | (x) <- map _, [1, 2, 3] | ||
| 3483 | x * 2 | ||
| 3484 | ``` | ||
| 3485 | |||
| 3486 | <YueDisplay> | ||
| 3487 | |||
| 3488 | ```yue | ||
| 3489 | (x) <- map _, [1, 2, 3] | ||
| 3490 | x * 2 | ||
| 3491 | ``` | ||
| 3492 | |||
| 3493 | </YueDisplay> | ||
| 3494 | |||
| 3495 | Wenn du nach deinen Backcalls weiteren Code haben willst, kannst du sie mit einem `do`-Statement absetzen. Bei Nicht-Fat-Arrow-Funktionen können die Klammern weggelassen werden. | ||
| 3496 | |||
| 3497 | ```yuescript | ||
| 3498 | result, msg = do | ||
| 3499 | data <- readAsync "dateiname.txt" | ||
| 3500 | print data | ||
| 3501 | info <- processAsync data | ||
| 3502 | check info | ||
| 3503 | print result, msg | ||
| 3504 | ``` | ||
| 3505 | |||
| 3506 | <YueDisplay> | ||
| 3507 | |||
| 3508 | ```yue | ||
| 3509 | result, msg = do | ||
| 3510 | data <- readAsync "dateiname.txt" | ||
| 3511 | print data | ||
| 3512 | info <- processAsync data | ||
| 3513 | check info | ||
| 3514 | print result, msg | ||
| 3515 | ``` | ||
| 3516 | |||
| 3517 | </YueDisplay> | ||
| 3518 | |||
| 3519 | # Funktionsliterale | ||
| 3520 | |||
| 3521 | Alle Funktionen werden mit einem Funktionsausdruck erstellt. Eine einfache Funktion wird mit dem Pfeil **->** notiert. | ||
| 3522 | |||
| 3523 | ```yuescript | ||
| 3524 | my_function = -> | ||
| 3525 | my_function() -- leere Funktion aufrufen | ||
| 3526 | ``` | ||
| 3527 | |||
| 3528 | <YueDisplay> | ||
| 3529 | |||
| 3530 | ```yue | ||
| 3531 | my_function = -> | ||
| 3532 | my_function() -- leere Funktion aufrufen | ||
| 3533 | ``` | ||
| 3534 | |||
| 3535 | </YueDisplay> | ||
| 3536 | |||
| 3537 | Der Funktionskörper kann entweder eine einzelne Anweisung direkt nach dem Pfeil sein oder aus mehreren Anweisungen bestehen, die in den folgenden Zeilen eingerückt werden: | ||
| 3538 | |||
| 3539 | ```yuescript | ||
| 3540 | func_a = -> print "Hallo Welt" | ||
| 3541 | |||
| 3542 | func_b = -> | ||
| 3543 | value = 100 | ||
| 3544 | print "Der Wert:", value | ||
| 3545 | ``` | ||
| 3546 | |||
| 3547 | <YueDisplay> | ||
| 3548 | |||
| 3549 | ```yue | ||
| 3550 | func_a = -> print "Hallo Welt" | ||
| 3551 | |||
| 3552 | func_b = -> | ||
| 3553 | value = 100 | ||
| 3554 | print "Der Wert:", value | ||
| 3555 | ``` | ||
| 3556 | |||
| 3557 | </YueDisplay> | ||
| 3558 | |||
| 3559 | Wenn eine Funktion keine Argumente hat, kann sie mit dem `!`-Operator statt leerer Klammern aufgerufen werden. Der `!`-Aufruf ist die bevorzugte Art, Funktionen ohne Argumente aufzurufen. | ||
| 3560 | |||
| 3561 | ```yuescript | ||
| 3562 | func_a! | ||
| 3563 | func_b() | ||
| 3564 | ``` | ||
| 3565 | |||
| 3566 | <YueDisplay> | ||
| 3567 | |||
| 3568 | ```yue | ||
| 3569 | func_a! | ||
| 3570 | func_b() | ||
| 3571 | ``` | ||
| 3572 | |||
| 3573 | </YueDisplay> | ||
| 3574 | |||
| 3575 | Funktionen mit Argumenten werden erstellt, indem der Pfeil von einer Argumentliste in Klammern eingeleitet wird: | ||
| 3576 | |||
| 3577 | ```yuescript | ||
| 3578 | sum = (x, y) -> print "Summe", x + y | ||
| 3579 | ``` | ||
| 3580 | |||
| 3581 | <YueDisplay> | ||
| 3582 | |||
| 3583 | ```yue | ||
| 3584 | sum = (x, y) -> print "Summe", x + y | ||
| 3585 | ``` | ||
| 3586 | |||
| 3587 | </YueDisplay> | ||
| 3588 | |||
| 3589 | Funktionen können aufgerufen werden, indem die Argumente hinter dem Namen eines Ausdrucks stehen, der zu einer Funktion evaluiert. Beim Verketten mehrerer Funktionsaufrufe werden die Argumente der nächstliegenden Funktion links zugeordnet. | ||
| 3590 | |||
| 3591 | ```yuescript | ||
| 3592 | sum 10, 20 | ||
| 3593 | print sum 10, 20 | ||
| 3594 | |||
| 3595 | a b c "a", "b", "c" | ||
| 3596 | ``` | ||
| 3597 | |||
| 3598 | <YueDisplay> | ||
| 3599 | |||
| 3600 | ```yue | ||
| 3601 | sum 10, 20 | ||
| 3602 | print sum 10, 20 | ||
| 3603 | |||
| 3604 | a b c "a", "b", "c" | ||
| 3605 | ``` | ||
| 3606 | |||
| 3607 | </YueDisplay> | ||
| 3608 | |||
| 3609 | Um Mehrdeutigkeiten beim Aufruf zu vermeiden, können die Argumente auch in Klammern gesetzt werden. Das ist hier nötig, damit die richtigen Argumente an die richtigen Funktionen gehen. | ||
| 3610 | |||
| 3611 | ```yuescript | ||
| 3612 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3613 | ``` | ||
| 3614 | |||
| 3615 | <YueDisplay> | ||
| 3616 | |||
| 3617 | ```yue | ||
| 3618 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3619 | ``` | ||
| 3620 | |||
| 3621 | </YueDisplay> | ||
| 3622 | |||
| 3623 | Zwischen öffnender Klammer und Funktionsname darf kein Leerzeichen stehen. | ||
| 3624 | |||
| 3625 | Funktionen wandeln die letzte Anweisung im Funktionskörper in ein `return` um. Das nennt sich implizites Return: | ||
| 3626 | |||
| 3627 | ```yuescript | ||
| 3628 | sum = (x, y) -> x + y | ||
| 3629 | print "Die Summe ist ", sum 10, 20 | ||
| 3630 | ``` | ||
| 3631 | |||
| 3632 | <YueDisplay> | ||
| 3633 | |||
| 3634 | ```yue | ||
| 3635 | sum = (x, y) -> x + y | ||
| 3636 | print "Die Summe ist ", sum 10, 20 | ||
| 3637 | ``` | ||
| 3638 | |||
| 3639 | </YueDisplay> | ||
| 3640 | |||
| 3641 | Wenn du explizit zurückgeben willst, verwende `return`: | ||
| 3642 | |||
| 3643 | ```yuescript | ||
| 3644 | sum = (x, y) -> return x + y | ||
| 3645 | ``` | ||
| 3646 | |||
| 3647 | <YueDisplay> | ||
| 3648 | |||
| 3649 | ```yue | ||
| 3650 | sum = (x, y) -> return x + y | ||
| 3651 | ``` | ||
| 3652 | |||
| 3653 | </YueDisplay> | ||
| 3654 | |||
| 3655 | Wie in Lua können Funktionen mehrere Werte zurückgeben. Die letzte Anweisung muss eine Liste von Werten sein, getrennt durch Kommas: | ||
| 3656 | |||
| 3657 | ```yuescript | ||
| 3658 | mystery = (x, y) -> x + y, x - y | ||
| 3659 | a, b = mystery 10, 20 | ||
| 3660 | ``` | ||
| 3661 | |||
| 3662 | <YueDisplay> | ||
| 3663 | |||
| 3664 | ```yue | ||
| 3665 | mystery = (x, y) -> x + y, x - y | ||
| 3666 | a, b = mystery 10, 20 | ||
| 3667 | ``` | ||
| 3668 | |||
| 3669 | </YueDisplay> | ||
| 3670 | |||
| 3671 | ## Fat Arrows | ||
| 3672 | |||
| 3673 | Da es in Lua üblich ist, beim Methodenaufruf ein Objekt als erstes Argument zu übergeben, gibt es eine spezielle Syntax zum Erstellen von Funktionen, die automatisch ein `self`-Argument enthalten. | ||
| 3674 | |||
| 3675 | ```yuescript | ||
| 3676 | func = (num) => @value + num | ||
| 3677 | ``` | ||
| 3678 | |||
| 3679 | <YueDisplay> | ||
| 3680 | |||
| 3681 | ```yue | ||
| 3682 | func = (num) => @value + num | ||
| 3683 | ``` | ||
| 3684 | |||
| 3685 | </YueDisplay> | ||
| 3686 | |||
| 3687 | ## Standardwerte für Argumente | ||
| 3688 | |||
| 3689 | Es ist möglich, Standardwerte für Funktionsargumente anzugeben. Ein Argument gilt als leer, wenn sein Wert `nil` ist. Alle `nil`-Argumente mit Standardwert werden vor Ausführung des Funktionskörpers ersetzt. | ||
| 3690 | |||
| 3691 | ```yuescript | ||
| 3692 | my_function = (name = "etwas", height = 100) -> | ||
| 3693 | print "Hallo, ich bin", name | ||
| 3694 | print "Meine Größe ist", height | ||
| 3695 | ``` | ||
| 3696 | |||
| 3697 | <YueDisplay> | ||
| 3698 | |||
| 3699 | ```yue | ||
| 3700 | my_function = (name = "etwas", height = 100) -> | ||
| 3701 | print "Hallo, ich bin", name | ||
| 3702 | print "Meine Größe ist", height | ||
| 3703 | ``` | ||
| 3704 | |||
| 3705 | </YueDisplay> | ||
| 3706 | |||
| 3707 | Der Ausdruck für den Standardwert wird im Funktionskörper in der Reihenfolge der Argumentdeklarationen ausgewertet. Daher können Standardwerte auf zuvor deklarierte Argumente zugreifen. | ||
| 3708 | |||
| 3709 | ```yuescript | ||
| 3710 | some_args = (x = 100, y = x + 1000) -> | ||
| 3711 | print x + y | ||
| 3712 | ``` | ||
| 3713 | |||
| 3714 | <YueDisplay> | ||
| 3715 | |||
| 3716 | ```yue | ||
| 3717 | some_args = (x = 100, y = x + 1000) -> | ||
| 3718 | print x + y | ||
| 3719 | ``` | ||
| 3720 | |||
| 3721 | </YueDisplay> | ||
| 3722 | |||
| 3723 | ## Hinweise | ||
| 3724 | |||
| 3725 | Aufgrund der ausdrucksstarken, klammerlosen Funktionsaufrufe müssen einige Einschränkungen gelten, um Parsing-Mehrdeutigkeiten mit Leerraum zu vermeiden. | ||
| 3726 | |||
| 3727 | Das Minuszeichen hat zwei Rollen: unäre Negation und binäre Subtraktion. Sieh dir an, wie die folgenden Beispiele kompiliert werden: | ||
| 3728 | |||
| 3729 | ```yuescript | ||
| 3730 | a = x - 10 | ||
| 3731 | b = x-10 | ||
| 3732 | c = x -y | ||
| 3733 | d = x- z | ||
| 3734 | ``` | ||
| 3735 | |||
| 3736 | <YueDisplay> | ||
| 3737 | |||
| 3738 | ```yue | ||
| 3739 | a = x - 10 | ||
| 3740 | b = x-10 | ||
| 3741 | c = x -y | ||
| 3742 | d = x- z | ||
| 3743 | ``` | ||
| 3744 | |||
| 3745 | </YueDisplay> | ||
| 3746 | |||
| 3747 | Die Präzedenz des ersten Arguments eines Funktionsaufrufs kann mit Leerraum gesteuert werden, wenn das Argument ein String-Literal ist. In Lua lässt man bei Aufrufen mit einem einzelnen String- oder Tabellenliteral häufig die Klammern weg. | ||
| 3748 | |||
| 3749 | Wenn kein Leerzeichen zwischen Variable und String-Literal steht, hat der Funktionsaufruf Vorrang vor nachfolgenden Ausdrücken. In dieser Form können keine weiteren Argumente übergeben werden. | ||
| 3750 | |||
| 3751 | Steht ein Leerzeichen zwischen Variable und String-Literal, verhält sich der Aufruf wie oben gezeigt. Das String-Literal gehört dann zu nachfolgenden Ausdrücken (falls vorhanden) und dient als Argumentliste. | ||
| 3752 | |||
| 3753 | ```yuescript | ||
| 3754 | x = func"hallo" + 100 | ||
| 3755 | y = func "hallo" + 100 | ||
| 3756 | ``` | ||
| 3757 | |||
| 3758 | <YueDisplay> | ||
| 3759 | |||
| 3760 | ```yue | ||
| 3761 | x = func"hallo" + 100 | ||
| 3762 | y = func "hallo" + 100 | ||
| 3763 | ``` | ||
| 3764 | |||
| 3765 | </YueDisplay> | ||
| 3766 | |||
| 3767 | ## Mehrzeilige Argumente | ||
| 3768 | |||
| 3769 | Wenn Funktionsaufrufe viele Argumente haben, ist es praktisch, die Argumentliste auf mehrere Zeilen zu verteilen. Wegen der whitespace-sensitiven Natur der Sprache muss man dabei sorgfältig sein. | ||
| 3770 | |||
| 3771 | Wenn eine Argumentliste in der nächsten Zeile fortgesetzt wird, muss die aktuelle Zeile mit einem Komma enden. Die folgende Zeile muss stärker eingerückt sein als die aktuelle. Sobald eingerückt, müssen alle weiteren Argumentzeilen auf derselben Einrückungsebene liegen, um Teil der Argumentliste zu sein. | ||
| 3772 | |||
| 3773 | ```yuescript | ||
| 3774 | my_func 5, 4, 3, | ||
| 3775 | 8, 9, 10 | ||
| 3776 | |||
| 3777 | cool_func 1, 2, | ||
| 3778 | 3, 4, | ||
| 3779 | 5, 6, | ||
| 3780 | 7, 8 | ||
| 3781 | ``` | ||
| 3782 | |||
| 3783 | <YueDisplay> | ||
| 3784 | |||
| 3785 | ```yue | ||
| 3786 | my_func 5, 4, 3, | ||
| 3787 | 8, 9, 10 | ||
| 3788 | |||
| 3789 | cool_func 1, 2, | ||
| 3790 | 3, 4, | ||
| 3791 | 5, 6, | ||
| 3792 | 7, 8 | ||
| 3793 | ``` | ||
| 3794 | |||
| 3795 | </YueDisplay> | ||
| 3796 | |||
| 3797 | Diese Art des Aufrufs kann verschachtelt werden. Die Einrückungsebene bestimmt, zu welcher Funktion die Argumente gehören. | ||
| 3798 | |||
| 3799 | ```yuescript | ||
| 3800 | my_func 5, 6, 7, | ||
| 3801 | 6, another_func 6, 7, 8, | ||
| 3802 | 9, 1, 2, | ||
| 3803 | 5, 4 | ||
| 3804 | ``` | ||
| 3805 | |||
| 3806 | <YueDisplay> | ||
| 3807 | |||
| 3808 | ```yue | ||
| 3809 | my_func 5, 6, 7, | ||
| 3810 | 6, another_func 6, 7, 8, | ||
| 3811 | 9, 1, 2, | ||
| 3812 | 5, 4 | ||
| 3813 | ``` | ||
| 3814 | |||
| 3815 | </YueDisplay> | ||
| 3816 | |||
| 3817 | Da Tabellen ebenfalls das Komma als Trennzeichen verwenden, hilft diese Einrückungssyntax dabei, Werte zur Argumentliste gehören zu lassen, statt zur Tabelle. | ||
| 3818 | |||
| 3819 | ```yuescript | ||
| 3820 | x = [ | ||
| 3821 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3822 | 5, 6, | ||
| 3823 | 8, 9, 10 | ||
| 3824 | ] | ||
| 3825 | ``` | ||
| 3826 | |||
| 3827 | <YueDisplay> | ||
| 3828 | |||
| 3829 | ```yue | ||
| 3830 | x = [ | ||
| 3831 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3832 | 5, 6, | ||
| 3833 | 8, 9, 10 | ||
| 3834 | ] | ||
| 3835 | ``` | ||
| 3836 | |||
| 3837 | </YueDisplay> | ||
| 3838 | |||
| 3839 | Obwohl es selten ist: Du kannst Funktionsargumente tiefer einrücken, wenn du weißt, dass du später eine geringere Einrückungsebene verwenden wirst. | ||
| 3840 | |||
| 3841 | ```yuescript | ||
| 3842 | y = [ my_func 1, 2, 3, | ||
| 3843 | 4, 5, | ||
| 3844 | 5, 6, 7 | ||
| 3845 | ] | ||
| 3846 | ``` | ||
| 3847 | |||
| 3848 | <YueDisplay> | ||
| 3849 | |||
| 3850 | ```yue | ||
| 3851 | y = [ my_func 1, 2, 3, | ||
| 3852 | 4, 5, | ||
| 3853 | 5, 6, 7 | ||
| 3854 | ] | ||
| 3855 | ``` | ||
| 3856 | |||
| 3857 | </YueDisplay> | ||
| 3858 | |||
| 3859 | Dasselbe lässt sich mit anderen Block-Statements wie Bedingungen machen. Wir können die Einrückungsebene verwenden, um zu bestimmen, zu welcher Anweisung ein Wert gehört: | ||
| 3860 | |||
| 3861 | ```yuescript | ||
| 3862 | if func 1, 2, 3, | ||
| 3863 | "hallo", | ||
| 3864 | "Welt" | ||
| 3865 | print "hallo" | ||
| 3866 | print "Ich bin innerhalb der if-Bedingung" | ||
| 3867 | |||
| 3868 | if func 1, 2, 3, | ||
| 3869 | "hallo", | ||
| 3870 | "Welt" | ||
| 3871 | print "hallo" | ||
| 3872 | print "Ich bin innerhalb der if-Bedingung" | ||
| 3873 | ``` | ||
| 3874 | |||
| 3875 | <YueDisplay> | ||
| 3876 | |||
| 3877 | ```yue | ||
| 3878 | if func 1, 2, 3, | ||
| 3879 | "hallo", | ||
| 3880 | "Welt" | ||
| 3881 | print "hallo" | ||
| 3882 | print "Ich bin innerhalb der if-Bedingung" | ||
| 3883 | |||
| 3884 | if func 1, 2, 3, | ||
| 3885 | "hallo", | ||
| 3886 | "Welt" | ||
| 3887 | print "hallo" | ||
| 3888 | print "Ich bin innerhalb der if-Bedingung" | ||
| 3889 | ``` | ||
| 3890 | |||
| 3891 | </YueDisplay> | ||
| 3892 | |||
| 3893 | ## Parameter-Destructuring | ||
| 3894 | |||
| 3895 | YueScript unterstützt jetzt Destructuring von Funktionsparametern, wenn das Argument ein Objekt ist. Es gibt zwei Formen von Destructuring-Tabellenliteralen: | ||
| 3896 | |||
| 3897 | - **Geschweifte Klammern/Objektparameter**, die optionale Standardwerte erlauben, wenn Felder fehlen (z. B. `{:a, :b}`, `{a: a1 = 123}`). | ||
| 3898 | - **Unverpackte einfache Tabellensyntax**, die mit einer Sequenz aus Key-Value- oder Shorthand-Bindings beginnt und so lange läuft, bis ein anderer Ausdruck sie beendet (z. B. `:a, b: b1, :c`). Diese Form extrahiert mehrere Felder aus demselben Objekt. | ||
| 3899 | |||
| 3900 | ```yuescript | ||
| 3901 | f1 = (:a, :b, :c) -> | ||
| 3902 | print a, b, c | ||
| 3903 | |||
| 3904 | f1 a: 1, b: "2", c: {} | ||
| 3905 | |||
| 3906 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3907 | print a1, b, c | ||
| 3908 | |||
| 3909 | arg1 = {a: 0} | ||
| 3910 | f2 arg1, arg2 | ||
| 3911 | ``` | ||
| 3912 | |||
| 3913 | <YueDisplay> | ||
| 3914 | |||
| 3915 | ```yue | ||
| 3916 | f1 = (:a, :b, :c) -> | ||
| 3917 | print a, b, c | ||
| 3918 | |||
| 3919 | f1 a: 1, b: "2", c: {} | ||
| 3920 | |||
| 3921 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3922 | print a1, b, c | ||
| 3923 | |||
| 3924 | arg1 = {a: 0} | ||
| 3925 | f2 arg1, arg2 | ||
| 3926 | ``` | ||
| 3927 | |||
| 3928 | </YueDisplay> | ||
| 3929 | |||
| 3930 | ## Präfixiertes Return-Expression | ||
| 3931 | |||
| 3932 | Wenn du mit tief verschachtelten Funktionskörpern arbeitest, kann es mühsam sein, die Lesbarkeit und Konsistenz des Rückgabewerts zu erhalten. Dafür führt YueScript die Syntax der **präfixierten Return-Expression** ein. Sie hat folgende Form: | ||
| 3933 | |||
| 3934 | ```yuescript | ||
| 3935 | findFirstEven = (list): nil -> | ||
| 3936 | for item in *list | ||
| 3937 | if type(item) == "table" | ||
| 3938 | for sub in *item | ||
| 3939 | if sub % 2 == 0 | ||
| 3940 | return sub | ||
| 3941 | ``` | ||
| 3942 | |||
| 3943 | <YueDisplay> | ||
| 3944 | |||
| 3945 | ```yue | ||
| 3946 | findFirstEven = (list): nil -> | ||
| 3947 | for item in *list | ||
| 3948 | if type(item) == "table" | ||
| 3949 | for sub in *item | ||
| 3950 | if sub % 2 == 0 | ||
| 3951 | return sub | ||
| 3952 | ``` | ||
| 3953 | |||
| 3954 | </YueDisplay> | ||
| 3955 | |||
| 3956 | Das ist äquivalent zu: | ||
| 3957 | |||
| 3958 | ```yuescript | ||
| 3959 | findFirstEven = (list) -> | ||
| 3960 | for item in *list | ||
| 3961 | if type(item) == "table" | ||
| 3962 | for sub in *item | ||
| 3963 | if sub % 2 == 0 | ||
| 3964 | return sub | ||
| 3965 | nil | ||
| 3966 | ``` | ||
| 3967 | |||
| 3968 | <YueDisplay> | ||
| 3969 | |||
| 3970 | ```yue | ||
| 3971 | findFirstEven = (list) -> | ||
| 3972 | for item in *list | ||
| 3973 | if type(item) == "table" | ||
| 3974 | for sub in *item | ||
| 3975 | if sub % 2 == 0 | ||
| 3976 | return sub | ||
| 3977 | nil | ||
| 3978 | ``` | ||
| 3979 | |||
| 3980 | </YueDisplay> | ||
| 3981 | |||
| 3982 | Der einzige Unterschied ist, dass du den finalen Rückgabeausdruck vor das `->`- oder `=>`-Token ziehen kannst, um den impliziten Rückgabewert der Funktion als letzte Anweisung zu kennzeichnen. So musst du selbst bei Funktionen mit mehreren verschachtelten Schleifen oder bedingten Zweigen kein abschließendes `return` am Ende des Funktionskörpers mehr schreiben, was die Logikstruktur klarer und leichter nachvollziehbar macht. | ||
| 3983 | |||
| 3984 | ## Benannte Varargs | ||
| 3985 | |||
| 3986 | Mit der Syntax `(...t) ->` kannst du Varargs automatisch in einer benannten Tabelle speichern. Diese Tabelle enthält alle übergebenen Argumente (einschließlich `nil`-Werten), und das Feld `n` der Tabelle speichert die tatsächliche Anzahl übergebener Argumente (einschließlich `nil`-Werten). | ||
| 3987 | |||
| 3988 | ```yuescript | ||
| 3989 | f = (...t) -> | ||
| 3990 | print "Anzahl der Argumente:", t.n | ||
| 3991 | print "Tabellenlänge:", #t | ||
| 3992 | for i = 1, t.n | ||
| 3993 | print t[i] | ||
| 3994 | |||
| 3995 | f 1, 2, 3 | ||
| 3996 | f "a", "b", "c", "d" | ||
| 3997 | f! | ||
| 3998 | |||
| 3999 | -- Fälle mit nil-Werten behandeln | ||
| 4000 | process = (...args) -> | ||
| 4001 | sum = 0 | ||
| 4002 | for i = 1, args.n | ||
| 4003 | if args[i] != nil and type(args[i]) == "number" | ||
| 4004 | sum += args[i] | ||
| 4005 | sum | ||
| 4006 | |||
| 4007 | process 1, nil, 3, nil, 5 | ||
| 4008 | ``` | ||
| 4009 | |||
| 4010 | <YueDisplay> | ||
| 4011 | |||
| 4012 | ```yue | ||
| 4013 | f = (...t) -> | ||
| 4014 | print "Anzahl der Argumente:", t.n | ||
| 4015 | print "Tabellenlänge:", #t | ||
| 4016 | for i = 1, t.n | ||
| 4017 | print t[i] | ||
| 4018 | |||
| 4019 | f 1, 2, 3 | ||
| 4020 | f "a", "b", "c", "d" | ||
| 4021 | f! | ||
| 4022 | |||
| 4023 | -- Fälle mit nil-Werten behandeln | ||
| 4024 | process = (...args) -> | ||
| 4025 | sum = 0 | ||
| 4026 | for i = 1, args.n | ||
| 4027 | if args[i] != nil and type(args[i]) == "number" | ||
| 4028 | sum += args[i] | ||
| 4029 | sum | ||
| 4030 | |||
| 4031 | process 1, nil, 3, nil, 5 | ||
| 4032 | ``` | ||
| 4033 | |||
| 4034 | </YueDisplay> | ||
| 4035 | |||
| 4036 | # Leerraum | ||
| 4037 | |||
| 4038 | YueScript ist eine whitespace-sensible Sprache. Du musst bestimmte Code-Blöcke mit derselben Einrückung (Leerzeichen **' '** oder Tab **'\t'**) schreiben, z. B. Funktionskörper, Wertelisten und Kontrollblöcke. Ausdrücke mit unterschiedlichem Leerraum können unterschiedliche Bedeutungen haben. Ein Tab wird wie 4 Leerzeichen behandelt, aber es ist besser, Leerzeichen und Tabs nicht zu mischen. | ||
| 4039 | |||
| 4040 | ## Anweisungs-Trenner | ||
| 4041 | |||
| 4042 | Eine Anweisung endet normalerweise an einem Zeilenumbruch. Du kannst auch ein Semikolon `;` verwenden, um eine Anweisung explizit zu beenden, wodurch mehrere Anweisungen in einer Zeile möglich sind: | ||
| 4043 | |||
| 4044 | ```yuescript | ||
| 4045 | a = 1; b = 2; print a + b | ||
| 4046 | ``` | ||
| 4047 | |||
| 4048 | <YueDisplay> | ||
| 4049 | |||
| 4050 | ```yue | ||
| 4051 | a = 1; b = 2; print a + b | ||
| 4052 | ``` | ||
| 4053 | |||
| 4054 | </YueDisplay> | ||
| 4055 | |||
| 4056 | ## Mehrzeiliges Chaining | ||
| 4057 | |||
| 4058 | Du kannst mehrzeilige, verkettete Funktionsaufrufe mit derselben Einrückung schreiben. | ||
| 4059 | |||
| 4060 | ```yuescript | ||
| 4061 | Rx.Observable | ||
| 4062 | .fromRange 1, 8 | ||
| 4063 | \filter (x) -> x % 2 == 0 | ||
| 4064 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4065 | \map (value) -> value .. '!' | ||
| 4066 | \subscribe print | ||
| 4067 | ``` | ||
| 4068 | |||
| 4069 | <YueDisplay> | ||
| 4070 | |||
| 4071 | ```yue | ||
| 4072 | Rx.Observable | ||
| 4073 | .fromRange 1, 8 | ||
| 4074 | \filter (x) -> x % 2 == 0 | ||
| 4075 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4076 | \map (value) -> value .. '!' | ||
| 4077 | \subscribe print | ||
| 4078 | ``` | ||
| 4079 | |||
| 4080 | </YueDisplay> | ||
| 4081 | |||
| 4082 | # Kommentare | ||
| 4083 | |||
| 4084 | ```yuescript | ||
| 4085 | -- Ich bin ein Kommentar | ||
| 4086 | |||
| 4087 | str = --[[ | ||
| 4088 | Dies ist ein mehrzeiliger Kommentar. | ||
| 4089 | Alles okay. | ||
| 4090 | ]] strA \ -- Kommentar 1 | ||
| 4091 | .. strB \ -- Kommentar 2 | ||
| 4092 | .. strC | ||
| 4093 | |||
| 4094 | func --[[Port]] 3000, --[[IP]] "192.168.1.1" | ||
| 4095 | ``` | ||
| 4096 | |||
| 4097 | <YueDisplay> | ||
| 4098 | |||
| 4099 | ```yue | ||
| 4100 | -- Ich bin ein Kommentar | ||
| 4101 | |||
| 4102 | str = --[[ | ||
| 4103 | Dies ist ein mehrzeiliger Kommentar. | ||
| 4104 | Alles okay. | ||
| 4105 | ]] strA \ -- Kommentar 1 | ||
| 4106 | .. strB \ -- Kommentar 2 | ||
| 4107 | .. strC | ||
| 4108 | |||
| 4109 | func --[[Port]] 3000, --[[IP]] "192.168.1.1" | ||
| 4110 | ``` | ||
| 4111 | |||
| 4112 | </YueDisplay> | ||
| 4113 | |||
| 4114 | # Attribute | ||
| 4115 | |||
| 4116 | Syntax-Unterstützung für Lua-5.4-Attribute. Du kannst weiterhin die Deklarationen `const` und `close` verwenden und erhältst Konstantenprüfung sowie Scoped-Callbacks, wenn du auf Lua-Versionen unter 5.4 zielst. | ||
| 4117 | |||
| 4118 | ```yuescript | ||
| 4119 | const a = 123 | ||
| 4120 | close _ = <close>: -> print "Außerhalb des Gültigkeitsbereichs." | ||
| 4121 | ``` | ||
| 4122 | |||
| 4123 | <YueDisplay> | ||
| 4124 | |||
| 4125 | ```yue | ||
| 4126 | const a = 123 | ||
| 4127 | close _ = <close>: -> print "Außerhalb des Gültigkeitsbereichs." | ||
| 4128 | ``` | ||
| 4129 | |||
| 4130 | </YueDisplay> | ||
| 4131 | |||
| 4132 | Du kannst Destructuring mit als konstant markierten Variablen verwenden. | ||
| 4133 | |||
| 4134 | ```yuescript | ||
| 4135 | const {:a, :b, c, d} = tb | ||
| 4136 | -- a = 1 | ||
| 4137 | ``` | ||
| 4138 | |||
| 4139 | <YueDisplay> | ||
| 4140 | |||
| 4141 | ```yue | ||
| 4142 | const {:a, :b, c, d} = tb | ||
| 4143 | -- a = 1 | ||
| 4144 | ``` | ||
| 4145 | |||
| 4146 | </YueDisplay> | ||
| 4147 | |||
| 4148 | Du kannst auch eine globale Variable als `const` deklarieren. | ||
| 4149 | |||
| 4150 | ```yuescript | ||
| 4151 | global const Constant = 123 | ||
| 4152 | -- Constant = 1 | ||
| 4153 | ``` | ||
| 4154 | |||
| 4155 | <YueDisplay> | ||
| 4156 | |||
| 4157 | ```yue | ||
| 4158 | global const Constant = 123 | ||
| 4159 | -- Constant = 1 | ||
| 4160 | ``` | ||
| 4161 | |||
| 4162 | </YueDisplay> | ||
| 4163 | |||
| 4164 | # Operatoren | ||
| 4165 | |||
| 4166 | Alle binären und unären Operatoren von Lua sind verfügbar. Zusätzlich ist **!=** ein Alias für **~=**, und entweder **\*\* oder **::\*\* kann für verkettete Funktionsaufrufe wie `tb\func!` oder `tb::func!` verwendet werden. Außerdem bietet YueScript einige spezielle Operatoren für ausdrucksstärkeren Code. | ||
| 4167 | |||
| 4168 | ```yuescript | ||
| 4169 | tb\func! if tb ~= nil | ||
| 4170 | tb::func! if tb != nil | ||
| 4171 | ``` | ||
| 4172 | |||
| 4173 | <YueDisplay> | ||
| 4174 | |||
| 4175 | ```yue | ||
| 4176 | tb\func! if tb ~= nil | ||
| 4177 | tb::func! if tb != nil | ||
| 4178 | ``` | ||
| 4179 | |||
| 4180 | </YueDisplay> | ||
| 4181 | |||
| 4182 | ## Verkettete Vergleiche | ||
| 4183 | |||
| 4184 | Vergleiche können beliebig verkettet werden: | ||
| 4185 | |||
| 4186 | ```yuescript | ||
| 4187 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4188 | -- Ausgabe: true | ||
| 4189 | |||
| 4190 | a = 5 | ||
| 4191 | print 1 <= a <= 10 | ||
| 4192 | -- Ausgabe: true | ||
| 4193 | ``` | ||
| 4194 | |||
| 4195 | <YueDisplay> | ||
| 4196 | |||
| 4197 | ```yue | ||
| 4198 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4199 | -- Ausgabe: true | ||
| 4200 | |||
| 4201 | a = 5 | ||
| 4202 | print 1 <= a <= 10 | ||
| 4203 | -- Ausgabe: true | ||
| 4204 | ``` | ||
| 4205 | |||
| 4206 | </YueDisplay> | ||
| 4207 | |||
| 4208 | Beachte das Auswertungsverhalten verketteter Vergleiche: | ||
| 4209 | |||
| 4210 | ```yuescript | ||
| 4211 | v = (x) -> | ||
| 4212 | print x | ||
| 4213 | x | ||
| 4214 | |||
| 4215 | print v(1) < v(2) <= v(3) | ||
| 4216 | --[[ | ||
| 4217 | Ausgabe: | ||
| 4218 | 2 | ||
| 4219 | 1 | ||
| 4220 | 3 | ||
| 4221 | true | ||
| 4222 | ]] | ||
| 4223 | |||
| 4224 | print v(1) > v(2) <= v(3) | ||
| 4225 | --[[ | ||
| 4226 | Ausgabe: | ||
| 4227 | 2 | ||
| 4228 | 1 | ||
| 4229 | false | ||
| 4230 | ]] | ||
| 4231 | ``` | ||
| 4232 | |||
| 4233 | <YueDisplay> | ||
| 4234 | |||
| 4235 | ```yue | ||
| 4236 | v = (x) -> | ||
| 4237 | print x | ||
| 4238 | x | ||
| 4239 | |||
| 4240 | print v(1) < v(2) <= v(3) | ||
| 4241 | --[[ | ||
| 4242 | Ausgabe: | ||
| 4243 | 2 | ||
| 4244 | 1 | ||
| 4245 | 3 | ||
| 4246 | true | ||
| 4247 | ]] | ||
| 4248 | |||
| 4249 | print v(1) > v(2) <= v(3) | ||
| 4250 | --[[ | ||
| 4251 | Ausgabe: | ||
| 4252 | 2 | ||
| 4253 | 1 | ||
| 4254 | false | ||
| 4255 | ]] | ||
| 4256 | ``` | ||
| 4257 | |||
| 4258 | </YueDisplay> | ||
| 4259 | |||
| 4260 | Der mittlere Ausdruck wird nur einmal ausgewertet, nicht zweimal wie bei `v(1) < v(2) and v(2) <= v(3)`. Die Auswertungsreihenfolge in verketteten Vergleichen ist jedoch undefiniert. Es wird dringend empfohlen, in verketteten Vergleichen keine Ausdrücke mit Seiteneffekten (z. B. `print`) zu verwenden. Wenn Seiteneffekte nötig sind, sollte der Short-Circuit-Operator `and` explizit verwendet werden. | ||
| 4261 | |||
| 4262 | ## Tabellenerweiterung | ||
| 4263 | |||
| 4264 | Der Operator **[] =** wird verwendet, um Werte an Tabellen anzuhängen. | ||
| 4265 | |||
| 4266 | ```yuescript | ||
| 4267 | tab = [] | ||
| 4268 | tab[] = "Wert" | ||
| 4269 | ``` | ||
| 4270 | |||
| 4271 | <YueDisplay> | ||
| 4272 | |||
| 4273 | ```yue | ||
| 4274 | tab = [] | ||
| 4275 | tab[] = "Wert" | ||
| 4276 | ``` | ||
| 4277 | |||
| 4278 | </YueDisplay> | ||
| 4279 | |||
| 4280 | Du kannst auch den Spread-Operator `...` verwenden, um alle Elemente einer Liste an eine andere anzuhängen: | ||
| 4281 | |||
| 4282 | ```yuescript | ||
| 4283 | tbA = [1, 2, 3] | ||
| 4284 | tbB = [4, 5, 6] | ||
| 4285 | tbA[] = ...tbB | ||
| 4286 | -- tbA ist jetzt [1, 2, 3, 4, 5, 6] | ||
| 4287 | ``` | ||
| 4288 | |||
| 4289 | <YueDisplay> | ||
| 4290 | |||
| 4291 | ```yue | ||
| 4292 | tbA = [1, 2, 3] | ||
| 4293 | tbB = [4, 5, 6] | ||
| 4294 | tbA[] = ...tbB | ||
| 4295 | -- tbA ist jetzt [1, 2, 3, 4, 5, 6] | ||
| 4296 | ``` | ||
| 4297 | |||
| 4298 | </YueDisplay> | ||
| 4299 | |||
| 4300 | ## Tabellen-Spread | ||
| 4301 | |||
| 4302 | Du kannst Array-Tabellen oder Hash-Tabellen mit dem Spread-Operator `...` vor Ausdrücken in Tabellenliteralen zusammenführen. | ||
| 4303 | |||
| 4304 | ```yuescript | ||
| 4305 | parts = | ||
| 4306 | * "Schultern" | ||
| 4307 | * "Knie" | ||
| 4308 | lyrics = | ||
| 4309 | * "Kopf" | ||
| 4310 | * ...parts | ||
| 4311 | * "und" | ||
| 4312 | * "Zehen" | ||
| 4313 | |||
| 4314 | copy = {...other} | ||
| 4315 | |||
| 4316 | a = {1, 2, 3, x: 1} | ||
| 4317 | b = {4, 5, y: 1} | ||
| 4318 | merge = {...a, ...b} | ||
| 4319 | ``` | ||
| 4320 | |||
| 4321 | <YueDisplay> | ||
| 4322 | |||
| 4323 | ```yue | ||
| 4324 | parts = | ||
| 4325 | * "Schultern" | ||
| 4326 | * "Knie" | ||
| 4327 | lyrics = | ||
| 4328 | * "Kopf" | ||
| 4329 | * ...parts | ||
| 4330 | * "und" | ||
| 4331 | * "Zehen" | ||
| 4332 | |||
| 4333 | copy = {...other} | ||
| 4334 | |||
| 4335 | a = {1, 2, 3, x: 1} | ||
| 4336 | b = {4, 5, y: 1} | ||
| 4337 | merge = {...a, ...b} | ||
| 4338 | ``` | ||
| 4339 | |||
| 4340 | </YueDisplay> | ||
| 4341 | |||
| 4342 | ## Umgekehrter Tabellenindex | ||
| 4343 | |||
| 4344 | Mit dem Operator **#** kannst du auf die letzten Elemente einer Tabelle zugreifen. | ||
| 4345 | |||
| 4346 | ```yuescript | ||
| 4347 | last = data.items[#] | ||
| 4348 | second_last = data.items[#-1] | ||
| 4349 | data.items[#] = 1 | ||
| 4350 | ``` | ||
| 4351 | |||
| 4352 | <YueDisplay> | ||
| 4353 | |||
| 4354 | ```yue | ||
| 4355 | last = data.items[#] | ||
| 4356 | second_last = data.items[#-1] | ||
| 4357 | data.items[#] = 1 | ||
| 4358 | ``` | ||
| 4359 | |||
| 4360 | </YueDisplay> | ||
| 4361 | |||
| 4362 | ## Metatable | ||
| 4363 | |||
| 4364 | Der Operator **<>** kann als Abkürzung für Metatable-Manipulation verwendet werden. | ||
| 4365 | |||
| 4366 | ### Metatable erstellen | ||
| 4367 | |||
| 4368 | Erzeuge eine normale Tabelle mit leeren Klammern **<>** oder einem Metamethod-Schlüssel, der von **<>** umschlossen ist. | ||
| 4369 | |||
| 4370 | ```yuescript | ||
| 4371 | mt = {} | ||
| 4372 | add = (right) => <>: mt, value: @value + right.value | ||
| 4373 | mt.__add = add | ||
| 4374 | |||
| 4375 | a = <>: mt, value: 1 | ||
| 4376 | -- Feld mit gleichnamiger Variable setzen | ||
| 4377 | b = :<add>, value: 2 | ||
| 4378 | c = <add>: mt.__add, value: 3 | ||
| 4379 | |||
| 4380 | d = a + b + c | ||
| 4381 | print d.value | ||
| 4382 | |||
| 4383 | close _ = <close>: -> print "Außerhalb des Gültigkeitsbereichs" | ||
| 4384 | ``` | ||
| 4385 | |||
| 4386 | <YueDisplay> | ||
| 4387 | |||
| 4388 | ```yue | ||
| 4389 | mt = {} | ||
| 4390 | add = (right) => <>: mt, value: @value + right.value | ||
| 4391 | mt.__add = add | ||
| 4392 | |||
| 4393 | a = <>: mt, value: 1 | ||
| 4394 | -- Feld mit gleichnamiger Variable setzen | ||
| 4395 | b = :<add>, value: 2 | ||
| 4396 | c = <add>: mt.__add, value: 3 | ||
| 4397 | |||
| 4398 | d = a + b + c | ||
| 4399 | print d.value | ||
| 4400 | |||
| 4401 | close _ = <close>: -> print "Außerhalb des Gültigkeitsbereichs" | ||
| 4402 | ``` | ||
| 4403 | |||
| 4404 | </YueDisplay> | ||
| 4405 | |||
| 4406 | ### Metatable-Zugriff | ||
| 4407 | |||
| 4408 | Metatable mit **<>** oder einem von **<>** umschlossenen Metamethod-Namen aufrufen oder einen Ausdruck in **<>** schreiben. | ||
| 4409 | |||
| 4410 | ```yuescript | ||
| 4411 | -- erstellen mit Metatable, das das Feld "value" enthält | ||
| 4412 | tb = <"value">: 123 | ||
| 4413 | tb.<index> = tb.<> | ||
| 4414 | print tb.value | ||
| 4415 | |||
| 4416 | tb.<> = __index: {item: "hallo"} | ||
| 4417 | print tb.item | ||
| 4418 | ``` | ||
| 4419 | |||
| 4420 | <YueDisplay> | ||
| 4421 | |||
| 4422 | ```yue | ||
| 4423 | -- erstellen mit Metatable, das das Feld "value" enthält | ||
| 4424 | tb = <"value">: 123 | ||
| 4425 | tb.<index> = tb.<> | ||
| 4426 | print tb.value | ||
| 4427 | tb.<> = __index: {item: "hallo"} | ||
| 4428 | print tb.item | ||
| 4429 | ``` | ||
| 4430 | |||
| 4431 | </YueDisplay> | ||
| 4432 | |||
| 4433 | ### Metatable-Destrukturierung | ||
| 4434 | |||
| 4435 | Destrukturiere Metatable mit Metamethoden-Schlüssel, der von **<>** umschlossen ist. | ||
| 4436 | |||
| 4437 | ```yuescript | ||
| 4438 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4439 | print item, new, close, getter | ||
| 4440 | ``` | ||
| 4441 | |||
| 4442 | <YueDisplay> | ||
| 4443 | |||
| 4444 | ```yue | ||
| 4445 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4446 | print item, new, close, getter | ||
| 4447 | ``` | ||
| 4448 | |||
| 4449 | </YueDisplay> | ||
| 4450 | |||
| 4451 | ## Existenz | ||
| 4452 | |||
| 4453 | Der Operator **?** kann in verschiedenen Kontexten verwendet werden, um die Existenz zu prüfen. | ||
| 4454 | |||
| 4455 | ```yuescript | ||
| 4456 | func?! | ||
| 4457 | print abc?["hello world"]?.xyz | ||
| 4458 | |||
| 4459 | x = tab?.value | ||
| 4460 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4461 | |||
| 4462 | if print and x? | ||
| 4463 | print x | ||
| 4464 | |||
| 4465 | with? io.open "test.txt", "w" | ||
| 4466 | \write "hello" | ||
| 4467 | \close! | ||
| 4468 | ``` | ||
| 4469 | |||
| 4470 | <YueDisplay> | ||
| 4471 | |||
| 4472 | ```yue | ||
| 4473 | func?! | ||
| 4474 | print abc?["hello world"]?.xyz | ||
| 4475 | |||
| 4476 | x = tab?.value | ||
| 4477 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4478 | |||
| 4479 | if print and x? | ||
| 4480 | print x | ||
| 4481 | |||
| 4482 | with? io.open "test.txt", "w" | ||
| 4483 | \write "hello" | ||
| 4484 | \close! | ||
| 4485 | ``` | ||
| 4486 | |||
| 4487 | </YueDisplay> | ||
| 4488 | |||
| 4489 | ## Piping | ||
| 4490 | |||
| 4491 | Anstelle einer Reihe verschachtelter Funktionsaufrufe kannst du Werte mit dem Operator **|>** weiterleiten. | ||
| 4492 | |||
| 4493 | ```yuescript | ||
| 4494 | "hello" |> print | ||
| 4495 | 1 |> print 2 -- Pipe-Element als erstes Argument einfügen | ||
| 4496 | 2 |> print 1, _, 3 -- Pipe mit Platzhalter | ||
| 4497 | |||
| 4498 | -- Pipe-Ausdruck über mehrere Zeilen | ||
| 4499 | readFile "example.txt" | ||
| 4500 | |> extract language, {} | ||
| 4501 | |> parse language | ||
| 4502 | |> emit | ||
| 4503 | |> render | ||
| 4504 | |||
| 4505 | ``` | ||
| 4506 | |||
| 4507 | <YueDisplay> | ||
| 4508 | |||
| 4509 | ```yue | ||
| 4510 | "hello" |> print | ||
| 4511 | 1 |> print 2 -- Pipe-Element als erstes Argument einfügen | ||
| 4512 | 2 |> print 1, _, 3 -- Pipe mit Platzhalter | ||
| 4513 | -- Pipe-Ausdruck über mehrere Zeilen | ||
| 4514 | readFile "example.txt" | ||
| 4515 | |> extract language, {} | ||
| 4516 | |> parse language | ||
| 4517 | |> emit | ||
| 4518 | |> render | ||
| 4519 | |||
| 4520 | ``` | ||
| 4521 | |||
| 4522 | </YueDisplay> | ||
| 4523 | |||
| 4524 | ## Nil-Coalescing | ||
| 4525 | |||
| 4526 | Der Nil-Coalescing-Operator **??** gibt den Wert des linken Operanden zurück, wenn er nicht **nil** ist; andernfalls wird der rechte Operand ausgewertet und sein Ergebnis zurückgegeben. Der **??**-Operator wertet seinen rechten Operanden nicht aus, wenn der linke Operand nicht nil ergibt. | ||
| 4527 | |||
| 4528 | ```yuescript | ||
| 4529 | local a, b, c, d | ||
| 4530 | a = b ?? c ?? d | ||
| 4531 | func a ?? {} | ||
| 4532 | |||
| 4533 | a ??= false | ||
| 4534 | ``` | ||
| 4535 | |||
| 4536 | <YueDisplay> | ||
| 4537 | |||
| 4538 | ```yue | ||
| 4539 | local a, b, c, d | ||
| 4540 | a = b ?? c ?? d | ||
| 4541 | func a ?? {} | ||
| 4542 | a ??= false | ||
| 4543 | ``` | ||
| 4544 | |||
| 4545 | </YueDisplay> | ||
| 4546 | |||
| 4547 | ## Implizites Objekt | ||
| 4548 | |||
| 4549 | Du kannst innerhalb eines Tabellenblocks eine Liste impliziter Strukturen schreiben, die mit dem Symbol **\*** oder **-** beginnt. Beim Erstellen eines impliziten Objekts müssen die Felder des Objekts dieselbe Einrückung haben. | ||
| 4550 | |||
| 4551 | ```yuescript | ||
| 4552 | -- Zuweisung mit implizitem Objekt | ||
| 4553 | list = | ||
| 4554 | * 1 | ||
| 4555 | * 2 | ||
| 4556 | * 3 | ||
| 4557 | |||
| 4558 | -- Funktionsaufruf mit implizitem Objekt | ||
| 4559 | func | ||
| 4560 | * 1 | ||
| 4561 | * 2 | ||
| 4562 | * 3 | ||
| 4563 | |||
| 4564 | -- Rückgabe mit implizitem Objekt | ||
| 4565 | f = -> | ||
| 4566 | return | ||
| 4567 | * 1 | ||
| 4568 | * 2 | ||
| 4569 | * 3 | ||
| 4570 | |||
| 4571 | -- Tabelle mit implizitem Objekt | ||
| 4572 | tb = | ||
| 4573 | name: "abc" | ||
| 4574 | |||
| 4575 | values: | ||
| 4576 | - "a" | ||
| 4577 | - "b" | ||
| 4578 | - "c" | ||
| 4579 | |||
| 4580 | objects: | ||
| 4581 | - name: "a" | ||
| 4582 | value: 1 | ||
| 4583 | func: => @value + 1 | ||
| 4584 | tb: | ||
| 4585 | fieldA: 1 | ||
| 4586 | |||
| 4587 | - name: "b" | ||
| 4588 | value: 2 | ||
| 4589 | func: => @value + 2 | ||
| 4590 | tb: { } | ||
| 4591 | |||
| 4592 | ``` | ||
| 4593 | |||
| 4594 | <YueDisplay> | ||
| 4595 | |||
| 4596 | ```yue | ||
| 4597 | -- Zuweisung mit implizitem Objekt | ||
| 4598 | list = | ||
| 4599 | * 1 | ||
| 4600 | * 2 | ||
| 4601 | * 3 | ||
| 4602 | |||
| 4603 | -- Funktionsaufruf mit implizitem Objekt | ||
| 4604 | func | ||
| 4605 | * 1 | ||
| 4606 | * 2 | ||
| 4607 | * 3 | ||
| 4608 | |||
| 4609 | -- Rückgabe mit implizitem Objekt | ||
| 4610 | f = -> | ||
| 4611 | return | ||
| 4612 | * 1 | ||
| 4613 | * 2 | ||
| 4614 | * 3 | ||
| 4615 | |||
| 4616 | -- Tabelle mit implizitem Objekt | ||
| 4617 | tb = | ||
| 4618 | name: "abc" | ||
| 4619 | |||
| 4620 | values: | ||
| 4621 | - "a" | ||
| 4622 | - "b" | ||
| 4623 | - "c" | ||
| 4624 | |||
| 4625 | objects: | ||
| 4626 | - name: "a" | ||
| 4627 | value: 1 | ||
| 4628 | func: => @value + 1 | ||
| 4629 | tb: | ||
| 4630 | fieldA: 1 | ||
| 4631 | |||
| 4632 | - name: "b" | ||
| 4633 | value: 2 | ||
| 4634 | func: => @value + 2 | ||
| 4635 | tb: { } | ||
| 4636 | ``` | ||
| 4637 | |||
| 4638 | </YueDisplay> | ||
| 4639 | |||
| 4640 | # Literale | ||
| 4641 | |||
| 4642 | Alle primitiven Literale in Lua können verwendet werden. Das gilt für Zahlen, Strings, Booleans und **nil**. | ||
| 4643 | |||
| 4644 | Anders als in Lua sind Zeilenumbrüche innerhalb einfacher und doppelter Anführungszeichen ohne Escape-Sequenz erlaubt: | ||
| 4645 | |||
| 4646 | ```yuescript | ||
| 4647 | some_string = "Hier ist ein String | ||
| 4648 | mit einem Zeilenumbruch." | ||
| 4649 | |||
| 4650 | -- Mit der #{}-Syntax kannst du Ausdrücke in String-Literale einbinden. | ||
| 4651 | -- String-Interpolation gibt es nur in doppelt angeführten Strings. | ||
| 4652 | print "Ich bin mir zu #{math.random! * 100}% sicher." | ||
| 4653 | ``` | ||
| 4654 | |||
| 4655 | <YueDisplay> | ||
| 4656 | |||
| 4657 | ```yue | ||
| 4658 | some_string = "Hier ist ein String | ||
| 4659 | mit einem Zeilenumbruch." | ||
| 4660 | |||
| 4661 | -- Mit der #{}-Syntax kannst du Ausdrücke in String-Literale einbinden. | ||
| 4662 | -- String-Interpolation gibt es nur in doppelt angeführten Strings. | ||
| 4663 | print "Ich bin mir zu #{math.random! * 100}% sicher." | ||
| 4664 | ``` | ||
| 4665 | |||
| 4666 | </YueDisplay> | ||
| 4667 | |||
| 4668 | ## Zahlenliterale | ||
| 4669 | |||
| 4670 | Du kannst Unterstriche in Zahlenliteralen verwenden, um die Lesbarkeit zu erhöhen. | ||
| 4671 | |||
| 4672 | ```yuescript | ||
| 4673 | integer = 1_000_000 | ||
| 4674 | hex = 0xEF_BB_BF | ||
| 4675 | binary = 0B10011 | ||
| 4676 | ``` | ||
| 4677 | |||
| 4678 | <YueDisplay> | ||
| 4679 | |||
| 4680 | ```yue | ||
| 4681 | integer = 1_000_000 | ||
| 4682 | hex = 0xEF_BB_BF | ||
| 4683 | binary = 0B10011 | ||
| 4684 | ``` | ||
| 4685 | |||
| 4686 | </YueDisplay> | ||
| 4687 | |||
| 4688 | ## YAML-Mehrzeilen-String | ||
| 4689 | |||
| 4690 | Das Präfix `|` führt ein mehrzeiliges String-Literal im YAML-Stil ein: | ||
| 4691 | |||
| 4692 | ```yuescript | ||
| 4693 | str = | | ||
| 4694 | key: value | ||
| 4695 | list: | ||
| 4696 | - item1 | ||
| 4697 | - #{expr} | ||
| 4698 | ``` | ||
| 4699 | |||
| 4700 | <YueDisplay> | ||
| 4701 | |||
| 4702 | ```yue | ||
| 4703 | str = | | ||
| 4704 | key: value | ||
| 4705 | list: | ||
| 4706 | - item1 | ||
| 4707 | - #{expr} | ||
| 4708 | ``` | ||
| 4709 | |||
| 4710 | </YueDisplay> | ||
| 4711 | |||
| 4712 | Damit lässt sich strukturierter, mehrzeiliger Text bequem schreiben. Alle Zeilenumbrüche und Einrückungen bleiben relativ zur ersten nicht-leeren Zeile erhalten, und Ausdrücke innerhalb von `#{...}` werden automatisch als `tostring(expr)` interpoliert. | ||
| 4713 | |||
| 4714 | Der YAML-Mehrzeilen-String erkennt automatisch das gemeinsame führende Leerraumpräfix (minimale Einrückung über alle nicht-leeren Zeilen) und entfernt es aus allen Zeilen. So kannst du deinen Code optisch einrücken, ohne den resultierenden String zu verändern. | ||
| 4715 | |||
| 4716 | ```yuescript | ||
| 4717 | fn = -> | ||
| 4718 | str = | | ||
| 4719 | foo: | ||
| 4720 | bar: baz | ||
| 4721 | return str | ||
| 4722 | ``` | ||
| 4723 | |||
| 4724 | <YueDisplay> | ||
| 4725 | |||
| 4726 | ```yue | ||
| 4727 | fn = -> | ||
| 4728 | str = | | ||
| 4729 | foo: | ||
| 4730 | bar: baz | ||
| 4731 | return str | ||
| 4732 | ``` | ||
| 4733 | |||
| 4734 | </YueDisplay> | ||
| 4735 | |||
| 4736 | Die interne Einrückung bleibt relativ zum entfernten gemeinsamen Präfix erhalten, wodurch saubere, verschachtelte Strukturen möglich sind. | ||
| 4737 | |||
| 4738 | Alle Sonderzeichen wie Anführungszeichen (`"`) und Backslashes (`\`) im YAML-Mehrzeilen-Block werden automatisch escaped, sodass der erzeugte Lua-String syntaktisch korrekt ist und wie erwartet funktioniert. | ||
| 4739 | |||
| 4740 | ```yuescript | ||
| 4741 | str = | | ||
| 4742 | path: "C:\Program Files\App" | ||
| 4743 | note: 'He said: "#{Hello}!"' | ||
| 4744 | ``` | ||
| 4745 | |||
| 4746 | <YueDisplay> | ||
| 4747 | |||
| 4748 | ```yue | ||
| 4749 | str = | | ||
| 4750 | path: "C:\Program Files\App" | ||
| 4751 | note: 'He said: "#{Hello}!"' | ||
| 4752 | ``` | ||
| 4753 | |||
| 4754 | </YueDisplay> | ||
| 4755 | |||
| 4756 | # Module | ||
| 4757 | |||
| 4758 | ## Import | ||
| 4759 | |||
| 4760 | Die `import`-Anweisung ist syntaktischer Zucker für `require` und hilft beim Extrahieren von Einträgen aus importierten Modulen. Importierte Elemente sind standardmäßig `const`. | ||
| 4761 | |||
| 4762 | ```yuescript | ||
| 4763 | -- als Tabellen-Destrukturierung | ||
| 4764 | do | ||
| 4765 | import insert, concat from table | ||
| 4766 | -- Fehler beim Zuweisen zu insert, concat | ||
| 4767 | import C, Ct, Cmt from require "lpeg" | ||
| 4768 | -- Kurzform für implizites Require | ||
| 4769 | import x, y, z from 'mymodule' | ||
| 4770 | -- Import im Python-Stil | ||
| 4771 | from 'module' import a, b, c | ||
| 4772 | |||
| 4773 | -- Kurzform zum Laden eines Moduls | ||
| 4774 | do | ||
| 4775 | import 'module' | ||
| 4776 | import 'module_x' | ||
| 4777 | import "d-a-s-h-e-s" | ||
| 4778 | import "module.part" | ||
| 4779 | |||
| 4780 | -- Modul mit Alias oder Tabellen-Destrukturierung laden | ||
| 4781 | do | ||
| 4782 | import "player" as PlayerModule | ||
| 4783 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4784 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4785 | ``` | ||
| 4786 | |||
| 4787 | <YueDisplay> | ||
| 4788 | |||
| 4789 | ```yue | ||
| 4790 | -- als Tabellen-Destrukturierung | ||
| 4791 | do | ||
| 4792 | import insert, concat from table | ||
| 4793 | -- Fehler beim Zuweisen zu insert, concat | ||
| 4794 | import C, Ct, Cmt from require "lpeg" | ||
| 4795 | -- Kurzform für implizites Require | ||
| 4796 | import x, y, z from 'mymodule' | ||
| 4797 | -- Import im Python-Stil | ||
| 4798 | from 'module' import a, b, c | ||
| 4799 | |||
| 4800 | -- Kurzform zum Laden eines Moduls | ||
| 4801 | do | ||
| 4802 | import 'module' | ||
| 4803 | import 'module_x' | ||
| 4804 | import "d-a-s-h-e-s" | ||
| 4805 | import "module.part" | ||
| 4806 | |||
| 4807 | -- Modul mit Alias oder Tabellen-Destrukturierung laden | ||
| 4808 | do | ||
| 4809 | import "player" as PlayerModule | ||
| 4810 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4811 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4812 | ``` | ||
| 4813 | |||
| 4814 | </YueDisplay> | ||
| 4815 | |||
| 4816 | ## Import von Globals | ||
| 4817 | |||
| 4818 | Du kannst mit `import` bestimmte Globals in lokale Variablen importieren. Wenn du eine Kette von Globalzugriffen importierst, wird das letzte Feld der lokalen Variable zugewiesen. | ||
| 4819 | |||
| 4820 | ```yuescript | ||
| 4821 | do | ||
| 4822 | import tostring | ||
| 4823 | import table.concat | ||
| 4824 | print concat ["a", tostring 1] | ||
| 4825 | ``` | ||
| 4826 | |||
| 4827 | <YueDisplay> | ||
| 4828 | |||
| 4829 | ```yue | ||
| 4830 | do | ||
| 4831 | import tostring | ||
| 4832 | import table.concat | ||
| 4833 | print concat ["a", tostring 1] | ||
| 4834 | ``` | ||
| 4835 | |||
| 4836 | </YueDisplay> | ||
| 4837 | |||
| 4838 | ### Automatischer Global-Import | ||
| 4839 | |||
| 4840 | Du kannst `import global` am Anfang eines Blocks platzieren, um automatisch alle Namen zu importieren, die im aktuellen Scope nicht explizit deklariert oder zugewiesen sind. Diese impliziten Importe werden als lokale `const` behandelt, die an die entsprechenden Globals zum Zeitpunkt der Anweisung gebunden sind. | ||
| 4841 | |||
| 4842 | Namen, die im selben Scope explizit als `global` deklariert werden, werden nicht importiert, sodass du sie weiterhin zuweisen kannst. | ||
| 4843 | |||
| 4844 | ```yuescript | ||
| 4845 | do | ||
| 4846 | import global | ||
| 4847 | print "hallo" | ||
| 4848 | math.random 3 | ||
| 4849 | -- print = nil -- Fehler: importierte Globals sind const | ||
| 4850 | |||
| 4851 | do | ||
| 4852 | -- explizite globale Variable wird nicht importiert | ||
| 4853 | import global | ||
| 4854 | global FLAG | ||
| 4855 | print FLAG | ||
| 4856 | FLAG = 123 | ||
| 4857 | ``` | ||
| 4858 | |||
| 4859 | <YueDisplay> | ||
| 4860 | |||
| 4861 | ```yue | ||
| 4862 | do | ||
| 4863 | import global | ||
| 4864 | print "hallo" | ||
| 4865 | math.random 3 | ||
| 4866 | -- print = nil -- Fehler: importierte Globals sind const | ||
| 4867 | |||
| 4868 | do | ||
| 4869 | -- explizite globale Variable wird nicht importiert | ||
| 4870 | import global | ||
| 4871 | global FLAG | ||
| 4872 | print FLAG | ||
| 4873 | FLAG = 123 | ||
| 4874 | ``` | ||
| 4875 | |||
| 4876 | </YueDisplay> | ||
| 4877 | |||
| 4878 | ## Export | ||
| 4879 | |||
| 4880 | Die `export`-Anweisung bietet eine knappe Möglichkeit, Module zu definieren. | ||
| 4881 | |||
| 4882 | ### Benannter Export | ||
| 4883 | |||
| 4884 | Benannter Export definiert eine lokale Variable und fügt ein Feld in die exportierte Tabelle ein. | ||
| 4885 | |||
| 4886 | ```yuescript | ||
| 4887 | export a, b, c = 1, 2, 3 | ||
| 4888 | export cool = "Katze" | ||
| 4889 | |||
| 4890 | export What = if this | ||
| 4891 | "abc" | ||
| 4892 | else | ||
| 4893 | "def" | ||
| 4894 | |||
| 4895 | export y = -> | ||
| 4896 | hallo = 3434 | ||
| 4897 | |||
| 4898 | export class Something | ||
| 4899 | umm: "cool" | ||
| 4900 | ``` | ||
| 4901 | |||
| 4902 | <YueDisplay> | ||
| 4903 | |||
| 4904 | ```yue | ||
| 4905 | export a, b, c = 1, 2, 3 | ||
| 4906 | export cool = "Katze" | ||
| 4907 | |||
| 4908 | export What = if this | ||
| 4909 | "abc" | ||
| 4910 | else | ||
| 4911 | "def" | ||
| 4912 | |||
| 4913 | export y = -> | ||
| 4914 | hallo = 3434 | ||
| 4915 | |||
| 4916 | export class Something | ||
| 4917 | umm: "cool" | ||
| 4918 | ``` | ||
| 4919 | |||
| 4920 | </YueDisplay> | ||
| 4921 | |||
| 4922 | Benannter Export mit Destructuring. | ||
| 4923 | |||
| 4924 | ```yuescript | ||
| 4925 | export :loadstring, to_lua: tolua = yue | ||
| 4926 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4927 | ``` | ||
| 4928 | |||
| 4929 | <YueDisplay> | ||
| 4930 | |||
| 4931 | ```yue | ||
| 4932 | export :loadstring, to_lua: tolua = yue | ||
| 4933 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4934 | ``` | ||
| 4935 | |||
| 4936 | </YueDisplay> | ||
| 4937 | |||
| 4938 | Benannte Elemente aus dem Modul exportieren, ohne lokale Variablen zu erstellen. | ||
| 4939 | |||
| 4940 | ```yuescript | ||
| 4941 | export.itemA = tb | ||
| 4942 | export.<index> = items | ||
| 4943 | export["a-b-c"] = 123 | ||
| 4944 | ``` | ||
| 4945 | |||
| 4946 | <YueDisplay> | ||
| 4947 | |||
| 4948 | ```yue | ||
| 4949 | export.itemA = tb | ||
| 4950 | export.<index> = items | ||
| 4951 | export["a-b-c"] = 123 | ||
| 4952 | ``` | ||
| 4953 | |||
| 4954 | </YueDisplay> | ||
| 4955 | |||
| 4956 | ### Unbenannter Export | ||
| 4957 | |||
| 4958 | Unbenannter Export fügt das Ziel-Element in den Array-Teil der exportierten Tabelle ein. | ||
| 4959 | |||
| 4960 | ```yuescript | ||
| 4961 | d, e, f = 3, 2, 1 | ||
| 4962 | export d, e, f | ||
| 4963 | |||
| 4964 | export if this | ||
| 4965 | 123 | ||
| 4966 | else | ||
| 4967 | 456 | ||
| 4968 | |||
| 4969 | export with tmp | ||
| 4970 | j = 2000 | ||
| 4971 | ``` | ||
| 4972 | |||
| 4973 | <YueDisplay> | ||
| 4974 | |||
| 4975 | ```yue | ||
| 4976 | d, e, f = 3, 2, 1 | ||
| 4977 | export d, e, f | ||
| 4978 | |||
| 4979 | export if this | ||
| 4980 | 123 | ||
| 4981 | else | ||
| 4982 | 456 | ||
| 4983 | |||
| 4984 | export with tmp | ||
| 4985 | j = 2000 | ||
| 4986 | ``` | ||
| 4987 | |||
| 4988 | </YueDisplay> | ||
| 4989 | |||
| 4990 | ### Default-Export | ||
| 4991 | |||
| 4992 | Mit dem Schlüsselwort **default** in einer `export`-Anweisung wird die exportierte Tabelle durch ein beliebiges Objekt ersetzt. | ||
| 4993 | |||
| 4994 | ```yuescript | ||
| 4995 | export default -> | ||
| 4996 | print "hallo" | ||
| 4997 | 123 | ||
| 4998 | ``` | ||
| 4999 | |||
| 5000 | <YueDisplay> | ||
| 5001 | |||
| 5002 | ```yue | ||
| 5003 | export default -> | ||
| 5004 | print "hallo" | ||
| 5005 | 123 | ||
| 5006 | ``` | ||
| 5007 | |||
| 5008 | </YueDisplay> | ||
| 5009 | |||
| 5010 | # Lizenz: MIT | ||
| 5011 | |||
| 5012 | Hinweis: Die MIT-Lizenz ist unten im englischen Originaltext wiedergegeben. | ||
| 5013 | |||
| 5014 | Urheberrecht (c) 2017-2026 Li Jin <dragon-fly@qq.com> | ||
| 5015 | |||
| 5016 | Hiermit wird unentgeltlich jeder Person, die eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (die "Software") erhält, die Erlaubnis erteilt, uneingeschränkt mit der Software zu verfahren, einschließlich und ohne Beschränkung der Rechte, die Software zu benutzen, zu kopieren, zu verändern, zusammenzuführen, zu veröffentlichen, zu verbreiten, zu unterlizenzieren und/oder zu verkaufen, sowie Personen, denen die Software zur Verfügung gestellt wird, dies ebenfalls zu gestatten, unter den folgenden Bedingungen: | ||
| 5017 | |||
| 5018 | Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein. | ||
| 5019 | |||
| 5020 | DIE SOFTWARE WIRD OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GARANTIE ZUR VERFÜGUNG GESTELLT, EINSCHLIESSLICH DER GARANTIEN DER MARKTGÄNGIGKEIT, DER EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND DER NICHTVERLETZUNG. IN KEINEM FALL SIND DIE AUTOREN ODER URHEBERRECHTSINHABER FÜR ANSPRÜCHE, SCHÄDEN ODER SONSTIGE HAFTUNGEN VERANTWORTLICH, SEI ES AUS EINEM VERTRAG, EINER UNERLAUBTEN HANDLUNG ODER ANDERWEITIG, DIE SICH AUS DER SOFTWARE ODER DER BENUTZUNG DER SOFTWARE ODER ANDEREN GESCHÄFTEN MIT DER SOFTWARE ERGEBEN ODER DAMIT IN ZUSAMMENHANG STEHEN. | ||
| 5021 | |||
| 5022 | # Die YueScript-Bibliothek | ||
| 5023 | |||
| 5024 | Zugriff in Lua über `local yue = require("yue")`. | ||
| 5025 | |||
| 5026 | ## yue | ||
| 5027 | |||
| 5028 | **Beschreibung:** | ||
| 5029 | |||
| 5030 | Die YueScript-Sprachbibliothek. | ||
| 5031 | |||
| 5032 | ### version | ||
| 5033 | |||
| 5034 | **Typ:** Feld. | ||
| 5035 | |||
| 5036 | **Beschreibung:** | ||
| 5037 | |||
| 5038 | Die YueScript-Version. | ||
| 5039 | |||
| 5040 | **Signatur:** | ||
| 5041 | |||
| 5042 | ```lua | ||
| 5043 | version: string | ||
| 5044 | ``` | ||
| 5045 | |||
| 5046 | ### dirsep | ||
| 5047 | |||
| 5048 | **Typ:** Feld. | ||
| 5049 | |||
| 5050 | **Beschreibung:** | ||
| 5051 | |||
| 5052 | Der Dateitrennzeichen-String der aktuellen Plattform. | ||
| 5053 | |||
| 5054 | **Signatur:** | ||
| 5055 | |||
| 5056 | ```lua | ||
| 5057 | dirsep: string | ||
| 5058 | ``` | ||
| 5059 | |||
| 5060 | ### yue_compiled | ||
| 5061 | |||
| 5062 | **Typ:** Feld. | ||
| 5063 | |||
| 5064 | **Beschreibung:** | ||
| 5065 | |||
| 5066 | Der Cache für kompilierten Modulcode. | ||
| 5067 | |||
| 5068 | **Signatur:** | ||
| 5069 | |||
| 5070 | ```lua | ||
| 5071 | yue_compiled: {string: string} | ||
| 5072 | ``` | ||
| 5073 | |||
| 5074 | ### to_lua | ||
| 5075 | |||
| 5076 | **Typ:** Funktion. | ||
| 5077 | |||
| 5078 | **Beschreibung:** | ||
| 5079 | |||
| 5080 | Die YueScript-Compilerfunktion. Sie kompiliert YueScript-Code zu Lua-Code. | ||
| 5081 | |||
| 5082 | **Signatur:** | ||
| 5083 | |||
| 5084 | ```lua | ||
| 5085 | to_lua: function(code: string, config?: Config): | ||
| 5086 | --[[codes]] string | nil, | ||
| 5087 | --[[error]] string | nil, | ||
| 5088 | --[[globals]] {{string, integer, integer}} | nil | ||
| 5089 | ``` | ||
| 5090 | |||
| 5091 | **Parameter:** | ||
| 5092 | |||
| 5093 | | Parameter | Typ | Beschreibung | | ||
| 5094 | | --------- | ------ | --------------------------------- | | ||
| 5095 | | code | string | Der YueScript-Code. | | ||
| 5096 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5097 | |||
| 5098 | **Rückgabe:** | ||
| 5099 | |||
| 5100 | | Rückgabetyp | Beschreibung | | ||
| 5101 | | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | ||
| 5102 | | string \| nil | Der kompilierte Lua-Code oder `nil`, falls die Kompilierung fehlgeschlagen ist. | | ||
| 5103 | | string \| nil | Die Fehlermeldung oder `nil`, falls die Kompilierung erfolgreich war. | | ||
| 5104 | | {{string, integer, integer}} \| nil | Die globalen Variablen im Code (mit Name, Zeile und Spalte) oder `nil`, wenn die Compiler-Option `lint_global` false ist. | | ||
| 5105 | |||
| 5106 | ### file_exist | ||
| 5107 | |||
| 5108 | **Typ:** Funktion. | ||
| 5109 | |||
| 5110 | **Beschreibung:** | ||
| 5111 | |||
| 5112 | Prüft, ob eine Quelldatei existiert. Kann überschrieben werden, um das Verhalten anzupassen. | ||
| 5113 | |||
| 5114 | **Signatur:** | ||
| 5115 | |||
| 5116 | ```lua | ||
| 5117 | file_exist: function(filename: string): boolean | ||
| 5118 | ``` | ||
| 5119 | |||
| 5120 | **Parameter:** | ||
| 5121 | |||
| 5122 | | Parameter | Typ | Beschreibung | | ||
| 5123 | | --------- | ------ | -------------- | | ||
| 5124 | | filename | string | Der Dateiname. | | ||
| 5125 | |||
| 5126 | **Rückgabe:** | ||
| 5127 | |||
| 5128 | | Rückgabetyp | Beschreibung | | ||
| 5129 | | ----------- | ----------------------- | | ||
| 5130 | | boolean | Ob die Datei existiert. | | ||
| 5131 | |||
| 5132 | ### read_file | ||
| 5133 | |||
| 5134 | **Typ:** Funktion. | ||
| 5135 | |||
| 5136 | **Beschreibung:** | ||
| 5137 | |||
| 5138 | Liest eine Quelldatei. Kann überschrieben werden, um das Verhalten anzupassen. | ||
| 5139 | |||
| 5140 | **Signatur:** | ||
| 5141 | |||
| 5142 | ```lua | ||
| 5143 | read_file: function(filename: string): string | ||
| 5144 | ``` | ||
| 5145 | |||
| 5146 | **Parameter:** | ||
| 5147 | |||
| 5148 | | Parameter | Typ | Beschreibung | | ||
| 5149 | | --------- | ------ | -------------- | | ||
| 5150 | | filename | string | Der Dateiname. | | ||
| 5151 | |||
| 5152 | **Rückgabe:** | ||
| 5153 | |||
| 5154 | | Rückgabetyp | Beschreibung | | ||
| 5155 | | ----------- | ---------------- | | ||
| 5156 | | string | Der Dateiinhalt. | | ||
| 5157 | |||
| 5158 | ### insert_loader | ||
| 5159 | |||
| 5160 | **Typ:** Funktion. | ||
| 5161 | |||
| 5162 | **Beschreibung:** | ||
| 5163 | |||
| 5164 | Fügt den YueScript-Loader in die Package-Loader (Searcher) ein. | ||
| 5165 | |||
| 5166 | **Signatur:** | ||
| 5167 | |||
| 5168 | ```lua | ||
| 5169 | insert_loader: function(pos?: integer): boolean | ||
| 5170 | ``` | ||
| 5171 | |||
| 5172 | **Parameter:** | ||
| 5173 | |||
| 5174 | | Parameter | Typ | Beschreibung | | ||
| 5175 | | --------- | ------- | ---------------------------------------------------------------------- | | ||
| 5176 | | pos | integer | [Optional] Position, an der der Loader eingefügt wird. Standard ist 3. | | ||
| 5177 | |||
| 5178 | **Rückgabe:** | ||
| 5179 | |||
| 5180 | | Rückgabetyp | Beschreibung | | ||
| 5181 | | ----------- | ------------------------------------------------------------------------------------ | | ||
| 5182 | | boolean | Ob der Loader erfolgreich eingefügt wurde. Scheitert, wenn er bereits eingefügt ist. | | ||
| 5183 | |||
| 5184 | ### remove_loader | ||
| 5185 | |||
| 5186 | **Typ:** Funktion. | ||
| 5187 | |||
| 5188 | **Beschreibung:** | ||
| 5189 | |||
| 5190 | Entfernt den YueScript-Loader aus den Package-Loadern (Searchern). | ||
| 5191 | |||
| 5192 | **Signatur:** | ||
| 5193 | |||
| 5194 | ```lua | ||
| 5195 | remove_loader: function(): boolean | ||
| 5196 | ``` | ||
| 5197 | |||
| 5198 | **Rückgabe:** | ||
| 5199 | |||
| 5200 | | Rückgabetyp | Beschreibung | | ||
| 5201 | | ----------- | --------------------------------------------------------------------------------- | | ||
| 5202 | | boolean | Ob der Loader erfolgreich entfernt wurde. Scheitert, wenn er nicht eingefügt ist. | | ||
| 5203 | |||
| 5204 | ### loadstring | ||
| 5205 | |||
| 5206 | **Typ:** Funktion. | ||
| 5207 | |||
| 5208 | **Beschreibung:** | ||
| 5209 | |||
| 5210 | Lädt YueScript-Code aus einem String in eine Funktion. | ||
| 5211 | |||
| 5212 | **Signatur:** | ||
| 5213 | |||
| 5214 | ```lua | ||
| 5215 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | ||
| 5216 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5217 | --[[error]] string | nil | ||
| 5218 | ``` | ||
| 5219 | |||
| 5220 | **Parameter:** | ||
| 5221 | |||
| 5222 | | Parameter | Typ | Beschreibung | | ||
| 5223 | | --------- | ------ | --------------------------------- | | ||
| 5224 | | input | string | Der YueScript-Code. | | ||
| 5225 | | chunkname | string | Der Name des Code-Chunks. | | ||
| 5226 | | env | table | Die Environment-Tabelle. | | ||
| 5227 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5228 | |||
| 5229 | **Rückgabe:** | ||
| 5230 | |||
| 5231 | | Rückgabetyp | Beschreibung | | ||
| 5232 | | --------------- | --------------------------------------------------------------------- | | ||
| 5233 | | function \| nil | Die geladene Funktion oder `nil`, falls das Laden fehlgeschlagen ist. | | ||
| 5234 | | string \| nil | Die Fehlermeldung oder `nil`, falls das Laden erfolgreich war. | | ||
| 5235 | |||
| 5236 | ### loadstring | ||
| 5237 | |||
| 5238 | **Typ:** Funktion. | ||
| 5239 | |||
| 5240 | **Beschreibung:** | ||
| 5241 | |||
| 5242 | Lädt YueScript-Code aus einem String in eine Funktion. | ||
| 5243 | |||
| 5244 | **Signatur:** | ||
| 5245 | |||
| 5246 | ```lua | ||
| 5247 | loadstring: function(input: string, chunkname: string, config?: Config): | ||
| 5248 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5249 | --[[error]] string | nil | ||
| 5250 | ``` | ||
| 5251 | |||
| 5252 | **Parameter:** | ||
| 5253 | |||
| 5254 | | Parameter | Typ | Beschreibung | | ||
| 5255 | | --------- | ------ | --------------------------------- | | ||
| 5256 | | input | string | Der YueScript-Code. | | ||
| 5257 | | chunkname | string | Der Name des Code-Chunks. | | ||
| 5258 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5259 | |||
| 5260 | **Rückgabe:** | ||
| 5261 | |||
| 5262 | | Rückgabetyp | Beschreibung | | ||
| 5263 | | --------------- | --------------------------------------------------------------------- | | ||
| 5264 | | function \| nil | Die geladene Funktion oder `nil`, falls das Laden fehlgeschlagen ist. | | ||
| 5265 | | string \| nil | Die Fehlermeldung oder `nil`, falls das Laden erfolgreich war. | | ||
| 5266 | |||
| 5267 | ### loadstring | ||
| 5268 | |||
| 5269 | **Typ:** Funktion. | ||
| 5270 | |||
| 5271 | **Beschreibung:** | ||
| 5272 | |||
| 5273 | Lädt YueScript-Code aus einem String in eine Funktion. | ||
| 5274 | |||
| 5275 | **Signatur:** | ||
| 5276 | |||
| 5277 | ```lua | ||
| 5278 | loadstring: function(input: string, config?: Config): | ||
| 5279 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5280 | --[[error]] string | nil | ||
| 5281 | ``` | ||
| 5282 | |||
| 5283 | **Parameter:** | ||
| 5284 | |||
| 5285 | | Parameter | Typ | Beschreibung | | ||
| 5286 | | --------- | ------ | --------------------------------- | | ||
| 5287 | | input | string | Der YueScript-Code. | | ||
| 5288 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5289 | |||
| 5290 | **Rückgabe:** | ||
| 5291 | |||
| 5292 | | Rückgabetyp | Beschreibung | | ||
| 5293 | | --------------- | --------------------------------------------------------------------- | | ||
| 5294 | | function \| nil | Die geladene Funktion oder `nil`, falls das Laden fehlgeschlagen ist. | | ||
| 5295 | | string \| nil | Die Fehlermeldung oder `nil`, falls das Laden erfolgreich war. | | ||
| 5296 | |||
| 5297 | ### loadfile | ||
| 5298 | |||
| 5299 | **Typ:** Funktion. | ||
| 5300 | |||
| 5301 | **Beschreibung:** | ||
| 5302 | |||
| 5303 | Lädt YueScript-Code aus einer Datei in eine Funktion. | ||
| 5304 | |||
| 5305 | **Signatur:** | ||
| 5306 | |||
| 5307 | ```lua | ||
| 5308 | loadfile: function(filename: string, env: table, config?: Config): | ||
| 5309 | nil | function(...: any): (any...), | ||
| 5310 | string | nil | ||
| 5311 | ``` | ||
| 5312 | |||
| 5313 | **Parameter:** | ||
| 5314 | |||
| 5315 | | Parameter | Typ | Beschreibung | | ||
| 5316 | | --------- | ------ | --------------------------------- | | ||
| 5317 | | filename | string | Der Dateiname. | | ||
| 5318 | | env | table | Die Environment-Tabelle. | | ||
| 5319 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5320 | |||
| 5321 | **Rückgabe:** | ||
| 5322 | |||
| 5323 | | Rückgabetyp | Beschreibung | | ||
| 5324 | | --------------- | --------------------------------------------------------------------- | | ||
| 5325 | | function \| nil | Die geladene Funktion oder `nil`, falls das Laden fehlgeschlagen ist. | | ||
| 5326 | | string \| nil | Die Fehlermeldung oder `nil`, falls das Laden erfolgreich war. | | ||
| 5327 | |||
| 5328 | ### loadfile | ||
| 5329 | |||
| 5330 | **Typ:** Funktion. | ||
| 5331 | |||
| 5332 | **Beschreibung:** | ||
| 5333 | |||
| 5334 | Lädt YueScript-Code aus einer Datei in eine Funktion. | ||
| 5335 | |||
| 5336 | **Signatur:** | ||
| 5337 | |||
| 5338 | ```lua | ||
| 5339 | loadfile: function(filename: string, config?: Config): | ||
| 5340 | nil | function(...: any): (any...), | ||
| 5341 | string | nil | ||
| 5342 | ``` | ||
| 5343 | |||
| 5344 | **Parameter:** | ||
| 5345 | |||
| 5346 | | Parameter | Typ | Beschreibung | | ||
| 5347 | | --------- | ------ | --------------------------------- | | ||
| 5348 | | filename | string | Der Dateiname. | | ||
| 5349 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5350 | |||
| 5351 | **Rückgabe:** | ||
| 5352 | |||
| 5353 | | Rückgabetyp | Beschreibung | | ||
| 5354 | | --------------- | --------------------------------------------------------------------- | | ||
| 5355 | | function \| nil | Die geladene Funktion oder `nil`, falls das Laden fehlgeschlagen ist. | | ||
| 5356 | | string \| nil | Die Fehlermeldung oder `nil`, falls das Laden erfolgreich war. | | ||
| 5357 | |||
| 5358 | ### dofile | ||
| 5359 | |||
| 5360 | **Typ:** Funktion. | ||
| 5361 | |||
| 5362 | **Beschreibung:** | ||
| 5363 | |||
| 5364 | Lädt YueScript-Code aus einer Datei in eine Funktion und führt sie aus. | ||
| 5365 | |||
| 5366 | **Signatur:** | ||
| 5367 | |||
| 5368 | ```lua | ||
| 5369 | dofile: function(filename: string, env: table, config?: Config): any... | ||
| 5370 | ``` | ||
| 5371 | |||
| 5372 | **Parameter:** | ||
| 5373 | |||
| 5374 | | Parameter | Typ | Beschreibung | | ||
| 5375 | | --------- | ------ | --------------------------------- | | ||
| 5376 | | filename | string | Der Dateiname. | | ||
| 5377 | | env | table | Die Environment-Tabelle. | | ||
| 5378 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5379 | |||
| 5380 | **Rückgabe:** | ||
| 5381 | |||
| 5382 | | Rückgabetyp | Beschreibung | | ||
| 5383 | | ----------- | ----------------------------------------- | | ||
| 5384 | | any... | Die Rückgabewerte der geladenen Funktion. | | ||
| 5385 | |||
| 5386 | ### dofile | ||
| 5387 | |||
| 5388 | **Typ:** Funktion. | ||
| 5389 | |||
| 5390 | **Beschreibung:** | ||
| 5391 | |||
| 5392 | Lädt YueScript-Code aus einer Datei in eine Funktion und führt sie aus. | ||
| 5393 | |||
| 5394 | **Signatur:** | ||
| 5395 | |||
| 5396 | ```lua | ||
| 5397 | dofile: function(filename: string, config?: Config): any... | ||
| 5398 | ``` | ||
| 5399 | |||
| 5400 | **Parameter:** | ||
| 5401 | |||
| 5402 | | Parameter | Typ | Beschreibung | | ||
| 5403 | | --------- | ------ | --------------------------------- | | ||
| 5404 | | filename | string | Der Dateiname. | | ||
| 5405 | | config | Config | [Optional] Die Compiler-Optionen. | | ||
| 5406 | |||
| 5407 | **Rückgabe:** | ||
| 5408 | |||
| 5409 | | Rückgabetyp | Beschreibung | | ||
| 5410 | | ----------- | ----------------------------------------- | | ||
| 5411 | | any... | Die Rückgabewerte der geladenen Funktion. | | ||
| 5412 | |||
| 5413 | ### find_modulepath | ||
| 5414 | |||
| 5415 | **Typ:** Funktion. | ||
| 5416 | |||
| 5417 | **Beschreibung:** | ||
| 5418 | |||
| 5419 | Löst den YueScript-Modulnamen in einen Dateipfad auf. | ||
| 5420 | |||
| 5421 | **Signatur:** | ||
| 5422 | |||
| 5423 | ```lua | ||
| 5424 | find_modulepath: function(name: string): string | ||
| 5425 | ``` | ||
| 5426 | |||
| 5427 | **Parameter:** | ||
| 5428 | |||
| 5429 | | Parameter | Typ | Beschreibung | | ||
| 5430 | | --------- | ------ | -------------- | | ||
| 5431 | | name | string | Der Modulname. | | ||
| 5432 | |||
| 5433 | **Rückgabe:** | ||
| 5434 | |||
| 5435 | | Rückgabetyp | Beschreibung | | ||
| 5436 | | ----------- | -------------- | | ||
| 5437 | | string | Der Dateipfad. | | ||
| 5438 | |||
| 5439 | ### pcall | ||
| 5440 | |||
| 5441 | **Typ:** Funktion. | ||
| 5442 | |||
| 5443 | **Beschreibung:** | ||
| 5444 | |||
| 5445 | Ruft eine Funktion im geschützten Modus auf. | ||
| 5446 | Fängt Fehler ab und gibt einen Statuscode sowie Ergebnisse oder ein Fehlerobjekt zurück. | ||
| 5447 | Schreibt die Fehlerzeilennummer bei Fehlern auf die ursprüngliche Zeilennummer im YueScript-Code um. | ||
| 5448 | |||
| 5449 | **Signatur:** | ||
| 5450 | |||
| 5451 | ```lua | ||
| 5452 | pcall: function(f: function, ...: any): boolean, any... | ||
| 5453 | ``` | ||
| 5454 | |||
| 5455 | **Parameter:** | ||
| 5456 | |||
| 5457 | | Parameter | Typ | Beschreibung | | ||
| 5458 | | --------- | -------- | --------------------------- | | ||
| 5459 | | f | function | Die aufzurufende Funktion. | | ||
| 5460 | | ... | any | Argumente für die Funktion. | | ||
| 5461 | |||
| 5462 | **Rückgabe:** | ||
| 5463 | |||
| 5464 | | Rückgabetyp | Beschreibung | | ||
| 5465 | | ------------ | ---------------------------------------------------- | | ||
| 5466 | | boolean, ... | Statuscode und Funktionsresultate oder Fehlerobjekt. | | ||
| 5467 | |||
| 5468 | ### require | ||
| 5469 | |||
| 5470 | **Typ:** Funktion. | ||
| 5471 | |||
| 5472 | **Beschreibung:** | ||
| 5473 | |||
| 5474 | Lädt ein Modul (Lua oder YueScript). | ||
| 5475 | Schreibt die Fehlerzeilennummer auf die ursprüngliche Zeilennummer im YueScript-Code um, wenn das Modul ein YueScript-Modul ist und das Laden fehlschlägt. | ||
| 5476 | |||
| 5477 | **Signatur:** | ||
| 5478 | |||
| 5479 | ```lua | ||
| 5480 | require: function(name: string): any... | ||
| 5481 | ``` | ||
| 5482 | |||
| 5483 | **Parameter:** | ||
| 5484 | |||
| 5485 | | Parameter | Typ | Beschreibung | | ||
| 5486 | | --------- | ------ | -------------------------------- | | ||
| 5487 | | modname | string | Der Name des zu ladenden Moduls. | | ||
| 5488 | |||
| 5489 | **Rückgabe:** | ||
| 5490 | |||
| 5491 | | Rückgabetyp | Beschreibung | | ||
| 5492 | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| 5493 | | any | Der Wert in `package.loaded[modname]`, falls das Modul bereits geladen ist. Andernfalls wird ein Loader gesucht und der finale Wert von `package.loaded[modname]` sowie Loader-Daten als zweites Ergebnis zurückgegeben. | | ||
| 5494 | |||
| 5495 | ### p | ||
| 5496 | |||
| 5497 | **Typ:** Funktion. | ||
| 5498 | |||
| 5499 | **Beschreibung:** | ||
| 5500 | |||
| 5501 | Inspiziert die Struktur der übergebenen Werte und gibt String-Repräsentationen aus. | ||
| 5502 | |||
| 5503 | **Signatur:** | ||
| 5504 | |||
| 5505 | ```lua | ||
| 5506 | p: function(...: any) | ||
| 5507 | ``` | ||
| 5508 | |||
| 5509 | **Parameter:** | ||
| 5510 | |||
| 5511 | | Parameter | Typ | Beschreibung | | ||
| 5512 | | --------- | --- | ---------------------------- | | ||
| 5513 | | ... | any | Die zu inspizierenden Werte. | | ||
| 5514 | |||
| 5515 | ### options | ||
| 5516 | |||
| 5517 | **Typ:** Feld. | ||
| 5518 | |||
| 5519 | **Beschreibung:** | ||
| 5520 | |||
| 5521 | Die aktuellen Compiler-Optionen. | ||
| 5522 | |||
| 5523 | **Signatur:** | ||
| 5524 | |||
| 5525 | ```lua | ||
| 5526 | options: Config.Options | ||
| 5527 | ``` | ||
| 5528 | |||
| 5529 | ### traceback | ||
| 5530 | |||
| 5531 | **Typ:** Funktion. | ||
| 5532 | |||
| 5533 | **Beschreibung:** | ||
| 5534 | |||
| 5535 | Die Traceback-Funktion, die Stacktrace-Zeilennummern auf die ursprünglichen Zeilennummern im YueScript-Code umschreibt. | ||
| 5536 | |||
| 5537 | **Signatur:** | ||
| 5538 | |||
| 5539 | ```lua | ||
| 5540 | traceback: function(message: string): string | ||
| 5541 | ``` | ||
| 5542 | |||
| 5543 | **Parameter:** | ||
| 5544 | |||
| 5545 | | Parameter | Typ | Beschreibung | | ||
| 5546 | | --------- | ------ | ------------------------ | | ||
| 5547 | | message | string | Die Traceback-Nachricht. | | ||
| 5548 | |||
| 5549 | **Rückgabe:** | ||
| 5550 | |||
| 5551 | | Rückgabetyp | Beschreibung | | ||
| 5552 | | ----------- | --------------------------------------- | | ||
| 5553 | | string | Die umgeschriebene Traceback-Nachricht. | | ||
| 5554 | |||
| 5555 | ### is_ast | ||
| 5556 | |||
| 5557 | **Typ:** Funktion. | ||
| 5558 | |||
| 5559 | **Beschreibung:** | ||
| 5560 | |||
| 5561 | Prüft, ob der Code dem angegebenen AST entspricht. | ||
| 5562 | |||
| 5563 | **Signatur:** | ||
| 5564 | |||
| 5565 | ```lua | ||
| 5566 | is_ast: function(astName: string, code: string): boolean | ||
| 5567 | ``` | ||
| 5568 | |||
| 5569 | **Parameter:** | ||
| 5570 | |||
| 5571 | | Parameter | Typ | Beschreibung | | ||
| 5572 | | --------- | ------ | ------------- | | ||
| 5573 | | astName | string | Der AST-Name. | | ||
| 5574 | | code | string | Der Code. | | ||
| 5575 | |||
| 5576 | **Rückgabe:** | ||
| 5577 | |||
| 5578 | | Rückgabetyp | Beschreibung | | ||
| 5579 | | ----------- | ------------------------------- | | ||
| 5580 | | boolean | Ob der Code dem AST entspricht. | | ||
| 5581 | |||
| 5582 | ### AST | ||
| 5583 | |||
| 5584 | **Typ:** Feld. | ||
| 5585 | |||
| 5586 | **Beschreibung:** | ||
| 5587 | |||
| 5588 | Die AST-Typdefinition mit Name, Zeile, Spalte und Unterknoten. | ||
| 5589 | |||
| 5590 | **Signatur:** | ||
| 5591 | |||
| 5592 | ```lua | ||
| 5593 | type AST = {string, integer, integer, any} | ||
| 5594 | ``` | ||
| 5595 | |||
| 5596 | ### to_ast | ||
| 5597 | |||
| 5598 | **Typ:** Funktion. | ||
| 5599 | |||
| 5600 | **Beschreibung:** | ||
| 5601 | |||
| 5602 | Konvertiert Code in AST. | ||
| 5603 | |||
| 5604 | **Signatur:** | ||
| 5605 | |||
| 5606 | ```lua | ||
| 5607 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): | ||
| 5608 | --[[AST]] AST | nil, | ||
| 5609 | --[[error]] nil | string | ||
| 5610 | ``` | ||
| 5611 | |||
| 5612 | **Parameter:** | ||
| 5613 | |||
| 5614 | | Parameter | Typ | Beschreibung | | ||
| 5615 | | -------------- | ------- | -------------------------------------------------------------------------------------------- | | ||
| 5616 | | code | string | Der Code. | | ||
| 5617 | | flattenLevel | integer | [Optional] Der Flatten-Level. Höher bedeutet mehr Flattening. Standard ist 0. Maximum ist 2. | | ||
| 5618 | | astName | string | [Optional] Der AST-Name. Standard ist "File". | | ||
| 5619 | | reserveComment | boolean | [Optional] Ob die ursprünglichen Kommentare beibehalten werden. Standard ist false. | | ||
| 5620 | |||
| 5621 | **Rückgabe:** | ||
| 5622 | |||
| 5623 | | Rückgabetyp | Beschreibung | | ||
| 5624 | | ------------- | ---------------------------------------------------------------------- | | ||
| 5625 | | AST \| nil | Der AST oder `nil`, falls die Konvertierung fehlgeschlagen ist. | | ||
| 5626 | | string \| nil | Die Fehlermeldung oder `nil`, falls die Konvertierung erfolgreich war. | | ||
| 5627 | |||
| 5628 | ### format | ||
| 5629 | |||
| 5630 | **Typ:** Funktion. | ||
| 5631 | |||
| 5632 | **Beschreibung:** | ||
| 5633 | |||
| 5634 | Formatiert den YueScript-Code. | ||
| 5635 | |||
| 5636 | **Signatur:** | ||
| 5637 | |||
| 5638 | ```lua | ||
| 5639 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 5640 | ``` | ||
| 5641 | |||
| 5642 | **Parameter:** | ||
| 5643 | |||
| 5644 | | Parameter | Typ | Beschreibung | | ||
| 5645 | | -------------- | ------- | ---------------------------------------------------------------------------------- | | ||
| 5646 | | code | string | Der Code. | | ||
| 5647 | | tabSize | integer | [Optional] Die Tab-Größe. Standard ist 4. | | ||
| 5648 | | reserveComment | boolean | [Optional] Ob die ursprünglichen Kommentare beibehalten werden. Standard ist true. | | ||
| 5649 | |||
| 5650 | **Rückgabe:** | ||
| 5651 | |||
| 5652 | | Rückgabetyp | Beschreibung | | ||
| 5653 | | ----------- | --------------------- | | ||
| 5654 | | string | Der formatierte Code. | | ||
| 5655 | |||
| 5656 | ### \_\_call | ||
| 5657 | |||
| 5658 | **Typ:** Metamethod. | ||
| 5659 | |||
| 5660 | **Beschreibung:** | ||
| 5661 | |||
| 5662 | Required das YueScript-Modul. | ||
| 5663 | Schreibt die Fehlerzeilennummer bei Ladefehlern auf die ursprüngliche Zeilennummer im YueScript-Code um. | ||
| 5664 | |||
| 5665 | **Signatur:** | ||
| 5666 | |||
| 5667 | ```lua | ||
| 5668 | metamethod __call: function(self: yue, module: string): any... | ||
| 5669 | ``` | ||
| 5670 | |||
| 5671 | **Parameter:** | ||
| 5672 | |||
| 5673 | | Parameter | Typ | Beschreibung | | ||
| 5674 | | --------- | ------ | -------------- | | ||
| 5675 | | module | string | Der Modulname. | | ||
| 5676 | |||
| 5677 | **Rückgabe:** | ||
| 5678 | |||
| 5679 | | Rückgabetyp | Beschreibung | | ||
| 5680 | | ----------- | -------------- | | ||
| 5681 | | any | Der Modulwert. | | ||
| 5682 | |||
| 5683 | ## Config | ||
| 5684 | |||
| 5685 | **Beschreibung:** | ||
| 5686 | |||
| 5687 | Die Compiler-Optionen. | ||
| 5688 | |||
| 5689 | ### lint_global | ||
| 5690 | |||
| 5691 | **Typ:** Feld. | ||
| 5692 | |||
| 5693 | **Beschreibung:** | ||
| 5694 | |||
| 5695 | Ob der Compiler die globalen Variablen im Code sammeln soll. | ||
| 5696 | |||
| 5697 | **Signatur:** | ||
| 5698 | |||
| 5699 | ```lua | ||
| 5700 | lint_global: boolean | ||
| 5701 | ``` | ||
| 5702 | |||
| 5703 | ### implicit_return_root | ||
| 5704 | |||
| 5705 | **Typ:** Feld. | ||
| 5706 | |||
| 5707 | **Beschreibung:** | ||
| 5708 | |||
| 5709 | Ob der Compiler für den Root-Codeblock ein implizites Return verwenden soll. | ||
| 5710 | |||
| 5711 | **Signatur:** | ||
| 5712 | |||
| 5713 | ```lua | ||
| 5714 | implicit_return_root: boolean | ||
| 5715 | ``` | ||
| 5716 | |||
| 5717 | ### reserve_line_number | ||
| 5718 | |||
| 5719 | **Typ:** Feld. | ||
| 5720 | |||
| 5721 | **Beschreibung:** | ||
| 5722 | |||
| 5723 | Ob der Compiler die ursprüngliche Zeilennummer im kompilierten Code beibehalten soll. | ||
| 5724 | |||
| 5725 | **Signatur:** | ||
| 5726 | |||
| 5727 | ```lua | ||
| 5728 | reserve_line_number: boolean | ||
| 5729 | ``` | ||
| 5730 | |||
| 5731 | ### reserve_comment | ||
| 5732 | |||
| 5733 | **Typ:** Feld. | ||
| 5734 | |||
| 5735 | **Beschreibung:** | ||
| 5736 | |||
| 5737 | Ob der Compiler die ursprünglichen Kommentare im kompilierten Code beibehalten soll. | ||
| 5738 | |||
| 5739 | **Signatur:** | ||
| 5740 | |||
| 5741 | ```lua | ||
| 5742 | reserve_comment: boolean | ||
| 5743 | ``` | ||
| 5744 | |||
| 5745 | ### space_over_tab | ||
| 5746 | |||
| 5747 | **Typ:** Feld. | ||
| 5748 | |||
| 5749 | **Beschreibung:** | ||
| 5750 | |||
| 5751 | Ob der Compiler statt Tabzeichen Leerzeichen verwenden soll. | ||
| 5752 | |||
| 5753 | **Signatur:** | ||
| 5754 | |||
| 5755 | ```lua | ||
| 5756 | space_over_tab: boolean | ||
| 5757 | ``` | ||
| 5758 | |||
| 5759 | ### same_module | ||
| 5760 | |||
| 5761 | **Typ:** Feld. | ||
| 5762 | |||
| 5763 | **Beschreibung:** | ||
| 5764 | |||
| 5765 | Ob der Compiler den zu kompilierenden Code als dasselbe aktuell kompilierte Modul behandeln soll. Nur für internen Gebrauch. | ||
| 5766 | |||
| 5767 | **Signatur:** | ||
| 5768 | |||
| 5769 | ```lua | ||
| 5770 | same_module: boolean | ||
| 5771 | ``` | ||
| 5772 | |||
| 5773 | ### line_offset | ||
| 5774 | |||
| 5775 | **Typ:** Feld. | ||
| 5776 | |||
| 5777 | **Beschreibung:** | ||
| 5778 | |||
| 5779 | Ob die Compiler-Fehlermeldung einen Zeilennummern-Offset enthalten soll. Nur für internen Gebrauch. | ||
| 5780 | |||
| 5781 | **Signatur:** | ||
| 5782 | |||
| 5783 | ```lua | ||
| 5784 | line_offset: integer | ||
| 5785 | ``` | ||
| 5786 | |||
| 5787 | ### yue.Config.LuaTarget | ||
| 5788 | |||
| 5789 | **Typ:** Enumeration. | ||
| 5790 | |||
| 5791 | **Beschreibung:** | ||
| 5792 | |||
| 5793 | Die Ziel-Lua-Version. | ||
| 5794 | |||
| 5795 | **Signatur:** | ||
| 5796 | |||
| 5797 | ```lua | ||
| 5798 | enum LuaTarget | ||
| 5799 | "5.1" | ||
| 5800 | "5.2" | ||
| 5801 | "5.3" | ||
| 5802 | "5.4" | ||
| 5803 | "5.5" | ||
| 5804 | end | ||
| 5805 | ``` | ||
| 5806 | |||
| 5807 | ### options | ||
| 5808 | |||
| 5809 | **Typ:** Feld. | ||
| 5810 | |||
| 5811 | **Beschreibung:** | ||
| 5812 | |||
| 5813 | Zusätzliche Optionen für die Kompilierung. | ||
| 5814 | |||
| 5815 | **Signatur:** | ||
| 5816 | |||
| 5817 | ```lua | ||
| 5818 | options: Options | ||
| 5819 | ``` | ||
| 5820 | |||
| 5821 | ## Options | ||
| 5822 | |||
| 5823 | **Beschreibung:** | ||
| 5824 | |||
| 5825 | Zusätzliche Compiler-Optionen. | ||
| 5826 | |||
| 5827 | ### target | ||
| 5828 | |||
| 5829 | **Typ:** Feld. | ||
| 5830 | |||
| 5831 | **Beschreibung:** | ||
| 5832 | |||
| 5833 | Die Ziel-Lua-Version für die Kompilierung. | ||
| 5834 | |||
| 5835 | **Signatur:** | ||
| 5836 | |||
| 5837 | ```lua | ||
| 5838 | target: LuaTarget | ||
| 5839 | ``` | ||
| 5840 | |||
| 5841 | ### path | ||
| 5842 | |||
| 5843 | **Typ:** Feld. | ||
| 5844 | |||
| 5845 | **Beschreibung:** | ||
| 5846 | |||
| 5847 | Zusätzlicher Modul-Suchpfad. | ||
| 5848 | |||
| 5849 | **Signatur:** | ||
| 5850 | |||
| 5851 | ```lua | ||
| 5852 | path: string | ||
| 5853 | ``` | ||
| 5854 | |||
| 5855 | ### dump_locals | ||
| 5856 | |||
| 5857 | **Typ:** Feld. | ||
| 5858 | |||
| 5859 | **Beschreibung:** | ||
| 5860 | |||
| 5861 | Ob lokale Variablen in Traceback-Fehlermeldungen ausgegeben werden sollen. Standard ist false. | ||
| 5862 | |||
| 5863 | **Signatur:** | ||
| 5864 | |||
| 5865 | ```lua | ||
| 5866 | dump_locals: boolean | ||
| 5867 | ``` | ||
| 5868 | |||
| 5869 | ### simplified | ||
| 5870 | |||
| 5871 | **Typ:** Feld. | ||
| 5872 | |||
| 5873 | **Beschreibung:** | ||
| 5874 | |||
| 5875 | Ob Fehlermeldungen vereinfacht werden sollen. Standard ist true. | ||
| 5876 | |||
| 5877 | **Signatur:** | ||
| 5878 | |||
| 5879 | ```lua | ||
| 5880 | simplified: boolean | ||
| 5881 | ``` | ||
diff --git a/doc/yue-en.md b/doc/yue-en.md new file mode 100644 index 0000000..a16060c --- /dev/null +++ b/doc/yue-en.md | |||
| @@ -0,0 +1,5895 @@ | |||
| 1 | --- | ||
| 2 | title: Reference | ||
| 3 | --- | ||
| 4 | |||
| 5 | # YueScript Documentation | ||
| 6 | |||
| 7 | <img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em; padding-bottom: 2em;"/> | ||
| 8 | |||
| 9 | Welcome to the <b>YueScript</b> official documentation!<br/> | ||
| 10 | Here you can find the language features, usage, reference examples and resources.<br/> | ||
| 11 | Please select a chapter from the sidebar to start learning about YueScript. | ||
| 12 | |||
| 13 | # Do | ||
| 14 | |||
| 15 | When used as a statement, do works just like it does in Lua. | ||
| 16 | |||
| 17 | ```yuescript | ||
| 18 | do | ||
| 19 | var = "hello" | ||
| 20 | print var | ||
| 21 | print var -- nil here | ||
| 22 | ``` | ||
| 23 | |||
| 24 | <YueDisplay> | ||
| 25 | |||
| 26 | ```yue | ||
| 27 | do | ||
| 28 | var = "hello" | ||
| 29 | print var | ||
| 30 | print var -- nil here | ||
| 31 | ``` | ||
| 32 | |||
| 33 | </YueDisplay> | ||
| 34 | |||
| 35 | YueScript'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. | ||
| 36 | |||
| 37 | `do` expressions also support using `break` to interrupt control flow and return multiple values early: | ||
| 38 | |||
| 39 | ```yuescript | ||
| 40 | status, value = do | ||
| 41 | n = 12 | ||
| 42 | if n > 10 | ||
| 43 | break "large", n | ||
| 44 | break "small", n | ||
| 45 | ``` | ||
| 46 | |||
| 47 | <YueDisplay> | ||
| 48 | |||
| 49 | ```yue | ||
| 50 | status, value = do | ||
| 51 | n = 12 | ||
| 52 | if n > 10 | ||
| 53 | break "large", n | ||
| 54 | break "small", n | ||
| 55 | ``` | ||
| 56 | |||
| 57 | </YueDisplay> | ||
| 58 | |||
| 59 | ```yuescript | ||
| 60 | counter = do | ||
| 61 | i = 0 | ||
| 62 | -> | ||
| 63 | i += 1 | ||
| 64 | i | ||
| 65 | |||
| 66 | print counter! | ||
| 67 | print counter! | ||
| 68 | ``` | ||
| 69 | |||
| 70 | <YueDisplay> | ||
| 71 | |||
| 72 | ```yue | ||
| 73 | counter = do | ||
| 74 | i = 0 | ||
| 75 | -> | ||
| 76 | i += 1 | ||
| 77 | i | ||
| 78 | |||
| 79 | print counter! | ||
| 80 | print counter! | ||
| 81 | ``` | ||
| 82 | |||
| 83 | </YueDisplay> | ||
| 84 | |||
| 85 | ```yuescript | ||
| 86 | tbl = { | ||
| 87 | key: do | ||
| 88 | print "assigning key!" | ||
| 89 | 1234 | ||
| 90 | } | ||
| 91 | ``` | ||
| 92 | |||
| 93 | <YueDisplay> | ||
| 94 | |||
| 95 | ```yue | ||
| 96 | tbl = { | ||
| 97 | key: do | ||
| 98 | print "assigning key!" | ||
| 99 | 1234 | ||
| 100 | } | ||
| 101 | ``` | ||
| 102 | |||
| 103 | </YueDisplay> | ||
| 104 | |||
| 105 | # Line Decorators | ||
| 106 | |||
| 107 | For convenience, the for loop and if statement can be applied to single statements at the end of the line: | ||
| 108 | |||
| 109 | ```yuescript | ||
| 110 | print "hello world" if name == "Rob" | ||
| 111 | ``` | ||
| 112 | |||
| 113 | <YueDisplay> | ||
| 114 | |||
| 115 | ```yue | ||
| 116 | print "hello world" if name == "Rob" | ||
| 117 | ``` | ||
| 118 | |||
| 119 | </YueDisplay> | ||
| 120 | |||
| 121 | And with basic loops: | ||
| 122 | |||
| 123 | ```yuescript | ||
| 124 | print "item: ", item for item in *items | ||
| 125 | ``` | ||
| 126 | |||
| 127 | <YueDisplay> | ||
| 128 | |||
| 129 | ```yue | ||
| 130 | print "item: ", item for item in *items | ||
| 131 | ``` | ||
| 132 | |||
| 133 | </YueDisplay> | ||
| 134 | |||
| 135 | And with while loops: | ||
| 136 | |||
| 137 | ```yuescript | ||
| 138 | game\update! while game\isRunning! | ||
| 139 | |||
| 140 | reader\parse_line! until reader\eof! | ||
| 141 | ``` | ||
| 142 | |||
| 143 | <YueDisplay> | ||
| 144 | |||
| 145 | ```yue | ||
| 146 | game\update! while game\isRunning! | ||
| 147 | |||
| 148 | reader\parse_line! until reader\eof! | ||
| 149 | ``` | ||
| 150 | |||
| 151 | </YueDisplay> | ||
| 152 | |||
| 153 | # Macro | ||
| 154 | |||
| 155 | ## Common Usage | ||
| 156 | |||
| 157 | Macro function is used for evaluating a string in the compile time and insert the generated codes into final compilation. | ||
| 158 | |||
| 159 | ```yuescript | ||
| 160 | macro PI2 = -> math.pi * 2 | ||
| 161 | area = $PI2 * 5 | ||
| 162 | |||
| 163 | macro HELLO = -> "'hello world'" | ||
| 164 | print $HELLO | ||
| 165 | |||
| 166 | macro config = (debugging) -> | ||
| 167 | global debugMode = debugging == "true" | ||
| 168 | "" | ||
| 169 | |||
| 170 | macro asserts = (cond) -> | ||
| 171 | debugMode and "assert #{cond}" or "" | ||
| 172 | |||
| 173 | macro assert = (cond) -> | ||
| 174 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 175 | |||
| 176 | $config true | ||
| 177 | $asserts item ~= nil | ||
| 178 | |||
| 179 | $config false | ||
| 180 | value = $assert item | ||
| 181 | |||
| 182 | -- the passed expressions are treated as strings | ||
| 183 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 184 | if $and f1!, f2!, f3! | ||
| 185 | print "OK" | ||
| 186 | ``` | ||
| 187 | |||
| 188 | <YueDisplay> | ||
| 189 | |||
| 190 | ```yue | ||
| 191 | macro PI2 = -> math.pi * 2 | ||
| 192 | area = $PI2 * 5 | ||
| 193 | |||
| 194 | macro HELLO = -> "'hello world'" | ||
| 195 | print $HELLO | ||
| 196 | |||
| 197 | macro config = (debugging) -> | ||
| 198 | global debugMode = debugging == "true" | ||
| 199 | "" | ||
| 200 | |||
| 201 | macro asserts = (cond) -> | ||
| 202 | debugMode and "assert #{cond}" or "" | ||
| 203 | |||
| 204 | macro assert = (cond) -> | ||
| 205 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 206 | |||
| 207 | $config true | ||
| 208 | $asserts item ~= nil | ||
| 209 | |||
| 210 | $config false | ||
| 211 | value = $assert item | ||
| 212 | |||
| 213 | -- the passed expressions are treated as strings | ||
| 214 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 215 | if $and f1!, f2!, f3! | ||
| 216 | print "OK" | ||
| 217 | ``` | ||
| 218 | |||
| 219 | </YueDisplay> | ||
| 220 | |||
| 221 | ## Insert Raw Codes | ||
| 222 | |||
| 223 | A macro function can either return a YueScript string or a config table containing Lua codes. | ||
| 224 | |||
| 225 | ```yuescript | ||
| 226 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 227 | $yueFunc funcA | ||
| 228 | funcA = -> "fail to assign to the Yue macro defined variable" | ||
| 229 | |||
| 230 | macro luaFunc = (var) -> { | ||
| 231 | code: "local function #{var}() end" | ||
| 232 | type: "lua" | ||
| 233 | } | ||
| 234 | $luaFunc funcB | ||
| 235 | funcB = -> "fail to assign to the Lua macro defined variable" | ||
| 236 | |||
| 237 | macro lua = (code) -> { | ||
| 238 | :code | ||
| 239 | type: "lua" | ||
| 240 | } | ||
| 241 | |||
| 242 | -- the raw string leading and ending symbols are auto trimed | ||
| 243 | $lua[==[ | ||
| 244 | -- raw Lua codes insertion | ||
| 245 | if cond then | ||
| 246 | print("output") | ||
| 247 | end | ||
| 248 | ]==] | ||
| 249 | ``` | ||
| 250 | |||
| 251 | <YueDisplay> | ||
| 252 | |||
| 253 | ```yue | ||
| 254 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 255 | $yueFunc funcA | ||
| 256 | funcA = -> "fail to assign to the Yue macro defined variable" | ||
| 257 | |||
| 258 | macro luaFunc = (var) -> { | ||
| 259 | code: "local function #{var}() end" | ||
| 260 | type: "lua" | ||
| 261 | } | ||
| 262 | $luaFunc funcB | ||
| 263 | funcB = -> "fail to assign to the Lua macro defined variable" | ||
| 264 | |||
| 265 | macro lua = (code) -> { | ||
| 266 | :code | ||
| 267 | type: "lua" | ||
| 268 | } | ||
| 269 | |||
| 270 | -- the raw string leading and ending symbols are auto trimed | ||
| 271 | $lua[==[ | ||
| 272 | -- raw Lua codes insertion | ||
| 273 | if cond then | ||
| 274 | print("output") | ||
| 275 | end | ||
| 276 | ]==] | ||
| 277 | ``` | ||
| 278 | |||
| 279 | </YueDisplay> | ||
| 280 | |||
| 281 | ## Export Macro | ||
| 282 | |||
| 283 | Macro functions can be exported from a module and get imported in another module. You have to put export macro functions in a single file to be used, and only macro definition, macro importing and macro expansion in place can be put into the macro exporting module. | ||
| 284 | |||
| 285 | ```yuescript | ||
| 286 | -- file: utils.yue | ||
| 287 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 288 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 289 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 290 | #{action}" | ||
| 291 | |||
| 292 | -- file main.yue | ||
| 293 | import "utils" as { | ||
| 294 | $, -- symbol to import all macros | ||
| 295 | $foreach: $each -- rename macro $foreach to $each | ||
| 296 | } | ||
| 297 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 298 | ``` | ||
| 299 | |||
| 300 | <YueDisplay> | ||
| 301 | |||
| 302 | ```yue | ||
| 303 | -- file: utils.yue | ||
| 304 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 305 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 306 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 307 | #{action}" | ||
| 308 | |||
| 309 | -- file main.yue | ||
| 310 | -- import function is not available in browser, try it in a real environment | ||
| 311 | --[[ | ||
| 312 | import "utils" as { | ||
| 313 | $, -- symbol to import all macros | ||
| 314 | $foreach: $each -- rename macro $foreach to $each | ||
| 315 | } | ||
| 316 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 317 | ]] | ||
| 318 | ``` | ||
| 319 | |||
| 320 | </YueDisplay> | ||
| 321 | |||
| 322 | ## Builtin Macro | ||
| 323 | |||
| 324 | There are some builtin macros but you can override them by declaring macros with the same names. | ||
| 325 | |||
| 326 | ```yuescript | ||
| 327 | print $FILE -- get string of current module name | ||
| 328 | print $LINE -- get number 2 | ||
| 329 | ``` | ||
| 330 | |||
| 331 | <YueDisplay> | ||
| 332 | |||
| 333 | ```yue | ||
| 334 | print $FILE -- get string of current module name | ||
| 335 | print $LINE -- get number 2 | ||
| 336 | ``` | ||
| 337 | |||
| 338 | </YueDisplay> | ||
| 339 | |||
| 340 | ## Generating Macros with Macros | ||
| 341 | |||
| 342 | In YueScript, macro functions allow you to generate code at compile time. By nesting macro functions, you can create more complex generation patterns. This feature enables you to define a macro function that generates another macro function, allowing for more dynamic code generation. | ||
| 343 | |||
| 344 | ```yuescript | ||
| 345 | macro Enum = (...) -> | ||
| 346 | items = {...} | ||
| 347 | itemSet = {item, true for item in *items} | ||
| 348 | (item) -> | ||
| 349 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 350 | "\"#{item}\"" | ||
| 351 | |||
| 352 | macro BodyType = $Enum( | ||
| 353 | Static | ||
| 354 | Dynamic | ||
| 355 | Kinematic | ||
| 356 | ) | ||
| 357 | |||
| 358 | print "Valid enum type:", $BodyType Static | ||
| 359 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 360 | ``` | ||
| 361 | |||
| 362 | <YueDisplay> | ||
| 363 | |||
| 364 | ```yue | ||
| 365 | macro Enum = (...) -> | ||
| 366 | items = {...} | ||
| 367 | itemSet = {item, true for item in *items} | ||
| 368 | (item) -> | ||
| 369 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 370 | "\"#{item}\"" | ||
| 371 | |||
| 372 | macro BodyType = $Enum( | ||
| 373 | Static | ||
| 374 | Dynamic | ||
| 375 | Kinematic | ||
| 376 | ) | ||
| 377 | |||
| 378 | print "Valid enum type:", $BodyType Static | ||
| 379 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 380 | ``` | ||
| 381 | |||
| 382 | </YueDisplay> | ||
| 383 | |||
| 384 | ## Argument Validation | ||
| 385 | |||
| 386 | You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time. | ||
| 387 | |||
| 388 | ```yuescript | ||
| 389 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 390 | print( | ||
| 391 | #{num} | ||
| 392 | #{str} | ||
| 393 | ) | ||
| 394 | |||
| 395 | $printNumAndStr 123, "hello" | ||
| 396 | ``` | ||
| 397 | |||
| 398 | <YueDisplay> | ||
| 399 | |||
| 400 | ```yue | ||
| 401 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 402 | print( | ||
| 403 | #{num} | ||
| 404 | #{str} | ||
| 405 | ) | ||
| 406 | |||
| 407 | $printNumAndStr 123, "hello" | ||
| 408 | ``` | ||
| 409 | |||
| 410 | </YueDisplay> | ||
| 411 | |||
| 412 | If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place. | ||
| 413 | |||
| 414 | ```yuescript | ||
| 415 | macro printNumAndStr = (num, str) -> | ||
| 416 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 417 | error "expected String as second argument" unless $is_ast String, str | ||
| 418 | "print(#{num}, #{str})" | ||
| 419 | |||
| 420 | $printNumAndStr 123, "hello" | ||
| 421 | ``` | ||
| 422 | |||
| 423 | <YueDisplay> | ||
| 424 | |||
| 425 | ```yue | ||
| 426 | macro printNumAndStr = (num, str) -> | ||
| 427 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 428 | error "expected String as second argument" unless $is_ast String, str | ||
| 429 | "print(#{num}, #{str})" | ||
| 430 | |||
| 431 | $printNumAndStr 123, "hello" | ||
| 432 | ``` | ||
| 433 | |||
| 434 | </YueDisplay> | ||
| 435 | |||
| 436 | For 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). | ||
| 437 | |||
| 438 | # Try | ||
| 439 | |||
| 440 | The syntax for Lua error handling in a common form. | ||
| 441 | |||
| 442 | ```yuescript | ||
| 443 | try | ||
| 444 | func 1, 2, 3 | ||
| 445 | catch err | ||
| 446 | print yue.traceback err | ||
| 447 | |||
| 448 | success, result = try | ||
| 449 | func 1, 2, 3 | ||
| 450 | catch err | ||
| 451 | yue.traceback err | ||
| 452 | |||
| 453 | try func 1, 2, 3 | ||
| 454 | catch err | ||
| 455 | print yue.traceback err | ||
| 456 | |||
| 457 | success, result = try func 1, 2, 3 | ||
| 458 | |||
| 459 | try | ||
| 460 | print "trying" | ||
| 461 | func 1, 2, 3 | ||
| 462 | |||
| 463 | -- working with if assignment pattern | ||
| 464 | if success, result := try func 1, 2, 3 | ||
| 465 | catch err | ||
| 466 | print yue.traceback err | ||
| 467 | print result | ||
| 468 | ``` | ||
| 469 | |||
| 470 | <YueDisplay> | ||
| 471 | |||
| 472 | ```yue | ||
| 473 | try | ||
| 474 | func 1, 2, 3 | ||
| 475 | catch err | ||
| 476 | print yue.traceback err | ||
| 477 | |||
| 478 | success, result = try | ||
| 479 | func 1, 2, 3 | ||
| 480 | catch err | ||
| 481 | yue.traceback err | ||
| 482 | |||
| 483 | try func 1, 2, 3 | ||
| 484 | catch err | ||
| 485 | print yue.traceback err | ||
| 486 | |||
| 487 | success, result = try func 1, 2, 3 | ||
| 488 | |||
| 489 | try | ||
| 490 | print "trying" | ||
| 491 | func 1, 2, 3 | ||
| 492 | |||
| 493 | -- working with if assignment pattern | ||
| 494 | if success, result := try func 1, 2, 3 | ||
| 495 | catch err | ||
| 496 | print yue.traceback err | ||
| 497 | print result | ||
| 498 | ``` | ||
| 499 | |||
| 500 | </YueDisplay> | ||
| 501 | |||
| 502 | ## Try? | ||
| 503 | |||
| 504 | `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. | ||
| 505 | |||
| 506 | ```yuescript | ||
| 507 | a, b, c = try? func! | ||
| 508 | |||
| 509 | -- with nil coalescing operator | ||
| 510 | a = (try? func!) ?? "default" | ||
| 511 | |||
| 512 | -- as function argument | ||
| 513 | f try? func! | ||
| 514 | |||
| 515 | -- with catch block | ||
| 516 | f try? | ||
| 517 | print 123 | ||
| 518 | func! | ||
| 519 | catch e | ||
| 520 | print e | ||
| 521 | e | ||
| 522 | ``` | ||
| 523 | |||
| 524 | <YueDisplay> | ||
| 525 | |||
| 526 | ```yue | ||
| 527 | a, b, c = try? func! | ||
| 528 | |||
| 529 | -- with nil coalescing operator | ||
| 530 | a = (try? func!) ?? "default" | ||
| 531 | |||
| 532 | -- as function argument | ||
| 533 | f try? func! | ||
| 534 | |||
| 535 | -- with catch block | ||
| 536 | f try? | ||
| 537 | print 123 | ||
| 538 | func! | ||
| 539 | catch e | ||
| 540 | print e | ||
| 541 | e | ||
| 542 | ``` | ||
| 543 | |||
| 544 | </YueDisplay> | ||
| 545 | |||
| 546 | # Table Literals | ||
| 547 | |||
| 548 | Like in Lua, tables are delimited in curly braces. | ||
| 549 | |||
| 550 | ```yuescript | ||
| 551 | some_values = [1, 2, 3, 4] | ||
| 552 | ``` | ||
| 553 | |||
| 554 | <YueDisplay> | ||
| 555 | |||
| 556 | ```yue | ||
| 557 | some_values = [1, 2, 3, 4] | ||
| 558 | ``` | ||
| 559 | |||
| 560 | </YueDisplay> | ||
| 561 | |||
| 562 | Unlike Lua, assigning a value to a key in a table is done with **:** (instead of **=**). | ||
| 563 | |||
| 564 | ```yuescript | ||
| 565 | some_values = { | ||
| 566 | name: "Bill", | ||
| 567 | age: 200, | ||
| 568 | ["favorite food"]: "rice" | ||
| 569 | } | ||
| 570 | ``` | ||
| 571 | |||
| 572 | <YueDisplay> | ||
| 573 | |||
| 574 | ```yue | ||
| 575 | some_values = { | ||
| 576 | name: "Bill", | ||
| 577 | age: 200, | ||
| 578 | ["favorite food"]: "rice" | ||
| 579 | } | ||
| 580 | ``` | ||
| 581 | |||
| 582 | </YueDisplay> | ||
| 583 | |||
| 584 | The curly braces can be left off if a single table of key value pairs is being assigned. | ||
| 585 | |||
| 586 | ```yuescript | ||
| 587 | profile = | ||
| 588 | height: "4 feet", | ||
| 589 | shoe_size: 13, | ||
| 590 | favorite_foods: ["ice cream", "donuts"] | ||
| 591 | ``` | ||
| 592 | |||
| 593 | <YueDisplay> | ||
| 594 | |||
| 595 | ```yue | ||
| 596 | profile = | ||
| 597 | height: "4 feet", | ||
| 598 | shoe_size: 13, | ||
| 599 | favorite_foods: ["ice cream", "donuts"] | ||
| 600 | ``` | ||
| 601 | |||
| 602 | </YueDisplay> | ||
| 603 | |||
| 604 | Newlines can be used to delimit values instead of a comma (or both): | ||
| 605 | |||
| 606 | ```yuescript | ||
| 607 | values = { | ||
| 608 | 1, 2, 3, 4 | ||
| 609 | 5, 6, 7, 8 | ||
| 610 | name: "superman" | ||
| 611 | occupation: "crime fighting" | ||
| 612 | } | ||
| 613 | ``` | ||
| 614 | |||
| 615 | <YueDisplay> | ||
| 616 | |||
| 617 | ```yue | ||
| 618 | values = { | ||
| 619 | 1, 2, 3, 4 | ||
| 620 | 5, 6, 7, 8 | ||
| 621 | name: "superman" | ||
| 622 | occupation: "crime fighting" | ||
| 623 | } | ||
| 624 | ``` | ||
| 625 | |||
| 626 | </YueDisplay> | ||
| 627 | |||
| 628 | When creating a single line table literal, the curly braces can also be left off: | ||
| 629 | |||
| 630 | ```yuescript | ||
| 631 | my_function dance: "Tango", partner: "none" | ||
| 632 | |||
| 633 | y = type: "dog", legs: 4, tails: 1 | ||
| 634 | ``` | ||
| 635 | |||
| 636 | <YueDisplay> | ||
| 637 | |||
| 638 | ```yue | ||
| 639 | my_function dance: "Tango", partner: "none" | ||
| 640 | |||
| 641 | y = type: "dog", legs: 4, tails: 1 | ||
| 642 | ``` | ||
| 643 | |||
| 644 | </YueDisplay> | ||
| 645 | |||
| 646 | The keys of a table literal can be language keywords without being escaped: | ||
| 647 | |||
| 648 | ```yuescript | ||
| 649 | tbl = { | ||
| 650 | do: "something" | ||
| 651 | end: "hunger" | ||
| 652 | } | ||
| 653 | ``` | ||
| 654 | |||
| 655 | <YueDisplay> | ||
| 656 | |||
| 657 | ```yue | ||
| 658 | tbl = { | ||
| 659 | do: "something" | ||
| 660 | end: "hunger" | ||
| 661 | } | ||
| 662 | ``` | ||
| 663 | |||
| 664 | </YueDisplay> | ||
| 665 | |||
| 666 | If you are constructing a table out of variables and wish the keys to be the same as the variable names, then the **:** prefix operator can be used: | ||
| 667 | |||
| 668 | ```yuescript | ||
| 669 | hair = "golden" | ||
| 670 | height = 200 | ||
| 671 | person = { :hair, :height, shoe_size: 40 } | ||
| 672 | |||
| 673 | print_table :hair, :height | ||
| 674 | ``` | ||
| 675 | |||
| 676 | <YueDisplay> | ||
| 677 | |||
| 678 | ```yue | ||
| 679 | hair = "golden" | ||
| 680 | height = 200 | ||
| 681 | person = { :hair, :height, shoe_size: 40 } | ||
| 682 | |||
| 683 | print_table :hair, :height | ||
| 684 | ``` | ||
| 685 | |||
| 686 | </YueDisplay> | ||
| 687 | |||
| 688 | If you want the key of a field in the table to to be result of an expression, then you can wrap it in **[ ]**, just like in Lua. You can also use a string literal directly as a key, leaving out the square brackets. This is useful if your key has any special characters. | ||
| 689 | |||
| 690 | ```yuescript | ||
| 691 | t = { | ||
| 692 | [1 + 2]: "hello" | ||
| 693 | "hello world": true | ||
| 694 | } | ||
| 695 | ``` | ||
| 696 | |||
| 697 | <YueDisplay> | ||
| 698 | |||
| 699 | ```yue | ||
| 700 | t = { | ||
| 701 | [1 + 2]: "hello" | ||
| 702 | "hello world": true | ||
| 703 | } | ||
| 704 | ``` | ||
| 705 | |||
| 706 | </YueDisplay> | ||
| 707 | |||
| 708 | Lua tables have both an array part and a hash part, but sometimes you want to make a semantic distinction between array and hash usage when writing Lua tables. Then you can write Lua table with **[ ]** instead of **{ }** to represent an array table and writing any key value pair in a list table won't be allowed. | ||
| 709 | |||
| 710 | ```yuescript | ||
| 711 | some_values = [1, 2, 3, 4] | ||
| 712 | list_with_one_element = [1, ] | ||
| 713 | ``` | ||
| 714 | |||
| 715 | <YueDisplay> | ||
| 716 | |||
| 717 | ```yue | ||
| 718 | some_values = [1, 2, 3, 4] | ||
| 719 | list_with_one_element = [1, ] | ||
| 720 | ``` | ||
| 721 | |||
| 722 | </YueDisplay> | ||
| 723 | |||
| 724 | # Comprehensions | ||
| 725 | |||
| 726 | Comprehensions provide a convenient syntax for constructing a new table by iterating over some existing object and applying an expression to its values. There are two kinds of comprehensions: list comprehensions and table comprehensions. They both produce Lua tables; list comprehensions accumulate values into an array-like table, and table comprehensions let you set both the key and the value on each iteration. | ||
| 727 | |||
| 728 | ## List Comprehensions | ||
| 729 | |||
| 730 | The following creates a copy of the items table but with all the values doubled. | ||
| 731 | |||
| 732 | ```yuescript | ||
| 733 | items = [ 1, 2, 3, 4 ] | ||
| 734 | doubled = [item * 2 for i, item in ipairs items] | ||
| 735 | ``` | ||
| 736 | |||
| 737 | <YueDisplay> | ||
| 738 | |||
| 739 | ```yue | ||
| 740 | items = [ 1, 2, 3, 4 ] | ||
| 741 | doubled = [item * 2 for i, item in ipairs items] | ||
| 742 | ``` | ||
| 743 | |||
| 744 | </YueDisplay> | ||
| 745 | |||
| 746 | The items included in the new table can be restricted with a when clause: | ||
| 747 | |||
| 748 | ```yuescript | ||
| 749 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 750 | ``` | ||
| 751 | |||
| 752 | <YueDisplay> | ||
| 753 | |||
| 754 | ```yue | ||
| 755 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 756 | ``` | ||
| 757 | |||
| 758 | </YueDisplay> | ||
| 759 | |||
| 760 | Because it is common to iterate over the values of a numerically indexed table, an **\*** operator is introduced. The doubled example can be rewritten as: | ||
| 761 | |||
| 762 | ```yuescript | ||
| 763 | doubled = [item * 2 for item in *items] | ||
| 764 | ``` | ||
| 765 | |||
| 766 | <YueDisplay> | ||
| 767 | |||
| 768 | ```yue | ||
| 769 | doubled = [item * 2 for item in *items] | ||
| 770 | ``` | ||
| 771 | |||
| 772 | </YueDisplay> | ||
| 773 | |||
| 774 | In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect: | ||
| 775 | |||
| 776 | ```yuescript | ||
| 777 | data = | ||
| 778 | a: [1, 2, 3] | ||
| 779 | b: [4, 5, 6] | ||
| 780 | |||
| 781 | flat = [...v for k,v in pairs data] | ||
| 782 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 783 | ``` | ||
| 784 | |||
| 785 | <YueDisplay> | ||
| 786 | |||
| 787 | ```yue | ||
| 788 | data = | ||
| 789 | a: [1, 2, 3] | ||
| 790 | b: [4, 5, 6] | ||
| 791 | |||
| 792 | flat = [...v for k,v in pairs data] | ||
| 793 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 794 | ``` | ||
| 795 | |||
| 796 | </YueDisplay> | ||
| 797 | |||
| 798 | The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. | ||
| 799 | |||
| 800 | Using multiple for clauses is the same as using nested loops: | ||
| 801 | |||
| 802 | ```yuescript | ||
| 803 | x_coords = [4, 5, 6, 7] | ||
| 804 | y_coords = [9, 2, 3] | ||
| 805 | |||
| 806 | points = [ [x, y] for x in *x_coords \ | ||
| 807 | for y in *y_coords] | ||
| 808 | ``` | ||
| 809 | |||
| 810 | <YueDisplay> | ||
| 811 | |||
| 812 | ```yue | ||
| 813 | x_coords = [4, 5, 6, 7] | ||
| 814 | y_coords = [9, 2, 3] | ||
| 815 | |||
| 816 | points = [ [x, y] for x in *x_coords \ | ||
| 817 | for y in *y_coords] | ||
| 818 | ``` | ||
| 819 | |||
| 820 | </YueDisplay> | ||
| 821 | |||
| 822 | Numeric for loops can also be used in comprehensions: | ||
| 823 | |||
| 824 | ```yuescript | ||
| 825 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 826 | ``` | ||
| 827 | |||
| 828 | <YueDisplay> | ||
| 829 | |||
| 830 | ```yue | ||
| 831 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 832 | ``` | ||
| 833 | |||
| 834 | </YueDisplay> | ||
| 835 | |||
| 836 | ## Table Comprehensions | ||
| 837 | |||
| 838 | The syntax for table comprehensions is very similar, only differing by using **{** and **}** and taking two values from each iteration. | ||
| 839 | |||
| 840 | This example makes a copy of the tablething: | ||
| 841 | |||
| 842 | ```yuescript | ||
| 843 | thing = { | ||
| 844 | color: "red" | ||
| 845 | name: "fast" | ||
| 846 | width: 123 | ||
| 847 | } | ||
| 848 | |||
| 849 | thing_copy = {k, v for k, v in pairs thing} | ||
| 850 | ``` | ||
| 851 | |||
| 852 | <YueDisplay> | ||
| 853 | |||
| 854 | ```yue | ||
| 855 | thing = { | ||
| 856 | color: "red" | ||
| 857 | name: "fast" | ||
| 858 | width: 123 | ||
| 859 | } | ||
| 860 | |||
| 861 | thing_copy = {k, v for k, v in pairs thing} | ||
| 862 | ``` | ||
| 863 | |||
| 864 | </YueDisplay> | ||
| 865 | |||
| 866 | ```yuescript | ||
| 867 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 868 | ``` | ||
| 869 | |||
| 870 | <YueDisplay> | ||
| 871 | |||
| 872 | ```yue | ||
| 873 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 874 | ``` | ||
| 875 | |||
| 876 | </YueDisplay> | ||
| 877 | |||
| 878 | The **\*** operator is also supported. Here we create a square root look up table for a few numbers. | ||
| 879 | |||
| 880 | ```yuescript | ||
| 881 | numbers = [1, 2, 3, 4] | ||
| 882 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 883 | ``` | ||
| 884 | |||
| 885 | <YueDisplay> | ||
| 886 | |||
| 887 | ```yue | ||
| 888 | numbers = [1, 2, 3, 4] | ||
| 889 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 890 | ``` | ||
| 891 | |||
| 892 | </YueDisplay> | ||
| 893 | |||
| 894 | The key-value tuple in a table comprehension can also come from a single expression, in which case the expression should return two values. The first is used as the key and the second is used as the value: | ||
| 895 | |||
| 896 | In this example we convert an array of pairs to a table where the first item in the pair is the key and the second is the value. | ||
| 897 | |||
| 898 | ```yuescript | ||
| 899 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 900 | tbl = {unpack tuple for tuple in *tuples} | ||
| 901 | ``` | ||
| 902 | |||
| 903 | <YueDisplay> | ||
| 904 | |||
| 905 | ```yue | ||
| 906 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 907 | tbl = {unpack tuple for tuple in *tuples} | ||
| 908 | ``` | ||
| 909 | |||
| 910 | </YueDisplay> | ||
| 911 | |||
| 912 | ## Slicing | ||
| 913 | |||
| 914 | A special syntax is provided to restrict the items that are iterated over when using the **\*** operator. This is equivalent to setting the iteration bounds and a step size in a for loop. | ||
| 915 | |||
| 916 | Here we can set the minimum and maximum bounds, taking all items with indexes between 1 and 5 inclusive: | ||
| 917 | |||
| 918 | ```yuescript | ||
| 919 | slice = [item for item in *items[1, 5]] | ||
| 920 | ``` | ||
| 921 | |||
| 922 | <YueDisplay> | ||
| 923 | |||
| 924 | ```yue | ||
| 925 | slice = [item for item in *items[1, 5]] | ||
| 926 | ``` | ||
| 927 | |||
| 928 | </YueDisplay> | ||
| 929 | |||
| 930 | Any of the slice arguments can be left off to use a sensible default. In this example, if the max index is left off it defaults to the length of the table. This will take everything but the first element: | ||
| 931 | |||
| 932 | ```yuescript | ||
| 933 | slice = [item for item in *items[2,]] | ||
| 934 | ``` | ||
| 935 | |||
| 936 | <YueDisplay> | ||
| 937 | |||
| 938 | ```yue | ||
| 939 | slice = [item for item in *items[2,]] | ||
| 940 | ``` | ||
| 941 | |||
| 942 | </YueDisplay> | ||
| 943 | |||
| 944 | If the minimum bound is left out, it defaults to 1. Here we only provide a step size and leave the other bounds blank. This takes all odd indexed items: (1, 3, 5, …) | ||
| 945 | |||
| 946 | ```yuescript | ||
| 947 | slice = [item for item in *items[,,2]] | ||
| 948 | ``` | ||
| 949 | |||
| 950 | <YueDisplay> | ||
| 951 | |||
| 952 | ```yue | ||
| 953 | slice = [item for item in *items[,,2]] | ||
| 954 | ``` | ||
| 955 | |||
| 956 | </YueDisplay> | ||
| 957 | |||
| 958 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
| 959 | |||
| 960 | ```yuescript | ||
| 961 | -- take the last 4 items | ||
| 962 | slice = [item for item in *items[-4,-1]] | ||
| 963 | ``` | ||
| 964 | |||
| 965 | <YueDisplay> | ||
| 966 | |||
| 967 | ```yue | ||
| 968 | -- take the last 4 items | ||
| 969 | slice = [item for item in *items[-4,-1]] | ||
| 970 | ``` | ||
| 971 | |||
| 972 | </YueDisplay> | ||
| 973 | |||
| 974 | The step size can also be negative, which means that the items are taken in reverse order. | ||
| 975 | |||
| 976 | ```yuescript | ||
| 977 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 978 | ``` | ||
| 979 | |||
| 980 | <YueDisplay> | ||
| 981 | |||
| 982 | ```yue | ||
| 983 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 984 | ``` | ||
| 985 | |||
| 986 | </YueDisplay> | ||
| 987 | |||
| 988 | ### Slicing Expression | ||
| 989 | |||
| 990 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
| 991 | |||
| 992 | ```yuescript | ||
| 993 | -- take the 2nd and 4th items as a new list | ||
| 994 | sub_list = items[2, 4] | ||
| 995 | |||
| 996 | -- take the last 4 items | ||
| 997 | last_four_items = items[-4, -1] | ||
| 998 | ``` | ||
| 999 | |||
| 1000 | <YueDisplay> | ||
| 1001 | |||
| 1002 | ```yue | ||
| 1003 | -- take the 2nd and 4th items as a new list | ||
| 1004 | sub_list = items[2, 4] | ||
| 1005 | |||
| 1006 | -- take the last 4 items | ||
| 1007 | last_four_items = items[-4, -1] | ||
| 1008 | ``` | ||
| 1009 | |||
| 1010 | </YueDisplay> | ||
| 1011 | |||
| 1012 | # Object Oriented Programming | ||
| 1013 | |||
| 1014 | In 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. | ||
| 1015 | |||
| 1016 | A simple class: | ||
| 1017 | |||
| 1018 | ```yuescript | ||
| 1019 | class Inventory | ||
| 1020 | new: => | ||
| 1021 | @items = {} | ||
| 1022 | |||
| 1023 | add_item: (name) => | ||
| 1024 | if @items[name] | ||
| 1025 | @items[name] += 1 | ||
| 1026 | else | ||
| 1027 | @items[name] = 1 | ||
| 1028 | ``` | ||
| 1029 | |||
| 1030 | <YueDisplay> | ||
| 1031 | |||
| 1032 | ```yue | ||
| 1033 | class Inventory | ||
| 1034 | new: => | ||
| 1035 | @items = {} | ||
| 1036 | |||
| 1037 | add_item: (name) => | ||
| 1038 | if @items[name] | ||
| 1039 | @items[name] += 1 | ||
| 1040 | else | ||
| 1041 | @items[name] = 1 | ||
| 1042 | ``` | ||
| 1043 | |||
| 1044 | </YueDisplay> | ||
| 1045 | |||
| 1046 | A class is declared with a class statement followed by a table-like declaration where all of the methods and properties are listed. | ||
| 1047 | |||
| 1048 | The new property is special in that it will become the constructor. | ||
| 1049 | |||
| 1050 | Notice how all the methods in the class use the fat arrow function syntax. When calling methods on a instance, the instance itself is sent in as the first argument. The fat arrow handles the creation of a self argument. | ||
| 1051 | |||
| 1052 | The @ prefix on a variable name is shorthand for self.. @items becomes self.items. | ||
| 1053 | |||
| 1054 | Creating an instance of the class is done by calling the name of the class as a function. | ||
| 1055 | |||
| 1056 | ```yuescript | ||
| 1057 | inv = Inventory! | ||
| 1058 | inv\add_item "t-shirt" | ||
| 1059 | inv\add_item "pants" | ||
| 1060 | ``` | ||
| 1061 | |||
| 1062 | <YueDisplay> | ||
| 1063 | |||
| 1064 | ```yue | ||
| 1065 | inv = Inventory! | ||
| 1066 | inv\add_item "t-shirt" | ||
| 1067 | inv\add_item "pants" | ||
| 1068 | ``` | ||
| 1069 | |||
| 1070 | </YueDisplay> | ||
| 1071 | |||
| 1072 | Because the instance of the class needs to be sent to the methods when they are called, the \ operator is used. | ||
| 1073 | |||
| 1074 | All properties of a class are shared among the instances. This is fine for functions, but for other types of objects, undesired results may occur. | ||
| 1075 | |||
| 1076 | Consider the example below, the clothes property is shared amongst all instances, so modifications to it in one instance will show up in another: | ||
| 1077 | |||
| 1078 | ```yuescript | ||
| 1079 | class Person | ||
| 1080 | clothes: [] | ||
| 1081 | give_item: (name) => | ||
| 1082 | table.insert @clothes, name | ||
| 1083 | |||
| 1084 | a = Person! | ||
| 1085 | b = Person! | ||
| 1086 | |||
| 1087 | a\give_item "pants" | ||
| 1088 | b\give_item "shirt" | ||
| 1089 | |||
| 1090 | -- will print both pants and shirt | ||
| 1091 | print item for item in *a.clothes | ||
| 1092 | ``` | ||
| 1093 | |||
| 1094 | <YueDisplay> | ||
| 1095 | |||
| 1096 | ```yue | ||
| 1097 | class Person | ||
| 1098 | clothes: [] | ||
| 1099 | give_item: (name) => | ||
| 1100 | table.insert @clothes, name | ||
| 1101 | |||
| 1102 | a = Person! | ||
| 1103 | b = Person! | ||
| 1104 | |||
| 1105 | a\give_item "pants" | ||
| 1106 | b\give_item "shirt" | ||
| 1107 | |||
| 1108 | -- will print both pants and shirt | ||
| 1109 | print item for item in *a.clothes | ||
| 1110 | ``` | ||
| 1111 | |||
| 1112 | </YueDisplay> | ||
| 1113 | |||
| 1114 | The proper way to avoid this problem is to create the mutable state of the object in the constructor: | ||
| 1115 | |||
| 1116 | ```yuescript | ||
| 1117 | class Person | ||
| 1118 | new: => | ||
| 1119 | @clothes = [] | ||
| 1120 | ``` | ||
| 1121 | |||
| 1122 | <YueDisplay> | ||
| 1123 | |||
| 1124 | ```yue | ||
| 1125 | class Person | ||
| 1126 | new: => | ||
| 1127 | @clothes = [] | ||
| 1128 | ``` | ||
| 1129 | |||
| 1130 | </YueDisplay> | ||
| 1131 | |||
| 1132 | ## Inheritance | ||
| 1133 | |||
| 1134 | The extends keyword can be used in a class declaration to inherit the properties and methods from another class. | ||
| 1135 | |||
| 1136 | ```yuescript | ||
| 1137 | class BackPack extends Inventory | ||
| 1138 | size: 10 | ||
| 1139 | add_item: (name) => | ||
| 1140 | if #@items > size then error "backpack is full" | ||
| 1141 | super name | ||
| 1142 | ``` | ||
| 1143 | |||
| 1144 | <YueDisplay> | ||
| 1145 | |||
| 1146 | ```yue | ||
| 1147 | class BackPack extends Inventory | ||
| 1148 | size: 10 | ||
| 1149 | add_item: (name) => | ||
| 1150 | if #@items > size then error "backpack is full" | ||
| 1151 | super name | ||
| 1152 | ``` | ||
| 1153 | |||
| 1154 | </YueDisplay> | ||
| 1155 | |||
| 1156 | Here we extend our Inventory class, and limit the amount of items it can carry. | ||
| 1157 | |||
| 1158 | In 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. | ||
| 1159 | |||
| 1160 | Whenever 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. | ||
| 1161 | |||
| 1162 | ```yuescript | ||
| 1163 | class Shelf | ||
| 1164 | @__inherited: (child) => | ||
| 1165 | print @__name, "was inherited by", child.__name | ||
| 1166 | |||
| 1167 | -- will print: Shelf was inherited by Cupboard | ||
| 1168 | class Cupboard extends Shelf | ||
| 1169 | ``` | ||
| 1170 | |||
| 1171 | <YueDisplay> | ||
| 1172 | |||
| 1173 | ```yue | ||
| 1174 | class Shelf | ||
| 1175 | @__inherited: (child) => | ||
| 1176 | print @__name, "was inherited by", child.__name | ||
| 1177 | |||
| 1178 | -- will print: Shelf was inherited by Cupboard | ||
| 1179 | class Cupboard extends Shelf | ||
| 1180 | ``` | ||
| 1181 | |||
| 1182 | </YueDisplay> | ||
| 1183 | |||
| 1184 | ## Super | ||
| 1185 | |||
| 1186 | **super** is a special keyword that can be used in two different ways: It can be treated as an object, or it can be called like a function. It only has special functionality when inside a class. | ||
| 1187 | |||
| 1188 | When called as a function, it will call the function of the same name in the parent class. The current self will automatically be passed as the first argument. (As seen in the inheritance example above) | ||
| 1189 | |||
| 1190 | When super is used as a normal value, it is a reference to the parent class object. | ||
| 1191 | |||
| 1192 | It can be accessed like any of object in order to retrieve values in the parent class that might have been shadowed by the child class. | ||
| 1193 | |||
| 1194 | When the \ calling operator is used with super, self is inserted as the first argument instead of the value of super itself. When using . to retrieve a function, the raw function is returned. | ||
| 1195 | |||
| 1196 | A few examples of using super in different ways: | ||
| 1197 | |||
| 1198 | ```yuescript | ||
| 1199 | class MyClass extends ParentClass | ||
| 1200 | a_method: => | ||
| 1201 | -- the following have the same effect: | ||
| 1202 | super "hello", "world" | ||
| 1203 | super\a_method "hello", "world" | ||
| 1204 | super.a_method self, "hello", "world" | ||
| 1205 | |||
| 1206 | -- super as a value is equal to the parent class: | ||
| 1207 | assert super == ParentClass | ||
| 1208 | ``` | ||
| 1209 | |||
| 1210 | <YueDisplay> | ||
| 1211 | |||
| 1212 | ```yue | ||
| 1213 | class MyClass extends ParentClass | ||
| 1214 | a_method: => | ||
| 1215 | -- the following have the same effect: | ||
| 1216 | super "hello", "world" | ||
| 1217 | super\a_method "hello", "world" | ||
| 1218 | super.a_method self, "hello", "world" | ||
| 1219 | |||
| 1220 | -- super as a value is equal to the parent class: | ||
| 1221 | assert super == ParentClass | ||
| 1222 | ``` | ||
| 1223 | |||
| 1224 | </YueDisplay> | ||
| 1225 | |||
| 1226 | **super** can also be used on left side of a Function Stub. The only major difference is that instead of the resulting function being bound to the value of super, it is bound to self. | ||
| 1227 | |||
| 1228 | ## Types | ||
| 1229 | |||
| 1230 | Every instance of a class carries its type with it. This is stored in the special \_\_class property. This property holds the class object. The class object is what we call to build a new instance. We can also index the class object to retrieve class methods and properties. | ||
| 1231 | |||
| 1232 | ```yuescript | ||
| 1233 | b = BackPack! | ||
| 1234 | assert b.__class == BackPack | ||
| 1235 | |||
| 1236 | print BackPack.size -- prints 10 | ||
| 1237 | ``` | ||
| 1238 | |||
| 1239 | <YueDisplay> | ||
| 1240 | |||
| 1241 | ```yue | ||
| 1242 | b = BackPack! | ||
| 1243 | assert b.__class == BackPack | ||
| 1244 | |||
| 1245 | print BackPack.size -- prints 10 | ||
| 1246 | ``` | ||
| 1247 | |||
| 1248 | </YueDisplay> | ||
| 1249 | |||
| 1250 | ## Class Objects | ||
| 1251 | |||
| 1252 | The 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. | ||
| 1253 | |||
| 1254 | The 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. | ||
| 1255 | |||
| 1256 | A 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. | ||
| 1257 | |||
| 1258 | The 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. | ||
| 1259 | |||
| 1260 | It 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. | ||
| 1261 | |||
| 1262 | The class object has a couple special properties: | ||
| 1263 | |||
| 1264 | The name of the class as when it was declared is stored as a string in the \_\_name field of the class object. | ||
| 1265 | |||
| 1266 | ```yuescript | ||
| 1267 | print BackPack.__name -- prints Backpack | ||
| 1268 | ``` | ||
| 1269 | |||
| 1270 | <YueDisplay> | ||
| 1271 | |||
| 1272 | ```yue | ||
| 1273 | print BackPack.__name -- prints Backpack | ||
| 1274 | ``` | ||
| 1275 | |||
| 1276 | </YueDisplay> | ||
| 1277 | |||
| 1278 | The base object is stored in \_\_base. We can modify this table to add functionality to instances that have already been created and ones that are yet to be created. | ||
| 1279 | |||
| 1280 | If the class extends from anything, the parent class object is stored in \_\_parent. | ||
| 1281 | |||
| 1282 | ## Class Variables | ||
| 1283 | |||
| 1284 | We can create variables directly in the class object instead of in the base by using @ in the front of the property name in a class declaration. | ||
| 1285 | |||
| 1286 | ```yuescript | ||
| 1287 | class Things | ||
| 1288 | @some_func: => print "Hello from", @__name | ||
| 1289 | |||
| 1290 | Things\some_func! | ||
| 1291 | |||
| 1292 | -- class variables not visible in instances | ||
| 1293 | assert Things().some_func == nil | ||
| 1294 | ``` | ||
| 1295 | |||
| 1296 | <YueDisplay> | ||
| 1297 | |||
| 1298 | ```yue | ||
| 1299 | class Things | ||
| 1300 | @some_func: => print "Hello from", @__name | ||
| 1301 | |||
| 1302 | Things\some_func! | ||
| 1303 | |||
| 1304 | -- class variables not visible in instances | ||
| 1305 | assert Things().some_func == nil | ||
| 1306 | ``` | ||
| 1307 | |||
| 1308 | </YueDisplay> | ||
| 1309 | |||
| 1310 | In expressions, we can use @@ to access a value that is stored in the **class of self. Thus, @@hello is shorthand for self.**class.hello. | ||
| 1311 | |||
| 1312 | ```yuescript | ||
| 1313 | class Counter | ||
| 1314 | @count: 0 | ||
| 1315 | |||
| 1316 | new: => | ||
| 1317 | @@count += 1 | ||
| 1318 | |||
| 1319 | Counter! | ||
| 1320 | Counter! | ||
| 1321 | |||
| 1322 | print Counter.count -- prints 2 | ||
| 1323 | ``` | ||
| 1324 | |||
| 1325 | <YueDisplay> | ||
| 1326 | |||
| 1327 | ```yue | ||
| 1328 | class Counter | ||
| 1329 | @count: 0 | ||
| 1330 | |||
| 1331 | new: => | ||
| 1332 | @@count += 1 | ||
| 1333 | |||
| 1334 | Counter! | ||
| 1335 | Counter! | ||
| 1336 | |||
| 1337 | print Counter.count -- prints 2 | ||
| 1338 | ``` | ||
| 1339 | |||
| 1340 | </YueDisplay> | ||
| 1341 | |||
| 1342 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. | ||
| 1343 | |||
| 1344 | ```yuescript | ||
| 1345 | @@hello 1,2,3,4 | ||
| 1346 | ``` | ||
| 1347 | |||
| 1348 | <YueDisplay> | ||
| 1349 | |||
| 1350 | ```yue | ||
| 1351 | @@hello 1,2,3,4 | ||
| 1352 | ``` | ||
| 1353 | |||
| 1354 | </YueDisplay> | ||
| 1355 | |||
| 1356 | ## Class Declaration Statements | ||
| 1357 | |||
| 1358 | In 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. | ||
| 1359 | |||
| 1360 | Here is an alternative way to create a class variable compared to what's described above: | ||
| 1361 | |||
| 1362 | ```yuescript | ||
| 1363 | class Things | ||
| 1364 | @class_var = "hello world" | ||
| 1365 | ``` | ||
| 1366 | |||
| 1367 | <YueDisplay> | ||
| 1368 | |||
| 1369 | ```yue | ||
| 1370 | class Things | ||
| 1371 | @class_var = "hello world" | ||
| 1372 | ``` | ||
| 1373 | |||
| 1374 | </YueDisplay> | ||
| 1375 | |||
| 1376 | These expressions are executed after all the properties have been added to the base. | ||
| 1377 | |||
| 1378 | All variables declared in the body of the class are local to the classes properties. This is convenient for placing private values or helper functions that only the class methods can access: | ||
| 1379 | |||
| 1380 | ```yuescript | ||
| 1381 | class MoreThings | ||
| 1382 | secret = 123 | ||
| 1383 | log = (msg) -> print "LOG:", msg | ||
| 1384 | |||
| 1385 | some_method: => | ||
| 1386 | log "hello world: " .. secret | ||
| 1387 | ``` | ||
| 1388 | |||
| 1389 | <YueDisplay> | ||
| 1390 | |||
| 1391 | ```yue | ||
| 1392 | class MoreThings | ||
| 1393 | secret = 123 | ||
| 1394 | log = (msg) -> print "LOG:", msg | ||
| 1395 | |||
| 1396 | some_method: => | ||
| 1397 | log "hello world: " .. secret | ||
| 1398 | ``` | ||
| 1399 | |||
| 1400 | </YueDisplay> | ||
| 1401 | |||
| 1402 | ## @ and @@ Values | ||
| 1403 | |||
| 1404 | When @ and @@ are prefixed in front of a name they represent, respectively, that name accessed in self and self.\_\_class. | ||
| 1405 | |||
| 1406 | If they are used all by themselves, they are aliases for self and self.\_\_class. | ||
| 1407 | |||
| 1408 | ```yuescript | ||
| 1409 | assert @ == self | ||
| 1410 | assert @@ == self.__class | ||
| 1411 | ``` | ||
| 1412 | |||
| 1413 | <YueDisplay> | ||
| 1414 | |||
| 1415 | ```yue | ||
| 1416 | assert @ == self | ||
| 1417 | assert @@ == self.__class | ||
| 1418 | ``` | ||
| 1419 | |||
| 1420 | </YueDisplay> | ||
| 1421 | |||
| 1422 | For example, a quick way to create a new instance of the same class from an instance method using @@: | ||
| 1423 | |||
| 1424 | ```yuescript | ||
| 1425 | some_instance_method = (...) => @@ ... | ||
| 1426 | ``` | ||
| 1427 | |||
| 1428 | <YueDisplay> | ||
| 1429 | |||
| 1430 | ```yue | ||
| 1431 | some_instance_method = (...) => @@ ... | ||
| 1432 | ``` | ||
| 1433 | |||
| 1434 | </YueDisplay> | ||
| 1435 | |||
| 1436 | ## Constructor Property Promotion | ||
| 1437 | |||
| 1438 | To reduce the boilerplate code for definition of simple value objects. You can write a simple class like: | ||
| 1439 | |||
| 1440 | ```yuescript | ||
| 1441 | class Something | ||
| 1442 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1443 | |||
| 1444 | -- Which is short for | ||
| 1445 | |||
| 1446 | class Something | ||
| 1447 | new: (foo, bar, biz, baz) => | ||
| 1448 | @foo = foo | ||
| 1449 | @bar = bar | ||
| 1450 | @@biz = biz | ||
| 1451 | @@baz = baz | ||
| 1452 | ``` | ||
| 1453 | |||
| 1454 | <YueDisplay> | ||
| 1455 | |||
| 1456 | ```yue | ||
| 1457 | class Something | ||
| 1458 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1459 | |||
| 1460 | -- Which is short for | ||
| 1461 | |||
| 1462 | class Something | ||
| 1463 | new: (foo, bar, biz, baz) => | ||
| 1464 | @foo = foo | ||
| 1465 | @bar = bar | ||
| 1466 | @@biz = biz | ||
| 1467 | @@baz = baz | ||
| 1468 | ``` | ||
| 1469 | |||
| 1470 | </YueDisplay> | ||
| 1471 | |||
| 1472 | You can also use this syntax for a common function to initialize a object's fields. | ||
| 1473 | |||
| 1474 | ```yuescript | ||
| 1475 | new = (@fieldA, @fieldB) => @ | ||
| 1476 | obj = new {}, 123, "abc" | ||
| 1477 | print obj | ||
| 1478 | ``` | ||
| 1479 | |||
| 1480 | <YueDisplay> | ||
| 1481 | |||
| 1482 | ```yue | ||
| 1483 | new = (@fieldA, @fieldB) => @ | ||
| 1484 | obj = new {}, 123, "abc" | ||
| 1485 | print obj | ||
| 1486 | ``` | ||
| 1487 | |||
| 1488 | </YueDisplay> | ||
| 1489 | |||
| 1490 | ## Class Expressions | ||
| 1491 | |||
| 1492 | The class syntax can also be used as an expression which can be assigned to a variable or explicitly returned. | ||
| 1493 | |||
| 1494 | ```yuescript | ||
| 1495 | x = class Bucket | ||
| 1496 | drops: 0 | ||
| 1497 | add_drop: => @drops += 1 | ||
| 1498 | ``` | ||
| 1499 | |||
| 1500 | <YueDisplay> | ||
| 1501 | |||
| 1502 | ```yue | ||
| 1503 | x = class Bucket | ||
| 1504 | drops: 0 | ||
| 1505 | add_drop: => @drops += 1 | ||
| 1506 | ``` | ||
| 1507 | |||
| 1508 | </YueDisplay> | ||
| 1509 | |||
| 1510 | ## Anonymous classes | ||
| 1511 | |||
| 1512 | The name can be left out when declaring a class. The \_\_name attribute will be nil, unless the class expression is in an assignment. The name on the left hand side of the assignment is used instead of nil. | ||
| 1513 | |||
| 1514 | ```yuescript | ||
| 1515 | BigBucket = class extends Bucket | ||
| 1516 | add_drop: => @drops += 10 | ||
| 1517 | |||
| 1518 | assert Bucket.__name == "BigBucket" | ||
| 1519 | ``` | ||
| 1520 | |||
| 1521 | <YueDisplay> | ||
| 1522 | |||
| 1523 | ```yue | ||
| 1524 | BigBucket = class extends Bucket | ||
| 1525 | add_drop: => @drops += 10 | ||
| 1526 | |||
| 1527 | assert Bucket.__name == "BigBucket" | ||
| 1528 | ``` | ||
| 1529 | |||
| 1530 | </YueDisplay> | ||
| 1531 | |||
| 1532 | You can even leave off the body, meaning you can write a blank anonymous class like this: | ||
| 1533 | |||
| 1534 | ```yuescript | ||
| 1535 | x = class | ||
| 1536 | ``` | ||
| 1537 | |||
| 1538 | <YueDisplay> | ||
| 1539 | |||
| 1540 | ```yue | ||
| 1541 | x = class | ||
| 1542 | ``` | ||
| 1543 | |||
| 1544 | </YueDisplay> | ||
| 1545 | |||
| 1546 | ## Class Mixing | ||
| 1547 | |||
| 1548 | You can do mixing with keyword `using` to copy functions from either a plain table or a predefined class object into your new class. When doing mixing with a plain table, you can override the class indexing function (metamethod `__index`) to your customized implementation. When doing mixing with an existing class object, the class object's metamethods won't be copied. | ||
| 1549 | |||
| 1550 | ```yuescript | ||
| 1551 | MyIndex = __index: var: 1 | ||
| 1552 | |||
| 1553 | class X using MyIndex | ||
| 1554 | func: => | ||
| 1555 | print 123 | ||
| 1556 | |||
| 1557 | x = X! | ||
| 1558 | print x.var | ||
| 1559 | |||
| 1560 | class Y using X | ||
| 1561 | |||
| 1562 | y = Y! | ||
| 1563 | y\func! | ||
| 1564 | |||
| 1565 | assert y.__class.__parent ~= X -- X is not parent of Y | ||
| 1566 | ``` | ||
| 1567 | |||
| 1568 | <YueDisplay> | ||
| 1569 | |||
| 1570 | ```yue | ||
| 1571 | MyIndex = __index: var: 1 | ||
| 1572 | |||
| 1573 | class X using MyIndex | ||
| 1574 | func: => | ||
| 1575 | print 123 | ||
| 1576 | |||
| 1577 | x = X! | ||
| 1578 | print x.var | ||
| 1579 | |||
| 1580 | class Y using X | ||
| 1581 | |||
| 1582 | y = Y! | ||
| 1583 | y\func! | ||
| 1584 | |||
| 1585 | assert y.__class.__parent ~= X -- X is not parent of Y | ||
| 1586 | ``` | ||
| 1587 | |||
| 1588 | </YueDisplay> | ||
| 1589 | |||
| 1590 | # With Statement | ||
| 1591 | |||
| 1592 | A common pattern involving the creation of an object is calling a series of functions and setting a series of properties immediately after creating it. | ||
| 1593 | |||
| 1594 | This results in repeating the name of the object multiple times in code, adding unnecessary noise. A common solution to this is to pass a table in as an argument which contains a collection of keys and values to overwrite. The downside to this is that the constructor of this object must support this form. | ||
| 1595 | |||
| 1596 | The with block helps to alleviate this. Within a with block we can use a special statements that begin with either . or \ which represent those operations applied to the object we are using with on. | ||
| 1597 | |||
| 1598 | For example, we work with a newly created object: | ||
| 1599 | |||
| 1600 | ```yuescript | ||
| 1601 | with Person! | ||
| 1602 | .name = "Oswald" | ||
| 1603 | \add_relative my_dad | ||
| 1604 | \save! | ||
| 1605 | print .name | ||
| 1606 | ``` | ||
| 1607 | |||
| 1608 | <YueDisplay> | ||
| 1609 | |||
| 1610 | ```yue | ||
| 1611 | with Person! | ||
| 1612 | .name = "Oswald" | ||
| 1613 | \add_relative my_dad | ||
| 1614 | \save! | ||
| 1615 | print .name | ||
| 1616 | ``` | ||
| 1617 | |||
| 1618 | </YueDisplay> | ||
| 1619 | |||
| 1620 | The with statement can also be used as an expression which returns the value it has been giving access to. | ||
| 1621 | |||
| 1622 | ```yuescript | ||
| 1623 | file = with File "favorite_foods.txt" | ||
| 1624 | \set_encoding "utf8" | ||
| 1625 | ``` | ||
| 1626 | |||
| 1627 | <YueDisplay> | ||
| 1628 | |||
| 1629 | ```yue | ||
| 1630 | file = with File "favorite_foods.txt" | ||
| 1631 | \set_encoding "utf8" | ||
| 1632 | ``` | ||
| 1633 | |||
| 1634 | </YueDisplay> | ||
| 1635 | |||
| 1636 | `with` expressions support `break` with one value: | ||
| 1637 | |||
| 1638 | ```yuescript | ||
| 1639 | result = with obj | ||
| 1640 | break .value | ||
| 1641 | ``` | ||
| 1642 | |||
| 1643 | <YueDisplay> | ||
| 1644 | |||
| 1645 | ```yue | ||
| 1646 | result = with obj | ||
| 1647 | break .value | ||
| 1648 | ``` | ||
| 1649 | |||
| 1650 | </YueDisplay> | ||
| 1651 | |||
| 1652 | After `break value` is used inside `with`, the `with` expression no longer returns its target object. Instead, it returns the value from `break`. | ||
| 1653 | |||
| 1654 | ```yuescript | ||
| 1655 | a = with obj | ||
| 1656 | .x = 1 | ||
| 1657 | -- a is obj | ||
| 1658 | |||
| 1659 | b = with obj | ||
| 1660 | break .x | ||
| 1661 | -- b is .x, not obj | ||
| 1662 | ``` | ||
| 1663 | |||
| 1664 | <YueDisplay> | ||
| 1665 | |||
| 1666 | ```yue | ||
| 1667 | a = with obj | ||
| 1668 | .x = 1 | ||
| 1669 | -- a is obj | ||
| 1670 | |||
| 1671 | b = with obj | ||
| 1672 | break .x | ||
| 1673 | -- b is .x, not obj | ||
| 1674 | ``` | ||
| 1675 | |||
| 1676 | </YueDisplay> | ||
| 1677 | |||
| 1678 | Unlike `for` / `while` / `repeat` / `do`, `with` only supports one break value. | ||
| 1679 | |||
| 1680 | Or… | ||
| 1681 | |||
| 1682 | ```yuescript | ||
| 1683 | create_person = (name, relatives) -> | ||
| 1684 | with Person! | ||
| 1685 | .name = name | ||
| 1686 | \add_relative relative for relative in *relatives | ||
| 1687 | |||
| 1688 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1689 | ``` | ||
| 1690 | |||
| 1691 | <YueDisplay> | ||
| 1692 | |||
| 1693 | ```yue | ||
| 1694 | create_person = (name, relatives) -> | ||
| 1695 | with Person! | ||
| 1696 | .name = name | ||
| 1697 | \add_relative relative for relative in *relatives | ||
| 1698 | |||
| 1699 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1700 | ``` | ||
| 1701 | |||
| 1702 | </YueDisplay> | ||
| 1703 | |||
| 1704 | In this usage, with can be seen as a special form of the K combinator. | ||
| 1705 | |||
| 1706 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | ||
| 1707 | |||
| 1708 | ```yuescript | ||
| 1709 | with str := "Hello" | ||
| 1710 | print "original:", str | ||
| 1711 | print "upper:", \upper! | ||
| 1712 | ``` | ||
| 1713 | |||
| 1714 | <YueDisplay> | ||
| 1715 | |||
| 1716 | ```yue | ||
| 1717 | with str := "Hello" | ||
| 1718 | print "original:", str | ||
| 1719 | print "upper:", \upper! | ||
| 1720 | ``` | ||
| 1721 | |||
| 1722 | </YueDisplay> | ||
| 1723 | |||
| 1724 | You can access special keys with `[]` in a `with` statement. | ||
| 1725 | |||
| 1726 | ```yuescript | ||
| 1727 | with tb | ||
| 1728 | [1] = 1 | ||
| 1729 | print [2] | ||
| 1730 | with [abc] | ||
| 1731 | [3] = [2]\func! | ||
| 1732 | ["key-name"] = value | ||
| 1733 | [] = "abc" -- appending to "tb" | ||
| 1734 | ``` | ||
| 1735 | |||
| 1736 | <YueDisplay> | ||
| 1737 | |||
| 1738 | ```yue | ||
| 1739 | with tb | ||
| 1740 | [1] = 1 | ||
| 1741 | print [2] | ||
| 1742 | with [abc] | ||
| 1743 | [3] = [2]\func! | ||
| 1744 | ["key-name"] = value | ||
| 1745 | [] = "abc" -- appending to "tb" | ||
| 1746 | ``` | ||
| 1747 | |||
| 1748 | </YueDisplay> | ||
| 1749 | |||
| 1750 | `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. | ||
| 1751 | |||
| 1752 | ```yuescript | ||
| 1753 | with? obj | ||
| 1754 | print obj.name | ||
| 1755 | ``` | ||
| 1756 | |||
| 1757 | <YueDisplay> | ||
| 1758 | |||
| 1759 | ```yue | ||
| 1760 | with? obj | ||
| 1761 | print obj.name | ||
| 1762 | ``` | ||
| 1763 | |||
| 1764 | </YueDisplay> | ||
| 1765 | |||
| 1766 | # Assignment | ||
| 1767 | |||
| 1768 | The variable is dynamic typed and is defined as local by default. But you can change the scope of declaration by **local** and **global** statement. | ||
| 1769 | |||
| 1770 | ```yuescript | ||
| 1771 | hello = "world" | ||
| 1772 | a, b, c = 1, 2, 3 | ||
| 1773 | hello = 123 -- uses the existing variable | ||
| 1774 | ``` | ||
| 1775 | |||
| 1776 | <YueDisplay> | ||
| 1777 | |||
| 1778 | ```yue | ||
| 1779 | hello = "world" | ||
| 1780 | a, b, c = 1, 2, 3 | ||
| 1781 | hello = 123 -- uses the existing variable | ||
| 1782 | ``` | ||
| 1783 | |||
| 1784 | </YueDisplay> | ||
| 1785 | |||
| 1786 | ## Perform Update | ||
| 1787 | |||
| 1788 | You can perform update assignment with many binary operators. | ||
| 1789 | |||
| 1790 | ```yuescript | ||
| 1791 | x = 1 | ||
| 1792 | x += 1 | ||
| 1793 | x -= 1 | ||
| 1794 | x *= 10 | ||
| 1795 | x /= 10 | ||
| 1796 | x %= 10 | ||
| 1797 | s ..= "world" -- will add a new local if local variable is not exist | ||
| 1798 | arg or= "default value" | ||
| 1799 | ``` | ||
| 1800 | |||
| 1801 | <YueDisplay> | ||
| 1802 | |||
| 1803 | ```yue | ||
| 1804 | x = 1 | ||
| 1805 | x += 1 | ||
| 1806 | x -= 1 | ||
| 1807 | x *= 10 | ||
| 1808 | x /= 10 | ||
| 1809 | x %= 10 | ||
| 1810 | s ..= "world" -- will add a new local if local variable is not exist | ||
| 1811 | arg or= "default value" | ||
| 1812 | ``` | ||
| 1813 | |||
| 1814 | </YueDisplay> | ||
| 1815 | |||
| 1816 | ## Chaining Assignment | ||
| 1817 | |||
| 1818 | You can do chaining assignment to assign multiple items to hold the same value. | ||
| 1819 | |||
| 1820 | ```yuescript | ||
| 1821 | a = b = c = d = e = 0 | ||
| 1822 | x = y = z = f! | ||
| 1823 | ``` | ||
| 1824 | |||
| 1825 | <YueDisplay> | ||
| 1826 | |||
| 1827 | ```yue | ||
| 1828 | a = b = c = d = e = 0 | ||
| 1829 | x = y = z = f! | ||
| 1830 | ``` | ||
| 1831 | |||
| 1832 | </YueDisplay> | ||
| 1833 | |||
| 1834 | ## Explicit Locals | ||
| 1835 | |||
| 1836 | ```yuescript | ||
| 1837 | do | ||
| 1838 | local a = 1 | ||
| 1839 | local * | ||
| 1840 | print "forward declare all variables as locals" | ||
| 1841 | x = -> 1 + y + z | ||
| 1842 | y, z = 2, 3 | ||
| 1843 | global instance = Item\new! | ||
| 1844 | |||
| 1845 | do | ||
| 1846 | local X = 1 | ||
| 1847 | local ^ | ||
| 1848 | print "only forward declare upper case variables" | ||
| 1849 | a = 1 | ||
| 1850 | B = 2 | ||
| 1851 | ``` | ||
| 1852 | |||
| 1853 | <YueDisplay> | ||
| 1854 | |||
| 1855 | ```yue | ||
| 1856 | do | ||
| 1857 | local a = 1 | ||
| 1858 | local * | ||
| 1859 | print "forward declare all variables as locals" | ||
| 1860 | x = -> 1 + y + z | ||
| 1861 | y, z = 2, 3 | ||
| 1862 | global instance = Item\new! | ||
| 1863 | |||
| 1864 | do | ||
| 1865 | local X = 1 | ||
| 1866 | local ^ | ||
| 1867 | print "only forward declare upper case variables" | ||
| 1868 | a = 1 | ||
| 1869 | B = 2 | ||
| 1870 | ``` | ||
| 1871 | |||
| 1872 | </YueDisplay> | ||
| 1873 | |||
| 1874 | ## Explicit Globals | ||
| 1875 | |||
| 1876 | ```yuescript | ||
| 1877 | do | ||
| 1878 | global a = 1 | ||
| 1879 | global * | ||
| 1880 | print "declare all variables as globals" | ||
| 1881 | x = -> 1 + y + z | ||
| 1882 | y, z = 2, 3 | ||
| 1883 | |||
| 1884 | do | ||
| 1885 | global X = 1 | ||
| 1886 | global ^ | ||
| 1887 | print "only declare upper case variables as globals" | ||
| 1888 | a = 1 | ||
| 1889 | B = 2 | ||
| 1890 | local Temp = "a local value" | ||
| 1891 | ``` | ||
| 1892 | |||
| 1893 | <YueDisplay> | ||
| 1894 | |||
| 1895 | ```yue | ||
| 1896 | do | ||
| 1897 | global a = 1 | ||
| 1898 | global * | ||
| 1899 | print "declare all variables as globals" | ||
| 1900 | x = -> 1 + y + z | ||
| 1901 | y, z = 2, 3 | ||
| 1902 | |||
| 1903 | do | ||
| 1904 | global X = 1 | ||
| 1905 | global ^ | ||
| 1906 | print "only declare upper case variables as globals" | ||
| 1907 | a = 1 | ||
| 1908 | B = 2 | ||
| 1909 | local Temp = "a local value" | ||
| 1910 | ``` | ||
| 1911 | |||
| 1912 | </YueDisplay> | ||
| 1913 | |||
| 1914 | # Varargs Assignment | ||
| 1915 | |||
| 1916 | You can assign the results returned from a function to a varargs symbol `...`. And then access its content using the Lua way. | ||
| 1917 | |||
| 1918 | ```yuescript | ||
| 1919 | list = [1, 2, 3, 4, 5] | ||
| 1920 | fn = (ok) -> ok, table.unpack list | ||
| 1921 | ok, ... = fn true | ||
| 1922 | count = select '#', ... | ||
| 1923 | first = select 1, ... | ||
| 1924 | print ok, count, first | ||
| 1925 | ``` | ||
| 1926 | |||
| 1927 | <YueDisplay> | ||
| 1928 | |||
| 1929 | ```yue | ||
| 1930 | list = [1, 2, 3, 4, 5] | ||
| 1931 | fn = (ok) -> ok, table.unpack list | ||
| 1932 | ok, ... = fn true | ||
| 1933 | count = select '#', ... | ||
| 1934 | first = select 1, ... | ||
| 1935 | print ok, count, first | ||
| 1936 | ``` | ||
| 1937 | |||
| 1938 | </YueDisplay> | ||
| 1939 | |||
| 1940 | # If Assignment | ||
| 1941 | |||
| 1942 | `if` and `elseif` blocks can take an assignment in place of a conditional expression. Upon evaluating the conditional, the assignment will take place and the value that was assigned to will be used as the conditional expression. The assigned variable is only in scope for the body of the conditional, meaning it is never available if the value is not truthy. And you have to use "the walrus operator" `:=` instead of `=` to do assignment. | ||
| 1943 | |||
| 1944 | ```yuescript | ||
| 1945 | if user := database.find_user "moon" | ||
| 1946 | print user.name | ||
| 1947 | ``` | ||
| 1948 | |||
| 1949 | <YueDisplay> | ||
| 1950 | |||
| 1951 | ```yue | ||
| 1952 | if user := database.find_user "moon" | ||
| 1953 | print user.name | ||
| 1954 | ``` | ||
| 1955 | |||
| 1956 | </YueDisplay> | ||
| 1957 | |||
| 1958 | ```yuescript | ||
| 1959 | if hello := os.getenv "hello" | ||
| 1960 | print "You have hello", hello | ||
| 1961 | elseif world := os.getenv "world" | ||
| 1962 | print "you have world", world | ||
| 1963 | else | ||
| 1964 | print "nothing :(" | ||
| 1965 | ``` | ||
| 1966 | |||
| 1967 | <YueDisplay> | ||
| 1968 | |||
| 1969 | ```yue | ||
| 1970 | if hello := os.getenv "hello" | ||
| 1971 | print "You have hello", hello | ||
| 1972 | elseif world := os.getenv "world" | ||
| 1973 | print "you have world", world | ||
| 1974 | else | ||
| 1975 | print "nothing :(" | ||
| 1976 | ``` | ||
| 1977 | |||
| 1978 | </YueDisplay> | ||
| 1979 | |||
| 1980 | If assignment with multiple return values. Only the first value is getting checked, other values are scoped. | ||
| 1981 | |||
| 1982 | ```yuescript | ||
| 1983 | if success, result := pcall -> "get result without problems" | ||
| 1984 | print result -- variable result is scoped | ||
| 1985 | print "OK" | ||
| 1986 | ``` | ||
| 1987 | |||
| 1988 | <YueDisplay> | ||
| 1989 | |||
| 1990 | ```yue | ||
| 1991 | if success, result := pcall -> "get result without problems" | ||
| 1992 | print result -- variable result is scoped | ||
| 1993 | print "OK" | ||
| 1994 | ``` | ||
| 1995 | |||
| 1996 | </YueDisplay> | ||
| 1997 | |||
| 1998 | ## While Assignment | ||
| 1999 | |||
| 2000 | You can also use if assignment in a while loop to get the value as the loop condition. | ||
| 2001 | |||
| 2002 | ```yuescript | ||
| 2003 | while byte := stream\read_one! | ||
| 2004 | -- do something with the byte | ||
| 2005 | print byte | ||
| 2006 | ``` | ||
| 2007 | |||
| 2008 | <YueDisplay> | ||
| 2009 | |||
| 2010 | ```yue | ||
| 2011 | while byte := stream\read_one! | ||
| 2012 | -- do something with the byte | ||
| 2013 | print byte | ||
| 2014 | ``` | ||
| 2015 | |||
| 2016 | </YueDisplay> | ||
| 2017 | |||
| 2018 | # Destructuring Assignment | ||
| 2019 | |||
| 2020 | Destructuring assignment is a way to quickly extract values from a table by their name or position in array based tables. | ||
| 2021 | |||
| 2022 | Typically when you see a table literal, {1,2,3}, it is on the right hand side of an assignment because it is a value. Destructuring assignment swaps the role of the table literal, and puts it on the left hand side of an assign statement. | ||
| 2023 | |||
| 2024 | This is best explained with examples. Here is how you would unpack the first two values from a table: | ||
| 2025 | |||
| 2026 | ```yuescript | ||
| 2027 | thing = [1, 2] | ||
| 2028 | |||
| 2029 | [a, b] = thing | ||
| 2030 | print a, b | ||
| 2031 | ``` | ||
| 2032 | |||
| 2033 | <YueDisplay> | ||
| 2034 | |||
| 2035 | ```yue | ||
| 2036 | thing = [1, 2] | ||
| 2037 | |||
| 2038 | [a, b] = thing | ||
| 2039 | print a, b | ||
| 2040 | ``` | ||
| 2041 | |||
| 2042 | </YueDisplay> | ||
| 2043 | |||
| 2044 | In the destructuring table literal, the key represents the key to read from the right hand side, and the value represents the name the read value will be assigned to. | ||
| 2045 | |||
| 2046 | ```yuescript | ||
| 2047 | obj = { | ||
| 2048 | hello: "world" | ||
| 2049 | day: "tuesday" | ||
| 2050 | length: 20 | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | {hello: hello, day: the_day} = obj | ||
| 2054 | print hello, the_day | ||
| 2055 | |||
| 2056 | :day = obj -- OK to do simple destructuring without braces | ||
| 2057 | ``` | ||
| 2058 | |||
| 2059 | <YueDisplay> | ||
| 2060 | |||
| 2061 | ```yue | ||
| 2062 | obj = { | ||
| 2063 | hello: "world" | ||
| 2064 | day: "tuesday" | ||
| 2065 | length: 20 | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | {hello: hello, day: the_day} = obj | ||
| 2069 | print hello, the_day | ||
| 2070 | |||
| 2071 | :day = obj -- OK to do simple destructuring without braces | ||
| 2072 | ``` | ||
| 2073 | |||
| 2074 | </YueDisplay> | ||
| 2075 | |||
| 2076 | This also works with nested data structures as well: | ||
| 2077 | |||
| 2078 | ```yuescript | ||
| 2079 | obj2 = { | ||
| 2080 | numbers: [1, 2, 3, 4] | ||
| 2081 | properties: { | ||
| 2082 | color: "green" | ||
| 2083 | height: 13.5 | ||
| 2084 | } | ||
| 2085 | } | ||
| 2086 | |||
| 2087 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2088 | print first, second, color | ||
| 2089 | ``` | ||
| 2090 | |||
| 2091 | <YueDisplay> | ||
| 2092 | |||
| 2093 | ```yue | ||
| 2094 | obj2 = { | ||
| 2095 | numbers: [1, 2, 3, 4] | ||
| 2096 | properties: { | ||
| 2097 | color: "green" | ||
| 2098 | height: 13.5 | ||
| 2099 | } | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2103 | print first, second, color | ||
| 2104 | ``` | ||
| 2105 | |||
| 2106 | </YueDisplay> | ||
| 2107 | |||
| 2108 | If the destructuring statement is complicated, feel free to spread it out over a few lines. A slightly more complicated example: | ||
| 2109 | |||
| 2110 | ```yuescript | ||
| 2111 | { | ||
| 2112 | numbers: [first, second] | ||
| 2113 | properties: { | ||
| 2114 | color: color | ||
| 2115 | } | ||
| 2116 | } = obj2 | ||
| 2117 | ``` | ||
| 2118 | |||
| 2119 | <YueDisplay> | ||
| 2120 | |||
| 2121 | ```yue | ||
| 2122 | { | ||
| 2123 | numbers: [first, second] | ||
| 2124 | properties: { | ||
| 2125 | color: color | ||
| 2126 | } | ||
| 2127 | } = obj2 | ||
| 2128 | ``` | ||
| 2129 | |||
| 2130 | </YueDisplay> | ||
| 2131 | |||
| 2132 | It'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: | ||
| 2133 | |||
| 2134 | ```yuescript | ||
| 2135 | {:concat, :insert} = table | ||
| 2136 | ``` | ||
| 2137 | |||
| 2138 | <YueDisplay> | ||
| 2139 | |||
| 2140 | ```yue | ||
| 2141 | {:concat, :insert} = table | ||
| 2142 | ``` | ||
| 2143 | |||
| 2144 | </YueDisplay> | ||
| 2145 | |||
| 2146 | This is effectively the same as import, but we can rename fields we want to extract by mixing the syntax: | ||
| 2147 | |||
| 2148 | ```yuescript | ||
| 2149 | {:mix, :max, random: rand} = math | ||
| 2150 | ``` | ||
| 2151 | |||
| 2152 | <YueDisplay> | ||
| 2153 | |||
| 2154 | ```yue | ||
| 2155 | {:mix, :max, random: rand} = math | ||
| 2156 | ``` | ||
| 2157 | |||
| 2158 | </YueDisplay> | ||
| 2159 | |||
| 2160 | You can write default values while doing destructuring like: | ||
| 2161 | |||
| 2162 | ```yuescript | ||
| 2163 | {:name = "nameless", :job = "jobless"} = person | ||
| 2164 | ``` | ||
| 2165 | |||
| 2166 | <YueDisplay> | ||
| 2167 | |||
| 2168 | ```yue | ||
| 2169 | {:name = "nameless", :job = "jobless"} = person | ||
| 2170 | ``` | ||
| 2171 | |||
| 2172 | </YueDisplay> | ||
| 2173 | |||
| 2174 | You can use `_` as placeholder when doing a list destructuring: | ||
| 2175 | |||
| 2176 | ```yuescript | ||
| 2177 | [_, two, _, four] = items | ||
| 2178 | ``` | ||
| 2179 | |||
| 2180 | <YueDisplay> | ||
| 2181 | |||
| 2182 | ```yue | ||
| 2183 | [_, two, _, four] = items | ||
| 2184 | ``` | ||
| 2185 | |||
| 2186 | </YueDisplay> | ||
| 2187 | |||
| 2188 | ## Range Destructuring | ||
| 2189 | |||
| 2190 | You 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. | ||
| 2191 | |||
| 2192 | ```yuescript | ||
| 2193 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2194 | [first, ...bulk, last] = orders | ||
| 2195 | print first -- prints: first | ||
| 2196 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 2197 | print last -- prints: last | ||
| 2198 | ``` | ||
| 2199 | |||
| 2200 | <YueDisplay> | ||
| 2201 | |||
| 2202 | ```yue | ||
| 2203 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2204 | [first, ...bulk, last] = orders | ||
| 2205 | print first -- prints: first | ||
| 2206 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 2207 | print last -- prints: last | ||
| 2208 | ``` | ||
| 2209 | |||
| 2210 | </YueDisplay> | ||
| 2211 | |||
| 2212 | The 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: | ||
| 2213 | |||
| 2214 | ```yuescript | ||
| 2215 | -- Capture everything after first element | ||
| 2216 | [first, ...rest] = orders | ||
| 2217 | |||
| 2218 | -- Capture everything before last element | ||
| 2219 | [...start, last] = orders | ||
| 2220 | |||
| 2221 | -- Capture things except the middle elements | ||
| 2222 | [first, ..._, last] = orders | ||
| 2223 | ``` | ||
| 2224 | |||
| 2225 | <YueDisplay> | ||
| 2226 | |||
| 2227 | ```yue | ||
| 2228 | -- Capture everything after first element | ||
| 2229 | [first, ...rest] = orders | ||
| 2230 | |||
| 2231 | -- Capture everything before last element | ||
| 2232 | [...start, last] = orders | ||
| 2233 | |||
| 2234 | -- Capture things except the middle elements | ||
| 2235 | [first, ..._, last] = orders | ||
| 2236 | ``` | ||
| 2237 | |||
| 2238 | </YueDisplay> | ||
| 2239 | |||
| 2240 | ## Destructuring In Other Places | ||
| 2241 | |||
| 2242 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | ||
| 2243 | |||
| 2244 | ```yuescript | ||
| 2245 | tuples = [ | ||
| 2246 | ["hello", "world"] | ||
| 2247 | ["egg", "head"] | ||
| 2248 | ] | ||
| 2249 | |||
| 2250 | for [left, right] in *tuples | ||
| 2251 | print left, right | ||
| 2252 | ``` | ||
| 2253 | |||
| 2254 | <YueDisplay> | ||
| 2255 | |||
| 2256 | ```yue | ||
| 2257 | tuples = [ | ||
| 2258 | ["hello", "world"] | ||
| 2259 | ["egg", "head"] | ||
| 2260 | ] | ||
| 2261 | |||
| 2262 | for [left, right] in *tuples | ||
| 2263 | print left, right | ||
| 2264 | ``` | ||
| 2265 | |||
| 2266 | </YueDisplay> | ||
| 2267 | |||
| 2268 | We know each element in the array table is a two item tuple, so we can unpack it directly in the names clause of the for statement using a destructure. | ||
| 2269 | |||
| 2270 | # The Using Clause; Controlling Destructive Assignment | ||
| 2271 | |||
| 2272 | While lexical scoping can be a great help in reducing the complexity of the code we write, things can get unwieldy as the code size increases. Consider the following snippet: | ||
| 2273 | |||
| 2274 | ```yuescript | ||
| 2275 | i = 100 | ||
| 2276 | |||
| 2277 | -- many lines of code... | ||
| 2278 | |||
| 2279 | my_func = -> | ||
| 2280 | i = 10 | ||
| 2281 | while i > 0 | ||
| 2282 | print i | ||
| 2283 | i -= 1 | ||
| 2284 | |||
| 2285 | my_func! | ||
| 2286 | |||
| 2287 | print i -- will print 0 | ||
| 2288 | ``` | ||
| 2289 | |||
| 2290 | <YueDisplay> | ||
| 2291 | |||
| 2292 | ```yue | ||
| 2293 | i = 100 | ||
| 2294 | |||
| 2295 | -- many lines of code... | ||
| 2296 | |||
| 2297 | my_func = -> | ||
| 2298 | i = 10 | ||
| 2299 | while i > 0 | ||
| 2300 | print i | ||
| 2301 | i -= 1 | ||
| 2302 | |||
| 2303 | my_func! | ||
| 2304 | |||
| 2305 | print i -- will print 0 | ||
| 2306 | ``` | ||
| 2307 | |||
| 2308 | </YueDisplay> | ||
| 2309 | |||
| 2310 | In 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. | ||
| 2311 | |||
| 2312 | It 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. | ||
| 2313 | |||
| 2314 | The using keyword lets us do that. using nil makes sure that no closed variables are overwritten in assignment. The using clause is placed after the argument list in a function, or in place of it if there are no arguments. | ||
| 2315 | |||
| 2316 | ```yuescript | ||
| 2317 | i = 100 | ||
| 2318 | |||
| 2319 | my_func = (using nil) -> | ||
| 2320 | i = "hello" -- a new local variable is created here | ||
| 2321 | |||
| 2322 | my_func! | ||
| 2323 | print i -- prints 100, i is unaffected | ||
| 2324 | ``` | ||
| 2325 | |||
| 2326 | <YueDisplay> | ||
| 2327 | |||
| 2328 | ```yue | ||
| 2329 | i = 100 | ||
| 2330 | |||
| 2331 | my_func = (using nil) -> | ||
| 2332 | i = "hello" -- a new local variable is created here | ||
| 2333 | |||
| 2334 | my_func! | ||
| 2335 | print i -- prints 100, i is unaffected | ||
| 2336 | ``` | ||
| 2337 | |||
| 2338 | </YueDisplay> | ||
| 2339 | |||
| 2340 | Multiple names can be separated by commas. Closure values can still be accessed, they just cant be modified: | ||
| 2341 | |||
| 2342 | ```yuescript | ||
| 2343 | tmp = 1213 | ||
| 2344 | i, k = 100, 50 | ||
| 2345 | |||
| 2346 | my_func = (add using k, i) -> | ||
| 2347 | tmp = tmp + add -- a new local tmp is created | ||
| 2348 | i += tmp | ||
| 2349 | k += tmp | ||
| 2350 | |||
| 2351 | my_func(22) | ||
| 2352 | print i, k -- these have been updated | ||
| 2353 | ``` | ||
| 2354 | |||
| 2355 | <YueDisplay> | ||
| 2356 | |||
| 2357 | ```yue | ||
| 2358 | tmp = 1213 | ||
| 2359 | i, k = 100, 50 | ||
| 2360 | |||
| 2361 | my_func = (add using k, i) -> | ||
| 2362 | tmp = tmp + add -- a new local tmp is created | ||
| 2363 | i += tmp | ||
| 2364 | k += tmp | ||
| 2365 | |||
| 2366 | my_func(22) | ||
| 2367 | print i, k -- these have been updated | ||
| 2368 | ``` | ||
| 2369 | |||
| 2370 | </YueDisplay> | ||
| 2371 | |||
| 2372 | # Usage | ||
| 2373 | |||
| 2374 | ## Lua Module | ||
| 2375 | |||
| 2376 | Use YueScript module in Lua: | ||
| 2377 | |||
| 2378 | - **Case 1** | ||
| 2379 | |||
| 2380 | Require "your_yuescript_entry.yue" in Lua. | ||
| 2381 | |||
| 2382 | ```Lua | ||
| 2383 | require("yue")("your_yuescript_entry") | ||
| 2384 | ``` | ||
| 2385 | |||
| 2386 | 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. | ||
| 2387 | |||
| 2388 | - **Case 2** | ||
| 2389 | |||
| 2390 | Require YueScript module and rewite message by hand. | ||
| 2391 | |||
| 2392 | ```lua | ||
| 2393 | local yue = require("yue") | ||
| 2394 | yue.insert_loader() | ||
| 2395 | local success, result = xpcall(function() | ||
| 2396 | return require("yuescript_module_name") | ||
| 2397 | end, function(err) | ||
| 2398 | return yue.traceback(err) | ||
| 2399 | end) | ||
| 2400 | ``` | ||
| 2401 | |||
| 2402 | - **Case 3** | ||
| 2403 | |||
| 2404 | Use the YueScript compiler function in Lua. | ||
| 2405 | |||
| 2406 | ```lua | ||
| 2407 | local yue = require("yue") | ||
| 2408 | local codes, err, globals = yue.to_lua([[ | ||
| 2409 | f = -> | ||
| 2410 | print "hello world" | ||
| 2411 | f! | ||
| 2412 | ]],{ | ||
| 2413 | implicit_return_root = true, | ||
| 2414 | reserve_line_number = true, | ||
| 2415 | lint_global = true, | ||
| 2416 | space_over_tab = false, | ||
| 2417 | options = { | ||
| 2418 | target = "5.4", | ||
| 2419 | path = "/script" | ||
| 2420 | } | ||
| 2421 | }) | ||
| 2422 | ``` | ||
| 2423 | |||
| 2424 | ## YueScript Tool | ||
| 2425 | |||
| 2426 | Use YueScript tool with: | ||
| 2427 | |||
| 2428 | ```shell | ||
| 2429 | > yue -h | ||
| 2430 | Usage: yue | ||
| 2431 | [options] [<file/directory>] ... | ||
| 2432 | yue -e <code_or_file> [args...] | ||
| 2433 | yue -w [<directory>] [options] | ||
| 2434 | yue - | ||
| 2435 | |||
| 2436 | Notes: | ||
| 2437 | - '-' / '--' must be the first and only argument. | ||
| 2438 | - '-o/--output' can not be used with multiple input files. | ||
| 2439 | - '-w/--watch' can not be used with file input (directory only). | ||
| 2440 | - with '-e/--execute', remaining tokens are treated as script args. | ||
| 2441 | |||
| 2442 | Options: | ||
| 2443 | -h, --help Show this help message and exit. | ||
| 2444 | -e <str>, --execute <str> Execute a file or raw codes | ||
| 2445 | -m, --minify Generate minified codes | ||
| 2446 | -r, --rewrite Rewrite output to match original line numbers | ||
| 2447 | -t <output_to>, --output-to <output_to> | ||
| 2448 | Specify where to place compiled files | ||
| 2449 | -o <file>, --output <file> Write output to file | ||
| 2450 | -p, --print Write output to standard out | ||
| 2451 | -b, --benchmark Dump compile time (doesn't write output) | ||
| 2452 | -g, --globals Dump global variables used in NAME LINE COLUMN | ||
| 2453 | -s, --spaces Use spaces in generated codes instead of tabs | ||
| 2454 | -l, --line-numbers Write line numbers from source codes | ||
| 2455 | -j, --no-implicit-return Disable implicit return at end of file | ||
| 2456 | -c, --reserve-comments Reserve comments before statement from source codes | ||
| 2457 | -w [<dir>], --watch [<dir>] | ||
| 2458 | Watch changes and compile every file under directory | ||
| 2459 | -v, --version Print version | ||
| 2460 | - Read from standard in, print to standard out | ||
| 2461 | (Must be first and only argument) | ||
| 2462 | -- Same as '-' (kept for backward compatibility) | ||
| 2463 | |||
| 2464 | --target <version> Specify the Lua version that codes will be generated to | ||
| 2465 | (version can only be 5.1 to 5.5) | ||
| 2466 | --path <path_str> Append an extra Lua search path string to package.path | ||
| 2467 | --<key>=<value> Pass compiler option in key=value form (existing behavior) | ||
| 2468 | |||
| 2469 | Execute without options to enter REPL, type symbol '$' | ||
| 2470 | in a single line to start/stop multi-line mode | ||
| 2471 | ``` | ||
| 2472 | |||
| 2473 | Use cases: | ||
| 2474 | |||
| 2475 | Recursively compile every YueScript file with extension **.yue** under current path: **yue .** | ||
| 2476 | |||
| 2477 | Compile and save results to a target path: **yue -t /target/path/ .** | ||
| 2478 | |||
| 2479 | Compile and reserve debug info: **yue -l .** | ||
| 2480 | |||
| 2481 | Compile and generate minified codes: **yue -m .** | ||
| 2482 | |||
| 2483 | Execute raw codes: **yue -e 'print 123'** | ||
| 2484 | |||
| 2485 | Execute a YueScript file: **yue -e main.yue** | ||
| 2486 | |||
| 2487 | # Introduction | ||
| 2488 | |||
| 2489 | YueScript is a dynamic language that compiles to Lua. And it's a [MoonScript](https://github.com/leafo/moonscript) dialect. The codes written in YueScript are expressive and extremely concise. And it is suitable for writing some changing application logic with more maintainable codes and runs in a Lua embeded environment such as games or website servers. | ||
| 2490 | |||
| 2491 | Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ]. | ||
| 2492 | |||
| 2493 | ## An Overview of YueScript | ||
| 2494 | |||
| 2495 | ```yuescript | ||
| 2496 | -- import syntax | ||
| 2497 | import p, to_lua from "yue" | ||
| 2498 | |||
| 2499 | -- object literals | ||
| 2500 | inventory = | ||
| 2501 | equipment: | ||
| 2502 | - "sword" | ||
| 2503 | - "shield" | ||
| 2504 | items: | ||
| 2505 | - name: "potion" | ||
| 2506 | count: 10 | ||
| 2507 | - name: "bread" | ||
| 2508 | count: 3 | ||
| 2509 | |||
| 2510 | -- list comprehension | ||
| 2511 | map = (arr, action) -> | ||
| 2512 | [action item for item in *arr] | ||
| 2513 | |||
| 2514 | filter = (arr, cond) -> | ||
| 2515 | [item for item in *arr when cond item] | ||
| 2516 | |||
| 2517 | reduce = (arr, init, action): init -> | ||
| 2518 | init = action init, item for item in *arr | ||
| 2519 | |||
| 2520 | -- pipe operator | ||
| 2521 | [1, 2, 3] | ||
| 2522 | |> map (x) -> x * 2 | ||
| 2523 | |> filter (x) -> x > 4 | ||
| 2524 | |> reduce 0, (a, b) -> a + b | ||
| 2525 | |||
| 2526 | |||
| 2527 | -- metatable manipulation | ||
| 2528 | apple = | ||
| 2529 | size: 15 | ||
| 2530 | <index>: | ||
| 2531 | color: 0x00ffff | ||
| 2532 | |||
| 2533 | with apple | ||
| 2534 | p .size, .color, .<index> if .<>? | ||
| 2535 | |||
| 2536 | -- js-like export syntax | ||
| 2537 | export 🌛 = "Script of Moon" | ||
| 2538 | ``` | ||
| 2539 | |||
| 2540 | <YueDisplay> | ||
| 2541 | |||
| 2542 | ```yue | ||
| 2543 | -- import syntax | ||
| 2544 | import p, to_lua from "yue" | ||
| 2545 | |||
| 2546 | -- object literals | ||
| 2547 | inventory = | ||
| 2548 | equipment: | ||
| 2549 | - "sword" | ||
| 2550 | - "shield" | ||
| 2551 | items: | ||
| 2552 | - name: "potion" | ||
| 2553 | count: 10 | ||
| 2554 | - name: "bread" | ||
| 2555 | count: 3 | ||
| 2556 | |||
| 2557 | -- list comprehension | ||
| 2558 | map = (arr, action) -> | ||
| 2559 | [action item for item in *arr] | ||
| 2560 | |||
| 2561 | filter = (arr, cond) -> | ||
| 2562 | [item for item in *arr when cond item] | ||
| 2563 | |||
| 2564 | reduce = (arr, init, action): init -> | ||
| 2565 | init = action init, item for item in *arr | ||
| 2566 | |||
| 2567 | -- pipe operator | ||
| 2568 | [1, 2, 3] | ||
| 2569 | |> map (x) -> x * 2 | ||
| 2570 | |> filter (x) -> x > 4 | ||
| 2571 | |> reduce 0, (a, b) -> a + b | ||
| 2572 | |||
| 2573 | |||
| 2574 | -- metatable manipulation | ||
| 2575 | apple = | ||
| 2576 | size: 15 | ||
| 2577 | <index>: | ||
| 2578 | color: 0x00ffff | ||
| 2579 | |||
| 2580 | with apple | ||
| 2581 | p .size, .color, .<index> if .<>? | ||
| 2582 | |||
| 2583 | -- js-like export syntax | ||
| 2584 | export 🌛 = "Script of Moon" | ||
| 2585 | ``` | ||
| 2586 | |||
| 2587 | </YueDisplay> | ||
| 2588 | |||
| 2589 | ## About Dora SSR | ||
| 2590 | |||
| 2591 | YueScript is being developed and maintained alongside the open-source game engine [Dora SSR](https://github.com/Dora-SSR/Dora-SSR). It has been used to create engine tools, game demos and prototypes, validating its capabilities in real-world scenarios while enhancing the Dora SSR development experience. | ||
| 2592 | |||
| 2593 | # Installation | ||
| 2594 | |||
| 2595 | ## Lua Module | ||
| 2596 | |||
| 2597 | Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install it as a Lua module and executable with: | ||
| 2598 | |||
| 2599 | ```shell | ||
| 2600 | luarocks install yuescript | ||
| 2601 | ``` | ||
| 2602 | |||
| 2603 | Or you can build `yue.so` file with: | ||
| 2604 | |||
| 2605 | ```shell | ||
| 2606 | make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua | ||
| 2607 | ``` | ||
| 2608 | |||
| 2609 | Then get the binary file from path **bin/shared/yue.so**. | ||
| 2610 | |||
| 2611 | ## Build Binary Tool | ||
| 2612 | |||
| 2613 | Clone this repo, then build and install executable with: | ||
| 2614 | |||
| 2615 | ```shell | ||
| 2616 | make install | ||
| 2617 | ``` | ||
| 2618 | |||
| 2619 | Build YueScript tool without macro feature: | ||
| 2620 | |||
| 2621 | ```shell | ||
| 2622 | make install NO_MACRO=true | ||
| 2623 | ``` | ||
| 2624 | |||
| 2625 | Build YueScript tool without built-in Lua binary: | ||
| 2626 | |||
| 2627 | ```shell | ||
| 2628 | make install NO_LUA=true | ||
| 2629 | ``` | ||
| 2630 | |||
| 2631 | ## Download Precompiled Binary | ||
| 2632 | |||
| 2633 | You can download precompiled binary files, including binary executable files compatible with different Lua versions and library files. | ||
| 2634 | |||
| 2635 | Download precompiled binary files from [here](https://github.com/IppClub/YueScript/releases). | ||
| 2636 | |||
| 2637 | # Conditionals | ||
| 2638 | |||
| 2639 | ```yuescript | ||
| 2640 | have_coins = false | ||
| 2641 | if have_coins | ||
| 2642 | print "Got coins" | ||
| 2643 | else | ||
| 2644 | print "No coins" | ||
| 2645 | ``` | ||
| 2646 | |||
| 2647 | <YueDisplay> | ||
| 2648 | |||
| 2649 | ```yue | ||
| 2650 | have_coins = false | ||
| 2651 | if have_coins | ||
| 2652 | print "Got coins" | ||
| 2653 | else | ||
| 2654 | print "No coins" | ||
| 2655 | ``` | ||
| 2656 | |||
| 2657 | </YueDisplay> | ||
| 2658 | |||
| 2659 | A short syntax for single statements can also be used: | ||
| 2660 | |||
| 2661 | ```yuescript | ||
| 2662 | have_coins = false | ||
| 2663 | if have_coins then print "Got coins" else print "No coins" | ||
| 2664 | ``` | ||
| 2665 | |||
| 2666 | <YueDisplay> | ||
| 2667 | |||
| 2668 | ```yue | ||
| 2669 | have_coins = false | ||
| 2670 | if have_coins then print "Got coins" else print "No coins" | ||
| 2671 | ``` | ||
| 2672 | |||
| 2673 | </YueDisplay> | ||
| 2674 | |||
| 2675 | Because if statements can be used as expressions, this can also be written as: | ||
| 2676 | |||
| 2677 | ```yuescript | ||
| 2678 | have_coins = false | ||
| 2679 | print if have_coins then "Got coins" else "No coins" | ||
| 2680 | ``` | ||
| 2681 | |||
| 2682 | <YueDisplay> | ||
| 2683 | |||
| 2684 | ```yue | ||
| 2685 | have_coins = false | ||
| 2686 | print if have_coins then "Got coins" else "No coins" | ||
| 2687 | ``` | ||
| 2688 | |||
| 2689 | </YueDisplay> | ||
| 2690 | |||
| 2691 | Conditionals can also be used in return statements and assignments: | ||
| 2692 | |||
| 2693 | ```yuescript | ||
| 2694 | is_tall = (name) -> | ||
| 2695 | if name == "Rob" | ||
| 2696 | true | ||
| 2697 | else | ||
| 2698 | false | ||
| 2699 | |||
| 2700 | message = if is_tall "Rob" | ||
| 2701 | "I am very tall" | ||
| 2702 | else | ||
| 2703 | "I am not so tall" | ||
| 2704 | |||
| 2705 | print message -- prints: I am very tall | ||
| 2706 | ``` | ||
| 2707 | |||
| 2708 | <YueDisplay> | ||
| 2709 | |||
| 2710 | ```yue | ||
| 2711 | is_tall = (name) -> | ||
| 2712 | if name == "Rob" | ||
| 2713 | true | ||
| 2714 | else | ||
| 2715 | false | ||
| 2716 | |||
| 2717 | message = if is_tall "Rob" | ||
| 2718 | "I am very tall" | ||
| 2719 | else | ||
| 2720 | "I am not so tall" | ||
| 2721 | |||
| 2722 | print message -- prints: I am very tall | ||
| 2723 | ``` | ||
| 2724 | |||
| 2725 | </YueDisplay> | ||
| 2726 | |||
| 2727 | The opposite of if is unless: | ||
| 2728 | |||
| 2729 | ```yuescript | ||
| 2730 | unless os.date("%A") == "Monday" | ||
| 2731 | print "it is not Monday!" | ||
| 2732 | ``` | ||
| 2733 | |||
| 2734 | <YueDisplay> | ||
| 2735 | |||
| 2736 | ```yue | ||
| 2737 | unless os.date("%A") == "Monday" | ||
| 2738 | print "it is not Monday!" | ||
| 2739 | ``` | ||
| 2740 | |||
| 2741 | </YueDisplay> | ||
| 2742 | |||
| 2743 | ```yuescript | ||
| 2744 | print "You're lucky!" unless math.random! > 0.1 | ||
| 2745 | ``` | ||
| 2746 | |||
| 2747 | <YueDisplay> | ||
| 2748 | |||
| 2749 | ```yue | ||
| 2750 | print "You're lucky!" unless math.random! > 0.1 | ||
| 2751 | ``` | ||
| 2752 | |||
| 2753 | </YueDisplay> | ||
| 2754 | |||
| 2755 | ## In Expression | ||
| 2756 | |||
| 2757 | You can write range checking code with an `in-expression`. | ||
| 2758 | |||
| 2759 | ```yuescript | ||
| 2760 | a = 5 | ||
| 2761 | |||
| 2762 | if a in [1, 3, 5, 7] | ||
| 2763 | print "checking equality with discrete values" | ||
| 2764 | |||
| 2765 | if a in list | ||
| 2766 | print "checking if `a` is in a list" | ||
| 2767 | ``` | ||
| 2768 | |||
| 2769 | <YueDisplay> | ||
| 2770 | |||
| 2771 | ```yue | ||
| 2772 | a = 5 | ||
| 2773 | |||
| 2774 | if a in [1, 3, 5, 7] | ||
| 2775 | print "checking equality with discrete values" | ||
| 2776 | |||
| 2777 | if a in list | ||
| 2778 | print "checking if `a` is in a list" | ||
| 2779 | ``` | ||
| 2780 | |||
| 2781 | </YueDisplay> | ||
| 2782 | |||
| 2783 | # For Loop | ||
| 2784 | |||
| 2785 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | ||
| 2786 | |||
| 2787 | ```yuescript | ||
| 2788 | for i = 10, 20 | ||
| 2789 | print i | ||
| 2790 | |||
| 2791 | for k = 1, 15, 2 -- an optional step provided | ||
| 2792 | print k | ||
| 2793 | |||
| 2794 | for key, value in pairs object | ||
| 2795 | print key, value | ||
| 2796 | ``` | ||
| 2797 | |||
| 2798 | <YueDisplay> | ||
| 2799 | |||
| 2800 | ```yue | ||
| 2801 | for i = 10, 20 | ||
| 2802 | print i | ||
| 2803 | |||
| 2804 | for k = 1, 15, 2 -- an optional step provided | ||
| 2805 | print k | ||
| 2806 | |||
| 2807 | for key, value in pairs object | ||
| 2808 | print key, value | ||
| 2809 | ``` | ||
| 2810 | |||
| 2811 | </YueDisplay> | ||
| 2812 | |||
| 2813 | The slicing and **\*** operators can be used, just like with comprehensions: | ||
| 2814 | |||
| 2815 | ```yuescript | ||
| 2816 | for item in *items[2, 4] | ||
| 2817 | print item | ||
| 2818 | ``` | ||
| 2819 | |||
| 2820 | <YueDisplay> | ||
| 2821 | |||
| 2822 | ```yue | ||
| 2823 | for item in *items[2, 4] | ||
| 2824 | print item | ||
| 2825 | ``` | ||
| 2826 | |||
| 2827 | </YueDisplay> | ||
| 2828 | |||
| 2829 | A shorter syntax is also available for all variations when the body is only a single line: | ||
| 2830 | |||
| 2831 | ```yuescript | ||
| 2832 | for item in *items do print item | ||
| 2833 | |||
| 2834 | for j = 1, 10, 3 do print j | ||
| 2835 | ``` | ||
| 2836 | |||
| 2837 | <YueDisplay> | ||
| 2838 | |||
| 2839 | ```yue | ||
| 2840 | for item in *items do print item | ||
| 2841 | |||
| 2842 | for j = 1, 10, 3 do print j | ||
| 2843 | ``` | ||
| 2844 | |||
| 2845 | </YueDisplay> | ||
| 2846 | |||
| 2847 | A for loop can also be used as an expression. The last statement in the body of the for loop is coerced into an expression and appended to an accumulating array table. | ||
| 2848 | |||
| 2849 | Doubling every even number: | ||
| 2850 | |||
| 2851 | ```yuescript | ||
| 2852 | doubled_evens = for i = 1, 20 | ||
| 2853 | if i % 2 == 0 | ||
| 2854 | i * 2 | ||
| 2855 | else | ||
| 2856 | i | ||
| 2857 | ``` | ||
| 2858 | |||
| 2859 | <YueDisplay> | ||
| 2860 | |||
| 2861 | ```yue | ||
| 2862 | doubled_evens = for i = 1, 20 | ||
| 2863 | if i % 2 == 0 | ||
| 2864 | i * 2 | ||
| 2865 | else | ||
| 2866 | i | ||
| 2867 | ``` | ||
| 2868 | |||
| 2869 | </YueDisplay> | ||
| 2870 | |||
| 2871 | In addition, for loops support break with return values, allowing the loop itself to be used as an expression that exits early with meaningful results. | ||
| 2872 | |||
| 2873 | For example, to find the first number greater than 10: | ||
| 2874 | |||
| 2875 | ```yuescript | ||
| 2876 | first_large = for n in *numbers | ||
| 2877 | break n if n > 10 | ||
| 2878 | ``` | ||
| 2879 | |||
| 2880 | <YueDisplay> | ||
| 2881 | |||
| 2882 | ```yue | ||
| 2883 | first_large = for n in *numbers | ||
| 2884 | break n if n > 10 | ||
| 2885 | ``` | ||
| 2886 | |||
| 2887 | </YueDisplay> | ||
| 2888 | |||
| 2889 | This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions. | ||
| 2890 | |||
| 2891 | For loop expressions can break with multiple values: | ||
| 2892 | |||
| 2893 | ```yuescript | ||
| 2894 | key, score = for k, v in pairs data | ||
| 2895 | break k, v * 10 if k == "target" | ||
| 2896 | ``` | ||
| 2897 | |||
| 2898 | <YueDisplay> | ||
| 2899 | |||
| 2900 | ```yue | ||
| 2901 | key, score = for k, v in pairs data | ||
| 2902 | break k, v * 10 if k == "target" | ||
| 2903 | ``` | ||
| 2904 | |||
| 2905 | </YueDisplay> | ||
| 2906 | |||
| 2907 | You can also filter values by combining the for loop expression with the continue statement. | ||
| 2908 | |||
| 2909 | For 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. | ||
| 2910 | |||
| 2911 | ```yuescript | ||
| 2912 | func_a = -> for i = 1, 10 do print i | ||
| 2913 | func_b = -> return for i = 1, 10 do i | ||
| 2914 | |||
| 2915 | print func_a! -- prints nil | ||
| 2916 | print func_b! -- prints table object | ||
| 2917 | ``` | ||
| 2918 | |||
| 2919 | <YueDisplay> | ||
| 2920 | |||
| 2921 | ```yue | ||
| 2922 | func_a = -> for i = 1, 10 do print i | ||
| 2923 | func_b = -> return for i = 1, 10 do i | ||
| 2924 | |||
| 2925 | print func_a! -- prints nil | ||
| 2926 | print func_b! -- prints table object | ||
| 2927 | ``` | ||
| 2928 | |||
| 2929 | </YueDisplay> | ||
| 2930 | |||
| 2931 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. | ||
| 2932 | |||
| 2933 | # Continue | ||
| 2934 | |||
| 2935 | A continue statement can be used to skip the current iteration in a loop. | ||
| 2936 | |||
| 2937 | ```yuescript | ||
| 2938 | i = 0 | ||
| 2939 | while i < 10 | ||
| 2940 | i += 1 | ||
| 2941 | continue if i % 2 == 0 | ||
| 2942 | print i | ||
| 2943 | ``` | ||
| 2944 | |||
| 2945 | <YueDisplay> | ||
| 2946 | |||
| 2947 | ```yue | ||
| 2948 | i = 0 | ||
| 2949 | while i < 10 | ||
| 2950 | i += 1 | ||
| 2951 | continue if i % 2 == 0 | ||
| 2952 | print i | ||
| 2953 | ``` | ||
| 2954 | |||
| 2955 | </YueDisplay> | ||
| 2956 | |||
| 2957 | continue can also be used with loop expressions to prevent that iteration from accumulating into the result. This examples filters the array table into just even numbers: | ||
| 2958 | |||
| 2959 | ```yuescript | ||
| 2960 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2961 | odds = for x in *my_numbers | ||
| 2962 | continue if x % 2 == 1 | ||
| 2963 | x | ||
| 2964 | ``` | ||
| 2965 | |||
| 2966 | <YueDisplay> | ||
| 2967 | |||
| 2968 | ```yue | ||
| 2969 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2970 | odds = for x in *my_numbers | ||
| 2971 | continue if x % 2 == 1 | ||
| 2972 | x | ||
| 2973 | ``` | ||
| 2974 | |||
| 2975 | </YueDisplay> | ||
| 2976 | |||
| 2977 | # Switch | ||
| 2978 | |||
| 2979 | The 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. | ||
| 2980 | |||
| 2981 | ```yuescript | ||
| 2982 | switch name := "Dan" | ||
| 2983 | when "Robert" | ||
| 2984 | print "You are Robert" | ||
| 2985 | when "Dan", "Daniel" | ||
| 2986 | print "Your name, it's Dan" | ||
| 2987 | else | ||
| 2988 | print "I don't know about you with name #{name}" | ||
| 2989 | ``` | ||
| 2990 | |||
| 2991 | <YueDisplay> | ||
| 2992 | |||
| 2993 | ```yue | ||
| 2994 | switch name := "Dan" | ||
| 2995 | when "Robert" | ||
| 2996 | print "You are Robert" | ||
| 2997 | when "Dan", "Daniel" | ||
| 2998 | print "Your name, it's Dan" | ||
| 2999 | else | ||
| 3000 | print "I don't know about you with name #{name}" | ||
| 3001 | ``` | ||
| 3002 | |||
| 3003 | </YueDisplay> | ||
| 3004 | |||
| 3005 | A switch when clause can match against multiple values by listing them out comma separated. | ||
| 3006 | |||
| 3007 | Switches can be used as expressions as well, here we can assign the result of the switch to a variable: | ||
| 3008 | |||
| 3009 | ```yuescript | ||
| 3010 | b = 1 | ||
| 3011 | next_number = switch b | ||
| 3012 | when 1 | ||
| 3013 | 2 | ||
| 3014 | when 2 | ||
| 3015 | 3 | ||
| 3016 | else | ||
| 3017 | error "can't count that high!" | ||
| 3018 | ``` | ||
| 3019 | |||
| 3020 | <YueDisplay> | ||
| 3021 | |||
| 3022 | ```yue | ||
| 3023 | b = 1 | ||
| 3024 | next_number = switch b | ||
| 3025 | when 1 | ||
| 3026 | 2 | ||
| 3027 | when 2 | ||
| 3028 | 3 | ||
| 3029 | else | ||
| 3030 | error "can't count that high!" | ||
| 3031 | ``` | ||
| 3032 | |||
| 3033 | </YueDisplay> | ||
| 3034 | |||
| 3035 | We 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. | ||
| 3036 | |||
| 3037 | ```yuescript | ||
| 3038 | msg = switch math.random(1, 5) | ||
| 3039 | when 1 then "you are lucky" | ||
| 3040 | when 2 then "you are almost lucky" | ||
| 3041 | else "not so lucky" | ||
| 3042 | ``` | ||
| 3043 | |||
| 3044 | <YueDisplay> | ||
| 3045 | |||
| 3046 | ```yue | ||
| 3047 | msg = switch math.random(1, 5) | ||
| 3048 | when 1 then "you are lucky" | ||
| 3049 | when 2 then "you are almost lucky" | ||
| 3050 | else "not so lucky" | ||
| 3051 | ``` | ||
| 3052 | |||
| 3053 | </YueDisplay> | ||
| 3054 | |||
| 3055 | If you want to write code with one less indent when writing a switch statement, you can put the first when clause on the statement start line, and then all other clauses can be written with one less indent. | ||
| 3056 | |||
| 3057 | ```yuescript | ||
| 3058 | switch math.random(1, 5) | ||
| 3059 | when 1 | ||
| 3060 | print "you are lucky" -- two indents | ||
| 3061 | else | ||
| 3062 | print "not so lucky" | ||
| 3063 | |||
| 3064 | switch math.random(1, 5) when 1 | ||
| 3065 | print "you are lucky" -- one indent | ||
| 3066 | else | ||
| 3067 | print "not so lucky" | ||
| 3068 | ``` | ||
| 3069 | |||
| 3070 | <YueDisplay> | ||
| 3071 | |||
| 3072 | ```yue | ||
| 3073 | switch math.random(1, 5) | ||
| 3074 | when 1 | ||
| 3075 | print "you are lucky" -- two indents | ||
| 3076 | else | ||
| 3077 | print "not so lucky" | ||
| 3078 | |||
| 3079 | switch math.random(1, 5) when 1 | ||
| 3080 | print "you are lucky" -- one indent | ||
| 3081 | else | ||
| 3082 | print "not so lucky" | ||
| 3083 | ``` | ||
| 3084 | |||
| 3085 | </YueDisplay> | ||
| 3086 | |||
| 3087 | It 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. | ||
| 3088 | |||
| 3089 | ## Table Matching | ||
| 3090 | |||
| 3091 | You can do table matching in a switch when clause, if the table can be destructured by a specific structure and get non-nil values. | ||
| 3092 | |||
| 3093 | ```yuescript | ||
| 3094 | items = | ||
| 3095 | * x: 100 | ||
| 3096 | y: 200 | ||
| 3097 | * width: 300 | ||
| 3098 | height: 400 | ||
| 3099 | |||
| 3100 | for item in *items | ||
| 3101 | switch item | ||
| 3102 | when :x, :y | ||
| 3103 | print "Vec2 #{x}, #{y}" | ||
| 3104 | when :width, :height | ||
| 3105 | print "size #{width}, #{height}" | ||
| 3106 | ``` | ||
| 3107 | |||
| 3108 | <YueDisplay> | ||
| 3109 | |||
| 3110 | ```yue | ||
| 3111 | items = | ||
| 3112 | * x: 100 | ||
| 3113 | y: 200 | ||
| 3114 | * width: 300 | ||
| 3115 | height: 400 | ||
| 3116 | |||
| 3117 | for item in *items | ||
| 3118 | switch item | ||
| 3119 | when :x, :y | ||
| 3120 | print "Vec2 #{x}, #{y}" | ||
| 3121 | when :width, :height | ||
| 3122 | print "size #{width}, #{height}" | ||
| 3123 | ``` | ||
| 3124 | |||
| 3125 | </YueDisplay> | ||
| 3126 | |||
| 3127 | You can use default values to optionally destructure the table for some fields. | ||
| 3128 | |||
| 3129 | ```yuescript | ||
| 3130 | item = {} | ||
| 3131 | |||
| 3132 | {pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos') | ||
| 3133 | |||
| 3134 | switch item | ||
| 3135 | when {pos: {:x = 50, :y = 200}} | ||
| 3136 | print "Vec2 #{x}, #{y}" -- table destructuring will still pass | ||
| 3137 | ``` | ||
| 3138 | |||
| 3139 | <YueDisplay> | ||
| 3140 | |||
| 3141 | ```yue | ||
| 3142 | item = {} | ||
| 3143 | |||
| 3144 | {pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos') | ||
| 3145 | |||
| 3146 | switch item | ||
| 3147 | when {pos: {:x = 50, :y = 200}} | ||
| 3148 | print "Vec2 #{x}, #{y}" -- table destructuring will still pass | ||
| 3149 | ``` | ||
| 3150 | |||
| 3151 | </YueDisplay> | ||
| 3152 | |||
| 3153 | You can also match against array elements, table fields, and even nested structures with array or table literals. | ||
| 3154 | |||
| 3155 | Match against array elements. | ||
| 3156 | |||
| 3157 | ```yuescript | ||
| 3158 | switch tb | ||
| 3159 | when [1, 2, 3] | ||
| 3160 | print "1, 2, 3" | ||
| 3161 | when [1, b, 3] | ||
| 3162 | print "1, #{b}, 3" | ||
| 3163 | when [1, 2, b = 3] -- b has a default value | ||
| 3164 | print "1, 2, #{b}" | ||
| 3165 | ``` | ||
| 3166 | |||
| 3167 | <YueDisplay> | ||
| 3168 | |||
| 3169 | ```yue | ||
| 3170 | switch tb | ||
| 3171 | when [1, 2, 3] | ||
| 3172 | print "1, 2, 3" | ||
| 3173 | when [1, b, 3] | ||
| 3174 | print "1, #{b}, 3" | ||
| 3175 | when [1, 2, b = 3] -- b has a default value | ||
| 3176 | print "1, 2, #{b}" | ||
| 3177 | ``` | ||
| 3178 | |||
| 3179 | </YueDisplay> | ||
| 3180 | |||
| 3181 | Match against table fields with destructuring. | ||
| 3182 | |||
| 3183 | ```yuescript | ||
| 3184 | switch tb | ||
| 3185 | when success: true, :result | ||
| 3186 | print "success", result | ||
| 3187 | when success: false | ||
| 3188 | print "failed", result | ||
| 3189 | else | ||
| 3190 | print "invalid" | ||
| 3191 | ``` | ||
| 3192 | |||
| 3193 | <YueDisplay> | ||
| 3194 | |||
| 3195 | ```yue | ||
| 3196 | switch tb | ||
| 3197 | when success: true, :result | ||
| 3198 | print "success", result | ||
| 3199 | when success: false | ||
| 3200 | print "failed", result | ||
| 3201 | else | ||
| 3202 | print "invalid" | ||
| 3203 | ``` | ||
| 3204 | |||
| 3205 | </YueDisplay> | ||
| 3206 | |||
| 3207 | Match against nested table structures. | ||
| 3208 | |||
| 3209 | ```yuescript | ||
| 3210 | switch tb | ||
| 3211 | when data: {type: "success", :content} | ||
| 3212 | print "success", content | ||
| 3213 | when data: {type: "error", :content} | ||
| 3214 | print "failed", content | ||
| 3215 | else | ||
| 3216 | print "invalid" | ||
| 3217 | ``` | ||
| 3218 | |||
| 3219 | <YueDisplay> | ||
| 3220 | |||
| 3221 | ```yue | ||
| 3222 | switch tb | ||
| 3223 | when data: {type: "success", :content} | ||
| 3224 | print "success", content | ||
| 3225 | when data: {type: "error", :content} | ||
| 3226 | print "failed", content | ||
| 3227 | else | ||
| 3228 | print "invalid" | ||
| 3229 | ``` | ||
| 3230 | |||
| 3231 | </YueDisplay> | ||
| 3232 | |||
| 3233 | Match against array of tables. | ||
| 3234 | |||
| 3235 | ```yuescript | ||
| 3236 | switch tb | ||
| 3237 | when [ | ||
| 3238 | {a: 1, b: 2} | ||
| 3239 | {a: 3, b: 4} | ||
| 3240 | {a: 5, b: 6} | ||
| 3241 | fourth | ||
| 3242 | ] | ||
| 3243 | print "matched", fourth | ||
| 3244 | ``` | ||
| 3245 | |||
| 3246 | <YueDisplay> | ||
| 3247 | |||
| 3248 | ```yue | ||
| 3249 | switch tb | ||
| 3250 | when [ | ||
| 3251 | {a: 1, b: 2} | ||
| 3252 | {a: 3, b: 4} | ||
| 3253 | {a: 5, b: 6} | ||
| 3254 | fourth | ||
| 3255 | ] | ||
| 3256 | print "matched", fourth | ||
| 3257 | ``` | ||
| 3258 | |||
| 3259 | </YueDisplay> | ||
| 3260 | |||
| 3261 | Match against a list and capture a range of elements. | ||
| 3262 | |||
| 3263 | ```yuescript | ||
| 3264 | segments = ["admin", "users", "logs", "view"] | ||
| 3265 | switch segments | ||
| 3266 | when [...groups, resource, action] | ||
| 3267 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3268 | print "Resource:", resource -- prints: "logs" | ||
| 3269 | print "Action:", action -- prints: "view" | ||
| 3270 | ``` | ||
| 3271 | |||
| 3272 | <YueDisplay> | ||
| 3273 | |||
| 3274 | ```yue | ||
| 3275 | segments = ["admin", "users", "logs", "view"] | ||
| 3276 | switch segments | ||
| 3277 | when [...groups, resource, action] | ||
| 3278 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3279 | print "Resource:", resource -- prints: "logs" | ||
| 3280 | print "Action:", action -- prints: "view" | ||
| 3281 | ``` | ||
| 3282 | |||
| 3283 | </YueDisplay> | ||
| 3284 | |||
| 3285 | # While Loop | ||
| 3286 | |||
| 3287 | The while loop also comes in four variations: | ||
| 3288 | |||
| 3289 | ```yuescript | ||
| 3290 | i = 10 | ||
| 3291 | while i > 0 | ||
| 3292 | print i | ||
| 3293 | i -= 1 | ||
| 3294 | |||
| 3295 | while running == true do my_function! | ||
| 3296 | ``` | ||
| 3297 | |||
| 3298 | <YueDisplay> | ||
| 3299 | |||
| 3300 | ```yue | ||
| 3301 | i = 10 | ||
| 3302 | while i > 0 | ||
| 3303 | print i | ||
| 3304 | i -= 1 | ||
| 3305 | |||
| 3306 | while running == true do my_function! | ||
| 3307 | ``` | ||
| 3308 | |||
| 3309 | </YueDisplay> | ||
| 3310 | |||
| 3311 | ```yuescript | ||
| 3312 | i = 10 | ||
| 3313 | until i == 0 | ||
| 3314 | print i | ||
| 3315 | i -= 1 | ||
| 3316 | |||
| 3317 | until running == false do my_function! | ||
| 3318 | ``` | ||
| 3319 | |||
| 3320 | <YueDisplay> | ||
| 3321 | |||
| 3322 | ```yue | ||
| 3323 | i = 10 | ||
| 3324 | until i == 0 | ||
| 3325 | print i | ||
| 3326 | i -= 1 | ||
| 3327 | until running == false do my_function! | ||
| 3328 | ``` | ||
| 3329 | |||
| 3330 | </YueDisplay> | ||
| 3331 | |||
| 3332 | Like for loops, the while loop can also be used as an expression. While and until loop expressions support `break` with multiple return values. | ||
| 3333 | |||
| 3334 | ```yuescript | ||
| 3335 | value, doubled = while true | ||
| 3336 | n = get_next! | ||
| 3337 | break n, n * 2 if n > 10 | ||
| 3338 | ``` | ||
| 3339 | |||
| 3340 | <YueDisplay> | ||
| 3341 | |||
| 3342 | ```yue | ||
| 3343 | value, doubled = while true | ||
| 3344 | n = get_next! | ||
| 3345 | break n, n * 2 if n > 10 | ||
| 3346 | ``` | ||
| 3347 | |||
| 3348 | </YueDisplay> | ||
| 3349 | |||
| 3350 | Additionally, for a function to return the accumulated value of a while loop, the statement must be explicitly returned. | ||
| 3351 | |||
| 3352 | ## Repeat Loop | ||
| 3353 | |||
| 3354 | The repeat loop comes from Lua: | ||
| 3355 | |||
| 3356 | ```yuescript | ||
| 3357 | i = 10 | ||
| 3358 | repeat | ||
| 3359 | print i | ||
| 3360 | i -= 1 | ||
| 3361 | until i == 0 | ||
| 3362 | ``` | ||
| 3363 | |||
| 3364 | <YueDisplay> | ||
| 3365 | |||
| 3366 | ```yue | ||
| 3367 | i = 10 | ||
| 3368 | repeat | ||
| 3369 | print i | ||
| 3370 | i -= 1 | ||
| 3371 | until i == 0 | ||
| 3372 | ``` | ||
| 3373 | |||
| 3374 | </YueDisplay> | ||
| 3375 | |||
| 3376 | Repeat loop expressions also support `break` with multiple return values: | ||
| 3377 | |||
| 3378 | ```yuescript | ||
| 3379 | i = 1 | ||
| 3380 | value, scaled = repeat | ||
| 3381 | break i, i * 100 if i > 3 | ||
| 3382 | i += 1 | ||
| 3383 | until false | ||
| 3384 | ``` | ||
| 3385 | |||
| 3386 | <YueDisplay> | ||
| 3387 | |||
| 3388 | ```yue | ||
| 3389 | i = 1 | ||
| 3390 | value, scaled = repeat | ||
| 3391 | break i, i * 100 if i > 3 | ||
| 3392 | i += 1 | ||
| 3393 | until false | ||
| 3394 | ``` | ||
| 3395 | |||
| 3396 | </YueDisplay> | ||
| 3397 | |||
| 3398 | # Function Stubs | ||
| 3399 | |||
| 3400 | It is common to pass a function from an object around as a value, for example, passing an instance method into a function as a callback. If the function expects the object it is operating on as the first argument then you must somehow bundle that object with the function so it can be called properly. | ||
| 3401 | |||
| 3402 | The function stub syntax is a shorthand for creating a new closure function that bundles both the object and function. This new function calls the wrapped function in the correct context of the object. | ||
| 3403 | |||
| 3404 | Its syntax is the same as calling an instance method with the \ operator but with no argument list provided. | ||
| 3405 | |||
| 3406 | ```yuescript | ||
| 3407 | my_object = { | ||
| 3408 | value: 1000 | ||
| 3409 | write: => print "the value:", @value | ||
| 3410 | } | ||
| 3411 | |||
| 3412 | run_callback = (func) -> | ||
| 3413 | print "running callback..." | ||
| 3414 | func! | ||
| 3415 | |||
| 3416 | -- this will not work: | ||
| 3417 | -- the function has to no reference to my_object | ||
| 3418 | run_callback my_object.write | ||
| 3419 | |||
| 3420 | -- function stub syntax | ||
| 3421 | -- lets us bundle the object into a new function | ||
| 3422 | run_callback my_object\write | ||
| 3423 | ``` | ||
| 3424 | |||
| 3425 | <YueDisplay> | ||
| 3426 | |||
| 3427 | ```yue | ||
| 3428 | my_object = { | ||
| 3429 | value: 1000 | ||
| 3430 | write: => print "the value:", @value | ||
| 3431 | } | ||
| 3432 | |||
| 3433 | run_callback = (func) -> | ||
| 3434 | print "running callback..." | ||
| 3435 | func! | ||
| 3436 | |||
| 3437 | -- this will not work: | ||
| 3438 | -- the function has to no reference to my_object | ||
| 3439 | run_callback my_object.write | ||
| 3440 | |||
| 3441 | -- function stub syntax | ||
| 3442 | -- lets us bundle the object into a new function | ||
| 3443 | run_callback my_object\write | ||
| 3444 | ``` | ||
| 3445 | |||
| 3446 | </YueDisplay> | ||
| 3447 | |||
| 3448 | # Backcalls | ||
| 3449 | |||
| 3450 | Backcalls 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. | ||
| 3451 | |||
| 3452 | ```yuescript | ||
| 3453 | x <- f | ||
| 3454 | print "hello" .. x | ||
| 3455 | ``` | ||
| 3456 | |||
| 3457 | <YueDisplay> | ||
| 3458 | |||
| 3459 | ```yue | ||
| 3460 | x <- f | ||
| 3461 | print "hello" .. x | ||
| 3462 | ``` | ||
| 3463 | |||
| 3464 | </YueDisplay> | ||
| 3465 | |||
| 3466 | Fat arrow functions are also available. | ||
| 3467 | |||
| 3468 | ```yuescript | ||
| 3469 | <= f | ||
| 3470 | print @value | ||
| 3471 | ``` | ||
| 3472 | |||
| 3473 | <YueDisplay> | ||
| 3474 | |||
| 3475 | ```yue | ||
| 3476 | <= f | ||
| 3477 | print @value | ||
| 3478 | ``` | ||
| 3479 | |||
| 3480 | </YueDisplay> | ||
| 3481 | |||
| 3482 | You can specify a placeholder for where you want the backcall function to go as a parameter. | ||
| 3483 | |||
| 3484 | ```yuescript | ||
| 3485 | (x) <- map _, [1, 2, 3] | ||
| 3486 | x * 2 | ||
| 3487 | ``` | ||
| 3488 | |||
| 3489 | <YueDisplay> | ||
| 3490 | |||
| 3491 | ```yue | ||
| 3492 | (x) <- map _, [1, 2, 3] | ||
| 3493 | x * 2 | ||
| 3494 | ``` | ||
| 3495 | |||
| 3496 | </YueDisplay> | ||
| 3497 | |||
| 3498 | If 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. | ||
| 3499 | |||
| 3500 | ```yuescript | ||
| 3501 | result, msg = do | ||
| 3502 | data <- readAsync "filename.txt" | ||
| 3503 | print data | ||
| 3504 | info <- processAsync data | ||
| 3505 | check info | ||
| 3506 | print result, msg | ||
| 3507 | ``` | ||
| 3508 | |||
| 3509 | <YueDisplay> | ||
| 3510 | |||
| 3511 | ```yue | ||
| 3512 | result, msg = do | ||
| 3513 | data <- readAsync "filename.txt" | ||
| 3514 | print data | ||
| 3515 | info <- processAsync data | ||
| 3516 | check info | ||
| 3517 | print result, msg | ||
| 3518 | ``` | ||
| 3519 | |||
| 3520 | </YueDisplay> | ||
| 3521 | |||
| 3522 | # Function Literals | ||
| 3523 | |||
| 3524 | All functions are created using a function expression. A simple function is denoted using the arrow: **->**. | ||
| 3525 | |||
| 3526 | ```yuescript | ||
| 3527 | my_function = -> | ||
| 3528 | my_function() -- call the empty function | ||
| 3529 | ``` | ||
| 3530 | |||
| 3531 | <YueDisplay> | ||
| 3532 | |||
| 3533 | ```yue | ||
| 3534 | my_function = -> | ||
| 3535 | my_function() -- call the empty function | ||
| 3536 | ``` | ||
| 3537 | |||
| 3538 | </YueDisplay> | ||
| 3539 | |||
| 3540 | The body of the function can either be one statement placed directly after the arrow, or it can be a series of statements indented on the following lines: | ||
| 3541 | |||
| 3542 | ```yuescript | ||
| 3543 | func_a = -> print "hello world" | ||
| 3544 | |||
| 3545 | func_b = -> | ||
| 3546 | value = 100 | ||
| 3547 | print "The value:", value | ||
| 3548 | ``` | ||
| 3549 | |||
| 3550 | <YueDisplay> | ||
| 3551 | |||
| 3552 | ```yue | ||
| 3553 | func_a = -> print "hello world" | ||
| 3554 | |||
| 3555 | func_b = -> | ||
| 3556 | value = 100 | ||
| 3557 | print "The value:", value | ||
| 3558 | ``` | ||
| 3559 | |||
| 3560 | </YueDisplay> | ||
| 3561 | |||
| 3562 | If a function has no arguments, it can be called using the ! operator, instead of empty parentheses. The ! invocation is the preferred way to call functions with no arguments. | ||
| 3563 | |||
| 3564 | ```yuescript | ||
| 3565 | func_a! | ||
| 3566 | func_b() | ||
| 3567 | ``` | ||
| 3568 | |||
| 3569 | <YueDisplay> | ||
| 3570 | |||
| 3571 | ```yue | ||
| 3572 | func_a! | ||
| 3573 | func_b() | ||
| 3574 | ``` | ||
| 3575 | |||
| 3576 | </YueDisplay> | ||
| 3577 | |||
| 3578 | Functions with arguments can be created by preceding the arrow with a list of argument names in parentheses: | ||
| 3579 | |||
| 3580 | ```yuescript | ||
| 3581 | sum = (x, y) -> print "sum", x + y | ||
| 3582 | ``` | ||
| 3583 | |||
| 3584 | <YueDisplay> | ||
| 3585 | |||
| 3586 | ```yue | ||
| 3587 | sum = (x, y) -> print "sum", x + y | ||
| 3588 | ``` | ||
| 3589 | |||
| 3590 | </YueDisplay> | ||
| 3591 | |||
| 3592 | Functions can be called by listing the arguments after the name of an expression that evaluates to a function. When chaining together function calls, the arguments are applied to the closest function to the left. | ||
| 3593 | |||
| 3594 | ```yuescript | ||
| 3595 | sum 10, 20 | ||
| 3596 | print sum 10, 20 | ||
| 3597 | |||
| 3598 | a b c "a", "b", "c" | ||
| 3599 | ``` | ||
| 3600 | |||
| 3601 | <YueDisplay> | ||
| 3602 | |||
| 3603 | ```yue | ||
| 3604 | sum 10, 20 | ||
| 3605 | print sum 10, 20 | ||
| 3606 | |||
| 3607 | a b c "a", "b", "c" | ||
| 3608 | ``` | ||
| 3609 | |||
| 3610 | </YueDisplay> | ||
| 3611 | |||
| 3612 | In order to avoid ambiguity in when calling functions, parentheses can also be used to surround the arguments. This is required here in order to make sure the right arguments get sent to the right functions. | ||
| 3613 | |||
| 3614 | ```yuescript | ||
| 3615 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3616 | ``` | ||
| 3617 | |||
| 3618 | <YueDisplay> | ||
| 3619 | |||
| 3620 | ```yue | ||
| 3621 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3622 | ``` | ||
| 3623 | |||
| 3624 | </YueDisplay> | ||
| 3625 | |||
| 3626 | There must not be any space between the opening parenthesis and the function. | ||
| 3627 | |||
| 3628 | Functions will coerce the last statement in their body into a return statement, this is called implicit return: | ||
| 3629 | |||
| 3630 | ```yuescript | ||
| 3631 | sum = (x, y) -> x + y | ||
| 3632 | print "The sum is ", sum 10, 20 | ||
| 3633 | ``` | ||
| 3634 | |||
| 3635 | <YueDisplay> | ||
| 3636 | |||
| 3637 | ```yue | ||
| 3638 | sum = (x, y) -> x + y | ||
| 3639 | print "The sum is ", sum 10, 20 | ||
| 3640 | ``` | ||
| 3641 | |||
| 3642 | </YueDisplay> | ||
| 3643 | |||
| 3644 | And if you need to explicitly return, you can use the return keyword: | ||
| 3645 | |||
| 3646 | ```yuescript | ||
| 3647 | sum = (x, y) -> return x + y | ||
| 3648 | ``` | ||
| 3649 | |||
| 3650 | <YueDisplay> | ||
| 3651 | |||
| 3652 | ```yue | ||
| 3653 | sum = (x, y) -> return x + y | ||
| 3654 | ``` | ||
| 3655 | |||
| 3656 | </YueDisplay> | ||
| 3657 | |||
| 3658 | Just like in Lua, functions can return multiple values. The last statement must be a list of values separated by commas: | ||
| 3659 | |||
| 3660 | ```yuescript | ||
| 3661 | mystery = (x, y) -> x + y, x - y | ||
| 3662 | a, b = mystery 10, 20 | ||
| 3663 | ``` | ||
| 3664 | |||
| 3665 | <YueDisplay> | ||
| 3666 | |||
| 3667 | ```yue | ||
| 3668 | mystery = (x, y) -> x + y, x - y | ||
| 3669 | a, b = mystery 10, 20 | ||
| 3670 | ``` | ||
| 3671 | |||
| 3672 | </YueDisplay> | ||
| 3673 | |||
| 3674 | ## Fat Arrows | ||
| 3675 | |||
| 3676 | Because it is an idiom in Lua to send an object as the first argument when calling a method, a special syntax is provided for creating functions which automatically includes a self argument. | ||
| 3677 | |||
| 3678 | ```yuescript | ||
| 3679 | func = (num) => @value + num | ||
| 3680 | ``` | ||
| 3681 | |||
| 3682 | <YueDisplay> | ||
| 3683 | |||
| 3684 | ```yue | ||
| 3685 | func = (num) => @value + num | ||
| 3686 | ``` | ||
| 3687 | |||
| 3688 | </YueDisplay> | ||
| 3689 | |||
| 3690 | ## Argument Defaults | ||
| 3691 | |||
| 3692 | It is possible to provide default values for the arguments of a function. An argument is determined to be empty if its value is nil. Any nil arguments that have a default value will be replace before the body of the function is run. | ||
| 3693 | |||
| 3694 | ```yuescript | ||
| 3695 | my_function = (name = "something", height = 100) -> | ||
| 3696 | print "Hello I am", name | ||
| 3697 | print "My height is", height | ||
| 3698 | ``` | ||
| 3699 | |||
| 3700 | <YueDisplay> | ||
| 3701 | |||
| 3702 | ```yue | ||
| 3703 | my_function = (name = "something", height = 100) -> | ||
| 3704 | print "Hello I am", name | ||
| 3705 | print "My height is", height | ||
| 3706 | ``` | ||
| 3707 | |||
| 3708 | </YueDisplay> | ||
| 3709 | |||
| 3710 | An argument default value expression is evaluated in the body of the function in the order of the argument declarations. For this reason default values have access to previously declared arguments. | ||
| 3711 | |||
| 3712 | ```yuescript | ||
| 3713 | some_args = (x = 100, y = x + 1000) -> | ||
| 3714 | print x + y | ||
| 3715 | ``` | ||
| 3716 | |||
| 3717 | <YueDisplay> | ||
| 3718 | |||
| 3719 | ```yue | ||
| 3720 | some_args = (x = 100, y = x + 1000) -> | ||
| 3721 | print x + y | ||
| 3722 | ``` | ||
| 3723 | |||
| 3724 | </YueDisplay> | ||
| 3725 | |||
| 3726 | ## Considerations | ||
| 3727 | |||
| 3728 | Because of the expressive parentheses-less way of calling functions, some restrictions must be put in place to avoid parsing ambiguity involving whitespace. | ||
| 3729 | |||
| 3730 | The minus sign plays two roles, a unary negation operator and a binary subtraction operator. Consider how the following examples compile: | ||
| 3731 | |||
| 3732 | ```yuescript | ||
| 3733 | a = x - 10 | ||
| 3734 | b = x-10 | ||
| 3735 | c = x -y | ||
| 3736 | d = x- z | ||
| 3737 | ``` | ||
| 3738 | |||
| 3739 | <YueDisplay> | ||
| 3740 | |||
| 3741 | ```yue | ||
| 3742 | a = x - 10 | ||
| 3743 | b = x-10 | ||
| 3744 | c = x -y | ||
| 3745 | d = x- z | ||
| 3746 | ``` | ||
| 3747 | |||
| 3748 | </YueDisplay> | ||
| 3749 | |||
| 3750 | The precedence of the first argument of a function call can be controlled using whitespace if the argument is a literal string. In Lua, it is common to leave off parentheses when calling a function with a single string or table literal. | ||
| 3751 | |||
| 3752 | When there is no space between a variable and a string literal, the function call takes precedence over any following expressions. No other arguments can be passed to the function when it is called this way. | ||
| 3753 | |||
| 3754 | Where there is a space following a variable and a string literal, the function call acts as show above. The string literal belongs to any following expressions (if they exist), which serves as the argument list. | ||
| 3755 | |||
| 3756 | ```yuescript | ||
| 3757 | x = func"hello" + 100 | ||
| 3758 | y = func "hello" + 100 | ||
| 3759 | ``` | ||
| 3760 | |||
| 3761 | <YueDisplay> | ||
| 3762 | |||
| 3763 | ```yue | ||
| 3764 | x = func"hello" + 100 | ||
| 3765 | y = func "hello" + 100 | ||
| 3766 | ``` | ||
| 3767 | |||
| 3768 | </YueDisplay> | ||
| 3769 | |||
| 3770 | ## Multi-line arguments | ||
| 3771 | |||
| 3772 | When calling functions that take a large number of arguments, it is convenient to split the argument list over multiple lines. Because of the white-space sensitive nature of the language, care must be taken when splitting up the argument list. | ||
| 3773 | |||
| 3774 | If an argument list is to be continued onto the next line, the current line must end in a comma. And the following line must be indented more than the current indentation. Once indented, all other argument lines must be at the same level of indentation to be part of the argument list | ||
| 3775 | |||
| 3776 | ```yuescript | ||
| 3777 | my_func 5, 4, 3, | ||
| 3778 | 8, 9, 10 | ||
| 3779 | |||
| 3780 | cool_func 1, 2, | ||
| 3781 | 3, 4, | ||
| 3782 | 5, 6, | ||
| 3783 | 7, 8 | ||
| 3784 | ``` | ||
| 3785 | |||
| 3786 | <YueDisplay> | ||
| 3787 | |||
| 3788 | ```yue | ||
| 3789 | my_func 5, 4, 3, | ||
| 3790 | 8, 9, 10 | ||
| 3791 | |||
| 3792 | cool_func 1, 2, | ||
| 3793 | 3, 4, | ||
| 3794 | 5, 6, | ||
| 3795 | 7, 8 | ||
| 3796 | ``` | ||
| 3797 | |||
| 3798 | </YueDisplay> | ||
| 3799 | |||
| 3800 | This type of invocation can be nested. The level of indentation is used to determine to which function the arguments belong to. | ||
| 3801 | |||
| 3802 | ```yuescript | ||
| 3803 | my_func 5, 6, 7, | ||
| 3804 | 6, another_func 6, 7, 8, | ||
| 3805 | 9, 1, 2, | ||
| 3806 | 5, 4 | ||
| 3807 | ``` | ||
| 3808 | |||
| 3809 | <YueDisplay> | ||
| 3810 | |||
| 3811 | ```yue | ||
| 3812 | my_func 5, 6, 7, | ||
| 3813 | 6, another_func 6, 7, 8, | ||
| 3814 | 9, 1, 2, | ||
| 3815 | 5, 4 | ||
| 3816 | ``` | ||
| 3817 | |||
| 3818 | </YueDisplay> | ||
| 3819 | |||
| 3820 | Because tables also use the comma as a delimiter, this indentation syntax is helpful for letting values be part of the argument list instead of being part of the table. | ||
| 3821 | |||
| 3822 | ```yuescript | ||
| 3823 | x = [ | ||
| 3824 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3825 | 5, 6, | ||
| 3826 | 8, 9, 10 | ||
| 3827 | ] | ||
| 3828 | ``` | ||
| 3829 | |||
| 3830 | <YueDisplay> | ||
| 3831 | |||
| 3832 | ```yue | ||
| 3833 | x = [ | ||
| 3834 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3835 | 5, 6, | ||
| 3836 | 8, 9, 10 | ||
| 3837 | ] | ||
| 3838 | ``` | ||
| 3839 | |||
| 3840 | </YueDisplay> | ||
| 3841 | |||
| 3842 | Although uncommon, notice how we can give a deeper indentation for function arguments if we know we will be using a lower indentation further on. | ||
| 3843 | |||
| 3844 | ```yuescript | ||
| 3845 | y = [ my_func 1, 2, 3, | ||
| 3846 | 4, 5, | ||
| 3847 | 5, 6, 7 | ||
| 3848 | ] | ||
| 3849 | ``` | ||
| 3850 | |||
| 3851 | <YueDisplay> | ||
| 3852 | |||
| 3853 | ```yue | ||
| 3854 | y = [ my_func 1, 2, 3, | ||
| 3855 | 4, 5, | ||
| 3856 | 5, 6, 7 | ||
| 3857 | ] | ||
| 3858 | ``` | ||
| 3859 | |||
| 3860 | </YueDisplay> | ||
| 3861 | |||
| 3862 | The same thing can be done with other block level statements like conditionals. We can use indentation level to determine what statement a value belongs to: | ||
| 3863 | |||
| 3864 | ```yuescript | ||
| 3865 | if func 1, 2, 3, | ||
| 3866 | "hello", | ||
| 3867 | "world" | ||
| 3868 | print "hello" | ||
| 3869 | print "I am inside if" | ||
| 3870 | |||
| 3871 | if func 1, 2, 3, | ||
| 3872 | "hello", | ||
| 3873 | "world" | ||
| 3874 | print "hello" | ||
| 3875 | print "I am inside if" | ||
| 3876 | ``` | ||
| 3877 | |||
| 3878 | <YueDisplay> | ||
| 3879 | |||
| 3880 | ```yue | ||
| 3881 | if func 1, 2, 3, | ||
| 3882 | "hello", | ||
| 3883 | "world" | ||
| 3884 | print "hello" | ||
| 3885 | print "I am inside if" | ||
| 3886 | |||
| 3887 | if func 1, 2, 3, | ||
| 3888 | "hello", | ||
| 3889 | "world" | ||
| 3890 | print "hello" | ||
| 3891 | print "I am inside if" | ||
| 3892 | ``` | ||
| 3893 | |||
| 3894 | </YueDisplay> | ||
| 3895 | |||
| 3896 | ## Parameter Destructuring | ||
| 3897 | |||
| 3898 | YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available: | ||
| 3899 | |||
| 3900 | - **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`). | ||
| 3901 | |||
| 3902 | - **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. | ||
| 3903 | |||
| 3904 | ```yuescript | ||
| 3905 | f1 = (:a, :b, :c) -> | ||
| 3906 | print a, b, c | ||
| 3907 | |||
| 3908 | f1 a: 1, b: "2", c: {} | ||
| 3909 | |||
| 3910 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3911 | print a1, b, c | ||
| 3912 | |||
| 3913 | arg1 = {a: 0} | ||
| 3914 | f2 arg1, arg2 | ||
| 3915 | ``` | ||
| 3916 | |||
| 3917 | <YueDisplay> | ||
| 3918 | |||
| 3919 | ```yue | ||
| 3920 | f1 = (:a, :b, :c) -> | ||
| 3921 | print a, b, c | ||
| 3922 | |||
| 3923 | f1 a: 1, b: "2", c: {} | ||
| 3924 | |||
| 3925 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3926 | print a1, b, c | ||
| 3927 | |||
| 3928 | arg1 = {a: 0} | ||
| 3929 | f2 arg1, arg2 | ||
| 3930 | ``` | ||
| 3931 | |||
| 3932 | </YueDisplay> | ||
| 3933 | |||
| 3934 | ## Prefixed Return Expression | ||
| 3935 | |||
| 3936 | When 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: | ||
| 3937 | |||
| 3938 | ```yuescript | ||
| 3939 | findFirstEven = (list): nil -> | ||
| 3940 | for item in *list | ||
| 3941 | if type(item) == "table" | ||
| 3942 | for sub in *item | ||
| 3943 | if sub % 2 == 0 | ||
| 3944 | return sub | ||
| 3945 | ``` | ||
| 3946 | |||
| 3947 | <YueDisplay> | ||
| 3948 | |||
| 3949 | ```yue | ||
| 3950 | findFirstEven = (list): nil -> | ||
| 3951 | for item in *list | ||
| 3952 | if type(item) == "table" | ||
| 3953 | for sub in *item | ||
| 3954 | if sub % 2 == 0 | ||
| 3955 | return sub | ||
| 3956 | ``` | ||
| 3957 | |||
| 3958 | </YueDisplay> | ||
| 3959 | |||
| 3960 | This is equivalent to: | ||
| 3961 | |||
| 3962 | ```yuescript | ||
| 3963 | findFirstEven = (list) -> | ||
| 3964 | for item in *list | ||
| 3965 | if type(item) == "table" | ||
| 3966 | for sub in *item | ||
| 3967 | if sub % 2 == 0 | ||
| 3968 | return sub | ||
| 3969 | nil | ||
| 3970 | ``` | ||
| 3971 | |||
| 3972 | <YueDisplay> | ||
| 3973 | |||
| 3974 | ```yue | ||
| 3975 | findFirstEven = (list) -> | ||
| 3976 | for item in *list | ||
| 3977 | if type(item) == "table" | ||
| 3978 | for sub in *item | ||
| 3979 | if sub % 2 == 0 | ||
| 3980 | return sub | ||
| 3981 | nil | ||
| 3982 | ``` | ||
| 3983 | |||
| 3984 | </YueDisplay> | ||
| 3985 | |||
| 3986 | The 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. | ||
| 3987 | |||
| 3988 | ## Named Varargs | ||
| 3989 | |||
| 3990 | You 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). | ||
| 3991 | |||
| 3992 | ```yuescript | ||
| 3993 | f = (...t) -> | ||
| 3994 | print "argument count:", t.n | ||
| 3995 | print "table length:", #t | ||
| 3996 | for i = 1, t.n | ||
| 3997 | print t[i] | ||
| 3998 | |||
| 3999 | f 1, 2, 3 | ||
| 4000 | f "a", "b", "c", "d" | ||
| 4001 | f! | ||
| 4002 | |||
| 4003 | -- Handling cases with nil values | ||
| 4004 | process = (...args) -> | ||
| 4005 | sum = 0 | ||
| 4006 | for i = 1, args.n | ||
| 4007 | if args[i] != nil and type(args[i]) == "number" | ||
| 4008 | sum += args[i] | ||
| 4009 | sum | ||
| 4010 | |||
| 4011 | process 1, nil, 3, nil, 5 | ||
| 4012 | ``` | ||
| 4013 | |||
| 4014 | <YueDisplay> | ||
| 4015 | |||
| 4016 | ```yue | ||
| 4017 | f = (...t) -> | ||
| 4018 | print "argument count:", t.n | ||
| 4019 | print "table length:", #t | ||
| 4020 | for i = 1, t.n | ||
| 4021 | print t[i] | ||
| 4022 | |||
| 4023 | f 1, 2, 3 | ||
| 4024 | f "a", "b", "c", "d" | ||
| 4025 | f! | ||
| 4026 | |||
| 4027 | -- Handling cases with nil values | ||
| 4028 | process = (...args) -> | ||
| 4029 | sum = 0 | ||
| 4030 | for i = 1, args.n | ||
| 4031 | if args[i] != nil and type(args[i]) == "number" | ||
| 4032 | sum += args[i] | ||
| 4033 | sum | ||
| 4034 | |||
| 4035 | process 1, nil, 3, nil, 5 | ||
| 4036 | ``` | ||
| 4037 | |||
| 4038 | </YueDisplay> | ||
| 4039 | |||
| 4040 | # Whitespace | ||
| 4041 | |||
| 4042 | YueScript 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. | ||
| 4043 | |||
| 4044 | ## Statement Separator | ||
| 4045 | |||
| 4046 | A 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: | ||
| 4047 | |||
| 4048 | ```yuescript | ||
| 4049 | a = 1; b = 2; print a + b | ||
| 4050 | ``` | ||
| 4051 | |||
| 4052 | <YueDisplay> | ||
| 4053 | |||
| 4054 | ```yue | ||
| 4055 | a = 1; b = 2; print a + b | ||
| 4056 | ``` | ||
| 4057 | |||
| 4058 | </YueDisplay> | ||
| 4059 | |||
| 4060 | ## Multiline Chaining | ||
| 4061 | |||
| 4062 | You can write multi-line chaining function calls with a same indent. | ||
| 4063 | |||
| 4064 | ```yuescript | ||
| 4065 | Rx.Observable | ||
| 4066 | .fromRange 1, 8 | ||
| 4067 | \filter (x) -> x % 2 == 0 | ||
| 4068 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4069 | \map (value) -> value .. '!' | ||
| 4070 | \subscribe print | ||
| 4071 | ``` | ||
| 4072 | |||
| 4073 | <YueDisplay> | ||
| 4074 | |||
| 4075 | ```yue | ||
| 4076 | Rx.Observable | ||
| 4077 | .fromRange 1, 8 | ||
| 4078 | \filter (x) -> x % 2 == 0 | ||
| 4079 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4080 | \map (value) -> value .. '!' | ||
| 4081 | \subscribe print | ||
| 4082 | ``` | ||
| 4083 | |||
| 4084 | </YueDisplay> | ||
| 4085 | |||
| 4086 | # Comment | ||
| 4087 | |||
| 4088 | ```yuescript | ||
| 4089 | -- I am a comment | ||
| 4090 | |||
| 4091 | str = --[[ | ||
| 4092 | This is a multi-line comment. | ||
| 4093 | It's OK. | ||
| 4094 | ]] strA \ -- comment 1 | ||
| 4095 | .. strB \ -- comment 2 | ||
| 4096 | .. strC | ||
| 4097 | |||
| 4098 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4099 | ``` | ||
| 4100 | |||
| 4101 | <YueDisplay> | ||
| 4102 | |||
| 4103 | ```yue | ||
| 4104 | -- I am a comment | ||
| 4105 | |||
| 4106 | str = --[[ | ||
| 4107 | This is a multi-line comment. | ||
| 4108 | It's OK. | ||
| 4109 | ]] strA \ -- comment 1 | ||
| 4110 | .. strB \ -- comment 2 | ||
| 4111 | .. strC | ||
| 4112 | |||
| 4113 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4114 | ``` | ||
| 4115 | |||
| 4116 | </YueDisplay> | ||
| 4117 | |||
| 4118 | # Attributes | ||
| 4119 | |||
| 4120 | Syntax 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. | ||
| 4121 | |||
| 4122 | ```yuescript | ||
| 4123 | const a = 123 | ||
| 4124 | close _ = <close>: -> print "Out of scope." | ||
| 4125 | ``` | ||
| 4126 | |||
| 4127 | <YueDisplay> | ||
| 4128 | |||
| 4129 | ```yue | ||
| 4130 | const a = 123 | ||
| 4131 | close _ = <close>: -> print "Out of scope." | ||
| 4132 | ``` | ||
| 4133 | |||
| 4134 | </YueDisplay> | ||
| 4135 | |||
| 4136 | You can do desctructuring with variables attributed as constant. | ||
| 4137 | |||
| 4138 | ```yuescript | ||
| 4139 | const {:a, :b, c, d} = tb | ||
| 4140 | -- a = 1 | ||
| 4141 | ``` | ||
| 4142 | |||
| 4143 | <YueDisplay> | ||
| 4144 | |||
| 4145 | ```yue | ||
| 4146 | const {:a, :b, c, d} = tb | ||
| 4147 | -- a = 1 | ||
| 4148 | ``` | ||
| 4149 | |||
| 4150 | </YueDisplay> | ||
| 4151 | |||
| 4152 | You can also declare a global variable to be `const`. | ||
| 4153 | |||
| 4154 | ```yuescript | ||
| 4155 | global const Constant = 123 | ||
| 4156 | -- Constant = 1 | ||
| 4157 | ``` | ||
| 4158 | |||
| 4159 | <YueDisplay> | ||
| 4160 | |||
| 4161 | ```yue | ||
| 4162 | global const Constant = 123 | ||
| 4163 | -- Constant = 1 | ||
| 4164 | ``` | ||
| 4165 | |||
| 4166 | </YueDisplay> | ||
| 4167 | |||
| 4168 | # Operator | ||
| 4169 | |||
| 4170 | All 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. | ||
| 4171 | |||
| 4172 | ```yuescript | ||
| 4173 | tb\func! if tb ~= nil | ||
| 4174 | tb::func! if tb != nil | ||
| 4175 | ``` | ||
| 4176 | |||
| 4177 | <YueDisplay> | ||
| 4178 | |||
| 4179 | ```yue | ||
| 4180 | tb\func! if tb ~= nil | ||
| 4181 | tb::func! if tb != nil | ||
| 4182 | ``` | ||
| 4183 | |||
| 4184 | </YueDisplay> | ||
| 4185 | |||
| 4186 | ## Chaining Comparisons | ||
| 4187 | |||
| 4188 | Comparisons can be arbitrarily chained: | ||
| 4189 | |||
| 4190 | ```yuescript | ||
| 4191 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4192 | -- output: true | ||
| 4193 | |||
| 4194 | a = 5 | ||
| 4195 | print 1 <= a <= 10 | ||
| 4196 | -- output: true | ||
| 4197 | ``` | ||
| 4198 | |||
| 4199 | <YueDisplay> | ||
| 4200 | |||
| 4201 | ```yue | ||
| 4202 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4203 | -- output: true | ||
| 4204 | |||
| 4205 | a = 5 | ||
| 4206 | print 1 <= a <= 10 | ||
| 4207 | -- output: true | ||
| 4208 | ``` | ||
| 4209 | |||
| 4210 | </YueDisplay> | ||
| 4211 | |||
| 4212 | Note the evaluation behavior of chained comparisons: | ||
| 4213 | |||
| 4214 | ```yuescript | ||
| 4215 | v = (x) -> | ||
| 4216 | print x | ||
| 4217 | x | ||
| 4218 | |||
| 4219 | print v(1) < v(2) <= v(3) | ||
| 4220 | --[[ | ||
| 4221 | output: | ||
| 4222 | 2 | ||
| 4223 | 1 | ||
| 4224 | 3 | ||
| 4225 | true | ||
| 4226 | ]] | ||
| 4227 | |||
| 4228 | print v(1) > v(2) <= v(3) | ||
| 4229 | --[[ | ||
| 4230 | output: | ||
| 4231 | 2 | ||
| 4232 | 1 | ||
| 4233 | false | ||
| 4234 | ]] | ||
| 4235 | ``` | ||
| 4236 | |||
| 4237 | <YueDisplay> | ||
| 4238 | |||
| 4239 | ```yue | ||
| 4240 | v = (x) -> | ||
| 4241 | print x | ||
| 4242 | x | ||
| 4243 | |||
| 4244 | print v(1) < v(2) <= v(3) | ||
| 4245 | --[[ | ||
| 4246 | output: | ||
| 4247 | 2 | ||
| 4248 | 1 | ||
| 4249 | 3 | ||
| 4250 | true | ||
| 4251 | ]] | ||
| 4252 | |||
| 4253 | print v(1) > v(2) <= v(3) | ||
| 4254 | --[[ | ||
| 4255 | output: | ||
| 4256 | 2 | ||
| 4257 | 1 | ||
| 4258 | false | ||
| 4259 | ]] | ||
| 4260 | ``` | ||
| 4261 | |||
| 4262 | </YueDisplay> | ||
| 4263 | |||
| 4264 | The middle expression is only evaluated once, rather than twice as it would be if the expression were written as `v(1) < v(2) and v(2) <= v(3)`. However, the order of evaluations in a chained comparison is undefined. It is strongly recommended not to use expressions with side effects (such as printing) in chained comparisons. If side effects are required, the short-circuit `and` operator should be used explicitly. | ||
| 4265 | |||
| 4266 | ## Table Appending | ||
| 4267 | |||
| 4268 | The **[] =** operator is used to append values to tables. | ||
| 4269 | |||
| 4270 | ```yuescript | ||
| 4271 | tab = [] | ||
| 4272 | tab[] = "Value" | ||
| 4273 | ``` | ||
| 4274 | |||
| 4275 | <YueDisplay> | ||
| 4276 | |||
| 4277 | ```yue | ||
| 4278 | tab = [] | ||
| 4279 | tab[] = "Value" | ||
| 4280 | ``` | ||
| 4281 | |||
| 4282 | </YueDisplay> | ||
| 4283 | |||
| 4284 | You can also use the spread operator `...` to append all elements from one list to another: | ||
| 4285 | |||
| 4286 | ```yuescript | ||
| 4287 | tbA = [1, 2, 3] | ||
| 4288 | tbB = [4, 5, 6] | ||
| 4289 | tbA[] = ...tbB | ||
| 4290 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 4291 | ``` | ||
| 4292 | |||
| 4293 | <YueDisplay> | ||
| 4294 | |||
| 4295 | ```yue | ||
| 4296 | tbA = [1, 2, 3] | ||
| 4297 | tbB = [4, 5, 6] | ||
| 4298 | tbA[] = ...tbB | ||
| 4299 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 4300 | ``` | ||
| 4301 | |||
| 4302 | </YueDisplay> | ||
| 4303 | |||
| 4304 | ## Table Spreading | ||
| 4305 | |||
| 4306 | You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. | ||
| 4307 | |||
| 4308 | ```yuescript | ||
| 4309 | parts = | ||
| 4310 | * "shoulders" | ||
| 4311 | * "knees" | ||
| 4312 | lyrics = | ||
| 4313 | * "head" | ||
| 4314 | * ...parts | ||
| 4315 | * "and" | ||
| 4316 | * "toes" | ||
| 4317 | |||
| 4318 | copy = {...other} | ||
| 4319 | |||
| 4320 | a = {1, 2, 3, x: 1} | ||
| 4321 | b = {4, 5, y: 1} | ||
| 4322 | merge = {...a, ...b} | ||
| 4323 | ``` | ||
| 4324 | |||
| 4325 | <YueDisplay> | ||
| 4326 | |||
| 4327 | ```yue | ||
| 4328 | parts = | ||
| 4329 | * "shoulders" | ||
| 4330 | * "knees" | ||
| 4331 | lyrics = | ||
| 4332 | * "head" | ||
| 4333 | * ...parts | ||
| 4334 | * "and" | ||
| 4335 | * "toes" | ||
| 4336 | |||
| 4337 | copy = {...other} | ||
| 4338 | |||
| 4339 | a = {1, 2, 3, x: 1} | ||
| 4340 | b = {4, 5, y: 1} | ||
| 4341 | merge = {...a, ...b} | ||
| 4342 | ``` | ||
| 4343 | |||
| 4344 | </YueDisplay> | ||
| 4345 | |||
| 4346 | ## Table Reversed Indexing | ||
| 4347 | |||
| 4348 | You can use the **#** operator to get the last elements of a table. | ||
| 4349 | |||
| 4350 | ```yuescript | ||
| 4351 | last = data.items[#] | ||
| 4352 | second_last = data.items[#-1] | ||
| 4353 | data.items[#] = 1 | ||
| 4354 | ``` | ||
| 4355 | |||
| 4356 | <YueDisplay> | ||
| 4357 | |||
| 4358 | ```yue | ||
| 4359 | last = data.items[#] | ||
| 4360 | second_last = data.items[#-1] | ||
| 4361 | data.items[#] = 1 | ||
| 4362 | ``` | ||
| 4363 | |||
| 4364 | </YueDisplay> | ||
| 4365 | |||
| 4366 | ## Metatable | ||
| 4367 | |||
| 4368 | The **<>** operator can be used as a shortcut for metatable manipulation. | ||
| 4369 | |||
| 4370 | ### Metatable Creation | ||
| 4371 | |||
| 4372 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. | ||
| 4373 | |||
| 4374 | ```yuescript | ||
| 4375 | mt = {} | ||
| 4376 | add = (right) => <>: mt, value: @value + right.value | ||
| 4377 | mt.__add = add | ||
| 4378 | |||
| 4379 | a = <>: mt, value: 1 | ||
| 4380 | -- set field with variable of the same name | ||
| 4381 | b = :<add>, value: 2 | ||
| 4382 | c = <add>: mt.__add, value: 3 | ||
| 4383 | |||
| 4384 | d = a + b + c | ||
| 4385 | print d.value | ||
| 4386 | |||
| 4387 | close _ = <close>: -> print "out of scope" | ||
| 4388 | ``` | ||
| 4389 | |||
| 4390 | <YueDisplay> | ||
| 4391 | |||
| 4392 | ```yue | ||
| 4393 | mt = {} | ||
| 4394 | add = (right) => <>: mt, value: @value + right.value | ||
| 4395 | mt.__add = add | ||
| 4396 | |||
| 4397 | a = <>: mt, value: 1 | ||
| 4398 | -- set field with variable of the same name | ||
| 4399 | b = :<add>, value: 2 | ||
| 4400 | c = <add>: mt.__add, value: 3 | ||
| 4401 | |||
| 4402 | d = a + b + c | ||
| 4403 | print d.value | ||
| 4404 | |||
| 4405 | close _ = <close>: -> print "out of scope" | ||
| 4406 | ``` | ||
| 4407 | |||
| 4408 | </YueDisplay> | ||
| 4409 | |||
| 4410 | ### Metatable Accessing | ||
| 4411 | |||
| 4412 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. | ||
| 4413 | |||
| 4414 | ```yuescript | ||
| 4415 | -- create with metatable containing field "value" | ||
| 4416 | tb = <"value">: 123 | ||
| 4417 | tb.<index> = tb.<> | ||
| 4418 | print tb.value | ||
| 4419 | |||
| 4420 | tb.<> = __index: {item: "hello"} | ||
| 4421 | print tb.item | ||
| 4422 | ``` | ||
| 4423 | |||
| 4424 | <YueDisplay> | ||
| 4425 | |||
| 4426 | ```yue | ||
| 4427 | -- create with metatable containing field "value" | ||
| 4428 | tb = <"value">: 123 | ||
| 4429 | tb.<index> = tb.<> | ||
| 4430 | print tb.value | ||
| 4431 | tb.<> = __index: {item: "hello"} | ||
| 4432 | print tb.item | ||
| 4433 | ``` | ||
| 4434 | |||
| 4435 | </YueDisplay> | ||
| 4436 | |||
| 4437 | ### Metatable Destructure | ||
| 4438 | |||
| 4439 | Destruct metatable with metamethod key surrounded by **<>**. | ||
| 4440 | |||
| 4441 | ```yuescript | ||
| 4442 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4443 | print item, new, close, getter | ||
| 4444 | ``` | ||
| 4445 | |||
| 4446 | <YueDisplay> | ||
| 4447 | |||
| 4448 | ```yue | ||
| 4449 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4450 | print item, new, close, getter | ||
| 4451 | ``` | ||
| 4452 | |||
| 4453 | </YueDisplay> | ||
| 4454 | |||
| 4455 | ## Existence | ||
| 4456 | |||
| 4457 | The **?** operator can be used in a variety of contexts to check for existence. | ||
| 4458 | |||
| 4459 | ```yuescript | ||
| 4460 | func?! | ||
| 4461 | print abc?["hello world"]?.xyz | ||
| 4462 | |||
| 4463 | x = tab?.value | ||
| 4464 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4465 | |||
| 4466 | if print and x? | ||
| 4467 | print x | ||
| 4468 | |||
| 4469 | with? io.open "test.txt", "w" | ||
| 4470 | \write "hello" | ||
| 4471 | \close! | ||
| 4472 | ``` | ||
| 4473 | |||
| 4474 | <YueDisplay> | ||
| 4475 | |||
| 4476 | ```yue | ||
| 4477 | func?! | ||
| 4478 | print abc?["hello world"]?.xyz | ||
| 4479 | |||
| 4480 | x = tab?.value | ||
| 4481 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4482 | |||
| 4483 | if print and x? | ||
| 4484 | print x | ||
| 4485 | |||
| 4486 | with? io.open "test.txt", "w" | ||
| 4487 | \write "hello" | ||
| 4488 | \close! | ||
| 4489 | ``` | ||
| 4490 | |||
| 4491 | </YueDisplay> | ||
| 4492 | |||
| 4493 | ## Piping | ||
| 4494 | |||
| 4495 | Instead of a series of nested function calls, you can pipe values with operator **|>**. | ||
| 4496 | |||
| 4497 | ```yuescript | ||
| 4498 | "hello" |> print | ||
| 4499 | 1 |> print 2 -- insert pipe item as the first argument | ||
| 4500 | 2 |> print 1, _, 3 -- pipe with a placeholder | ||
| 4501 | |||
| 4502 | -- pipe expression in multiline | ||
| 4503 | readFile "example.txt" | ||
| 4504 | |> extract language, {} | ||
| 4505 | |> parse language | ||
| 4506 | |> emit | ||
| 4507 | |> render | ||
| 4508 | |||
| 4509 | ``` | ||
| 4510 | |||
| 4511 | <YueDisplay> | ||
| 4512 | |||
| 4513 | ```yue | ||
| 4514 | "hello" |> print | ||
| 4515 | 1 |> print 2 -- insert pipe item as the first argument | ||
| 4516 | 2 |> print 1, _, 3 -- pipe with a placeholder | ||
| 4517 | -- pipe expression in multiline | ||
| 4518 | readFile "example.txt" | ||
| 4519 | |> extract language, {} | ||
| 4520 | |> parse language | ||
| 4521 | |> emit | ||
| 4522 | |> render | ||
| 4523 | |||
| 4524 | ``` | ||
| 4525 | |||
| 4526 | </YueDisplay> | ||
| 4527 | |||
| 4528 | ## Nil Coalescing | ||
| 4529 | |||
| 4530 | The nil-coalescing operator **??** returns the value of its left-hand operand if it isn't **nil**; otherwise, it evaluates the right-hand operand and returns its result. The **??** operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-nil. | ||
| 4531 | |||
| 4532 | ```yuescript | ||
| 4533 | local a, b, c, d | ||
| 4534 | a = b ?? c ?? d | ||
| 4535 | func a ?? {} | ||
| 4536 | |||
| 4537 | a ??= false | ||
| 4538 | ``` | ||
| 4539 | |||
| 4540 | <YueDisplay> | ||
| 4541 | |||
| 4542 | ```yue | ||
| 4543 | local a, b, c, d | ||
| 4544 | a = b ?? c ?? d | ||
| 4545 | func a ?? {} | ||
| 4546 | a ??= false | ||
| 4547 | ``` | ||
| 4548 | |||
| 4549 | </YueDisplay> | ||
| 4550 | |||
| 4551 | ## Implicit Object | ||
| 4552 | |||
| 4553 | You 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. | ||
| 4554 | |||
| 4555 | ```yuescript | ||
| 4556 | -- assignment with implicit object | ||
| 4557 | list = | ||
| 4558 | * 1 | ||
| 4559 | * 2 | ||
| 4560 | * 3 | ||
| 4561 | |||
| 4562 | -- function call with implicit object | ||
| 4563 | func | ||
| 4564 | * 1 | ||
| 4565 | * 2 | ||
| 4566 | * 3 | ||
| 4567 | |||
| 4568 | -- return with implicit object | ||
| 4569 | f = -> | ||
| 4570 | return | ||
| 4571 | * 1 | ||
| 4572 | * 2 | ||
| 4573 | * 3 | ||
| 4574 | |||
| 4575 | -- table with implicit object | ||
| 4576 | tb = | ||
| 4577 | name: "abc" | ||
| 4578 | |||
| 4579 | values: | ||
| 4580 | - "a" | ||
| 4581 | - "b" | ||
| 4582 | - "c" | ||
| 4583 | |||
| 4584 | objects: | ||
| 4585 | - name: "a" | ||
| 4586 | value: 1 | ||
| 4587 | func: => @value + 1 | ||
| 4588 | tb: | ||
| 4589 | fieldA: 1 | ||
| 4590 | |||
| 4591 | - name: "b" | ||
| 4592 | value: 2 | ||
| 4593 | func: => @value + 2 | ||
| 4594 | tb: { } | ||
| 4595 | |||
| 4596 | ``` | ||
| 4597 | |||
| 4598 | <YueDisplay> | ||
| 4599 | |||
| 4600 | ```yue | ||
| 4601 | -- assignment with implicit object | ||
| 4602 | list = | ||
| 4603 | * 1 | ||
| 4604 | * 2 | ||
| 4605 | * 3 | ||
| 4606 | |||
| 4607 | -- function call with implicit object | ||
| 4608 | func | ||
| 4609 | * 1 | ||
| 4610 | * 2 | ||
| 4611 | * 3 | ||
| 4612 | |||
| 4613 | -- return with implicit object | ||
| 4614 | f = -> | ||
| 4615 | return | ||
| 4616 | * 1 | ||
| 4617 | * 2 | ||
| 4618 | * 3 | ||
| 4619 | |||
| 4620 | -- table with implicit object | ||
| 4621 | tb = | ||
| 4622 | name: "abc" | ||
| 4623 | |||
| 4624 | values: | ||
| 4625 | - "a" | ||
| 4626 | - "b" | ||
| 4627 | - "c" | ||
| 4628 | |||
| 4629 | objects: | ||
| 4630 | - name: "a" | ||
| 4631 | value: 1 | ||
| 4632 | func: => @value + 1 | ||
| 4633 | tb: | ||
| 4634 | fieldA: 1 | ||
| 4635 | |||
| 4636 | - name: "b" | ||
| 4637 | value: 2 | ||
| 4638 | func: => @value + 2 | ||
| 4639 | tb: { } | ||
| 4640 | ``` | ||
| 4641 | |||
| 4642 | </YueDisplay> | ||
| 4643 | |||
| 4644 | # Literals | ||
| 4645 | |||
| 4646 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. | ||
| 4647 | |||
| 4648 | Unlike Lua, Line breaks are allowed inside of single and double quote strings without an escape sequence: | ||
| 4649 | |||
| 4650 | ```yuescript | ||
| 4651 | some_string = "Here is a string | ||
| 4652 | that has a line break in it." | ||
| 4653 | |||
| 4654 | -- You can mix expressions into string literals using #{} syntax. | ||
| 4655 | -- String interpolation is only available in double quoted strings. | ||
| 4656 | print "I am #{math.random! * 100}% sure." | ||
| 4657 | ``` | ||
| 4658 | |||
| 4659 | <YueDisplay> | ||
| 4660 | |||
| 4661 | ```yue | ||
| 4662 | some_string = "Here is a string | ||
| 4663 | that has a line break in it." | ||
| 4664 | |||
| 4665 | -- You can mix expressions into string literals using #{} syntax. | ||
| 4666 | -- String interpolation is only available in double quoted strings. | ||
| 4667 | print "I am #{math.random! * 100}% sure." | ||
| 4668 | ``` | ||
| 4669 | |||
| 4670 | </YueDisplay> | ||
| 4671 | |||
| 4672 | ## Number Literals | ||
| 4673 | |||
| 4674 | You can use underscores in a number literal to increase readability. | ||
| 4675 | |||
| 4676 | ```yuescript | ||
| 4677 | integer = 1_000_000 | ||
| 4678 | hex = 0xEF_BB_BF | ||
| 4679 | binary = 0B10011 | ||
| 4680 | ``` | ||
| 4681 | |||
| 4682 | <YueDisplay> | ||
| 4683 | |||
| 4684 | ```yue | ||
| 4685 | integer = 1_000_000 | ||
| 4686 | hex = 0xEF_BB_BF | ||
| 4687 | binary = 0B10011 | ||
| 4688 | ``` | ||
| 4689 | |||
| 4690 | </YueDisplay> | ||
| 4691 | |||
| 4692 | ## YAML Multiline String | ||
| 4693 | |||
| 4694 | The `|` prefix introduces a YAML-style multiline string literal: | ||
| 4695 | |||
| 4696 | ```yuescript | ||
| 4697 | str = | | ||
| 4698 | key: value | ||
| 4699 | list: | ||
| 4700 | - item1 | ||
| 4701 | - #{expr} | ||
| 4702 | ``` | ||
| 4703 | |||
| 4704 | <YueDisplay> | ||
| 4705 | |||
| 4706 | ```yue | ||
| 4707 | str = | | ||
| 4708 | key: value | ||
| 4709 | list: | ||
| 4710 | - item1 | ||
| 4711 | - #{expr} | ||
| 4712 | ``` | ||
| 4713 | |||
| 4714 | </YueDisplay> | ||
| 4715 | |||
| 4716 | This 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)`. | ||
| 4717 | |||
| 4718 | YAML 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. | ||
| 4719 | |||
| 4720 | ```yuescript | ||
| 4721 | fn = -> | ||
| 4722 | str = | | ||
| 4723 | foo: | ||
| 4724 | bar: baz | ||
| 4725 | return str | ||
| 4726 | ``` | ||
| 4727 | |||
| 4728 | <YueDisplay> | ||
| 4729 | |||
| 4730 | ```yue | ||
| 4731 | fn = -> | ||
| 4732 | str = | | ||
| 4733 | foo: | ||
| 4734 | bar: baz | ||
| 4735 | return str | ||
| 4736 | ``` | ||
| 4737 | |||
| 4738 | </YueDisplay> | ||
| 4739 | |||
| 4740 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
| 4741 | |||
| 4742 | All 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. | ||
| 4743 | |||
| 4744 | ```yuescript | ||
| 4745 | str = | | ||
| 4746 | path: "C:\Program Files\App" | ||
| 4747 | note: 'He said: "#{Hello}!"' | ||
| 4748 | ``` | ||
| 4749 | |||
| 4750 | <YueDisplay> | ||
| 4751 | |||
| 4752 | ```yue | ||
| 4753 | str = | | ||
| 4754 | path: "C:\Program Files\App" | ||
| 4755 | note: 'He said: "#{Hello}!"' | ||
| 4756 | ``` | ||
| 4757 | |||
| 4758 | </YueDisplay> | ||
| 4759 | |||
| 4760 | # Module | ||
| 4761 | |||
| 4762 | ## Import | ||
| 4763 | |||
| 4764 | The import statement is a syntax sugar for requiring a module or help extracting items from an imported module. The imported items are const by default. | ||
| 4765 | |||
| 4766 | ```yuescript | ||
| 4767 | -- used as table destructuring | ||
| 4768 | do | ||
| 4769 | import insert, concat from table | ||
| 4770 | -- report error when assigning to insert, concat | ||
| 4771 | import C, Ct, Cmt from require "lpeg" | ||
| 4772 | -- shortcut for implicit requiring | ||
| 4773 | import x, y, z from 'mymodule' | ||
| 4774 | -- import with Python style | ||
| 4775 | from 'module' import a, b, c | ||
| 4776 | |||
| 4777 | -- shortcut for requring a module | ||
| 4778 | do | ||
| 4779 | import 'module' | ||
| 4780 | import 'module_x' | ||
| 4781 | import "d-a-s-h-e-s" | ||
| 4782 | import "module.part" | ||
| 4783 | |||
| 4784 | -- requring module with aliasing or table destructuring | ||
| 4785 | do | ||
| 4786 | import "player" as PlayerModule | ||
| 4787 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4788 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4789 | ``` | ||
| 4790 | |||
| 4791 | <YueDisplay> | ||
| 4792 | |||
| 4793 | ```yue | ||
| 4794 | -- used as table destructuring | ||
| 4795 | do | ||
| 4796 | import insert, concat from table | ||
| 4797 | -- report error when assigning to insert, concat | ||
| 4798 | import C, Ct, Cmt from require "lpeg" | ||
| 4799 | -- shortcut for implicit requiring | ||
| 4800 | import x, y, z from 'mymodule' | ||
| 4801 | -- import with Python style | ||
| 4802 | from 'module' import a, b, c | ||
| 4803 | |||
| 4804 | -- shortcut for requring a module | ||
| 4805 | do | ||
| 4806 | import 'module' | ||
| 4807 | import 'module_x' | ||
| 4808 | import "d-a-s-h-e-s" | ||
| 4809 | import "module.part" | ||
| 4810 | |||
| 4811 | -- requring module with aliasing or table destructuring | ||
| 4812 | do | ||
| 4813 | import "player" as PlayerModule | ||
| 4814 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4815 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4816 | ``` | ||
| 4817 | |||
| 4818 | </YueDisplay> | ||
| 4819 | |||
| 4820 | ## Import Global | ||
| 4821 | |||
| 4822 | You 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. | ||
| 4823 | |||
| 4824 | ```yuescript | ||
| 4825 | do | ||
| 4826 | import tostring | ||
| 4827 | import table.concat | ||
| 4828 | print concat ["a", tostring 1] | ||
| 4829 | ``` | ||
| 4830 | |||
| 4831 | <YueDisplay> | ||
| 4832 | |||
| 4833 | ```yue | ||
| 4834 | do | ||
| 4835 | import tostring | ||
| 4836 | import table.concat | ||
| 4837 | print concat ["a", tostring 1] | ||
| 4838 | ``` | ||
| 4839 | |||
| 4840 | </YueDisplay> | ||
| 4841 | |||
| 4842 | ### Automatic Global Variable Import | ||
| 4843 | |||
| 4844 | You 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. | ||
| 4845 | |||
| 4846 | Names that are explicitly declared as globals in the same scope will not be imported, so you can still assign to them. | ||
| 4847 | |||
| 4848 | ```yuescript | ||
| 4849 | do | ||
| 4850 | import global | ||
| 4851 | print "hello" | ||
| 4852 | math.random 3 | ||
| 4853 | -- print = nil -- error: imported globals are const | ||
| 4854 | |||
| 4855 | do | ||
| 4856 | -- explicit global variable will not be imported | ||
| 4857 | import global | ||
| 4858 | global FLAG | ||
| 4859 | print FLAG | ||
| 4860 | FLAG = 123 | ||
| 4861 | ``` | ||
| 4862 | |||
| 4863 | <YueDisplay> | ||
| 4864 | |||
| 4865 | ```yue | ||
| 4866 | do | ||
| 4867 | import global | ||
| 4868 | print "hello" | ||
| 4869 | math.random 3 | ||
| 4870 | -- print = nil -- error: imported globals are const | ||
| 4871 | |||
| 4872 | do | ||
| 4873 | -- explicit global variable will not be imported | ||
| 4874 | import global | ||
| 4875 | global FLAG | ||
| 4876 | print FLAG | ||
| 4877 | FLAG = 123 | ||
| 4878 | ``` | ||
| 4879 | |||
| 4880 | </YueDisplay> | ||
| 4881 | |||
| 4882 | ## Export | ||
| 4883 | |||
| 4884 | The export statement offers a concise way to define modules. | ||
| 4885 | |||
| 4886 | ### Named Export | ||
| 4887 | |||
| 4888 | Named export will define a local variable as well as adding a field in the exported table. | ||
| 4889 | |||
| 4890 | ```yuescript | ||
| 4891 | export a, b, c = 1, 2, 3 | ||
| 4892 | export cool = "cat" | ||
| 4893 | |||
| 4894 | export What = if this | ||
| 4895 | "abc" | ||
| 4896 | else | ||
| 4897 | "def" | ||
| 4898 | |||
| 4899 | export y = -> | ||
| 4900 | hallo = 3434 | ||
| 4901 | |||
| 4902 | export class Something | ||
| 4903 | umm: "cool" | ||
| 4904 | ``` | ||
| 4905 | |||
| 4906 | <YueDisplay> | ||
| 4907 | |||
| 4908 | ```yue | ||
| 4909 | export a, b, c = 1, 2, 3 | ||
| 4910 | export cool = "cat" | ||
| 4911 | |||
| 4912 | export What = if this | ||
| 4913 | "abc" | ||
| 4914 | else | ||
| 4915 | "def" | ||
| 4916 | |||
| 4917 | export y = -> | ||
| 4918 | hallo = 3434 | ||
| 4919 | |||
| 4920 | export class Something | ||
| 4921 | umm: "cool" | ||
| 4922 | ``` | ||
| 4923 | |||
| 4924 | </YueDisplay> | ||
| 4925 | |||
| 4926 | Doing named export with destructuring. | ||
| 4927 | |||
| 4928 | ```yuescript | ||
| 4929 | export :loadstring, to_lua: tolua = yue | ||
| 4930 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4931 | ``` | ||
| 4932 | |||
| 4933 | <YueDisplay> | ||
| 4934 | |||
| 4935 | ```yue | ||
| 4936 | export :loadstring, to_lua: tolua = yue | ||
| 4937 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4938 | ``` | ||
| 4939 | |||
| 4940 | </YueDisplay> | ||
| 4941 | |||
| 4942 | Export named items from module without creating local variables. | ||
| 4943 | |||
| 4944 | ```yuescript | ||
| 4945 | export.itemA = tb | ||
| 4946 | export.<index> = items | ||
| 4947 | export["a-b-c"] = 123 | ||
| 4948 | ``` | ||
| 4949 | |||
| 4950 | <YueDisplay> | ||
| 4951 | |||
| 4952 | ```yue | ||
| 4953 | export.itemA = tb | ||
| 4954 | export.<index> = items | ||
| 4955 | export["a-b-c"] = 123 | ||
| 4956 | ``` | ||
| 4957 | |||
| 4958 | </YueDisplay> | ||
| 4959 | |||
| 4960 | ### Unnamed Export | ||
| 4961 | |||
| 4962 | Unnamed export will add the target item into the array part of the exported table. | ||
| 4963 | |||
| 4964 | ```yuescript | ||
| 4965 | d, e, f = 3, 2, 1 | ||
| 4966 | export d, e, f | ||
| 4967 | |||
| 4968 | export if this | ||
| 4969 | 123 | ||
| 4970 | else | ||
| 4971 | 456 | ||
| 4972 | |||
| 4973 | export with tmp | ||
| 4974 | j = 2000 | ||
| 4975 | ``` | ||
| 4976 | |||
| 4977 | <YueDisplay> | ||
| 4978 | |||
| 4979 | ```yue | ||
| 4980 | d, e, f = 3, 2, 1 | ||
| 4981 | export d, e, f | ||
| 4982 | |||
| 4983 | export if this | ||
| 4984 | 123 | ||
| 4985 | else | ||
| 4986 | 456 | ||
| 4987 | |||
| 4988 | export with tmp | ||
| 4989 | j = 2000 | ||
| 4990 | ``` | ||
| 4991 | |||
| 4992 | </YueDisplay> | ||
| 4993 | |||
| 4994 | ### Default Export | ||
| 4995 | |||
| 4996 | Using the **default** keyword in export statement to replace the exported table with any thing. | ||
| 4997 | |||
| 4998 | ```yuescript | ||
| 4999 | export default -> | ||
| 5000 | print "hello" | ||
| 5001 | 123 | ||
| 5002 | ``` | ||
| 5003 | |||
| 5004 | <YueDisplay> | ||
| 5005 | |||
| 5006 | ```yue | ||
| 5007 | export default -> | ||
| 5008 | print "hello" | ||
| 5009 | 123 | ||
| 5010 | ``` | ||
| 5011 | |||
| 5012 | </YueDisplay> | ||
| 5013 | |||
| 5014 | # License: MIT | ||
| 5015 | |||
| 5016 | Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\> | ||
| 5017 | |||
| 5018 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 5019 | of this software and associated documentation files (the "Software"), to deal | ||
| 5020 | in the Software without restriction, including without limitation the rights | ||
| 5021 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 5022 | copies of the Software, and to permit persons to whom the Software is | ||
| 5023 | furnished to do so, subject to the following conditions: | ||
| 5024 | |||
| 5025 | The above copyright notice and this permission notice shall be included in all | ||
| 5026 | copies or substantial portions of the Software. | ||
| 5027 | |||
| 5028 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 5029 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 5030 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 5031 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 5032 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 5033 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 5034 | SOFTWARE. | ||
| 5035 | |||
| 5036 | # The YueScript Library | ||
| 5037 | |||
| 5038 | Access it by `local yue = require("yue")` in Lua. | ||
| 5039 | |||
| 5040 | ## yue | ||
| 5041 | |||
| 5042 | **Description:** | ||
| 5043 | |||
| 5044 | The YueScript language library. | ||
| 5045 | |||
| 5046 | ### version | ||
| 5047 | |||
| 5048 | **Type:** Field. | ||
| 5049 | |||
| 5050 | **Description:** | ||
| 5051 | |||
| 5052 | The YueScript version. | ||
| 5053 | |||
| 5054 | **Signature:** | ||
| 5055 | |||
| 5056 | ```lua | ||
| 5057 | version: string | ||
| 5058 | ``` | ||
| 5059 | |||
| 5060 | ### dirsep | ||
| 5061 | |||
| 5062 | **Type:** Field. | ||
| 5063 | |||
| 5064 | **Description:** | ||
| 5065 | |||
| 5066 | The file separator for the current platform. | ||
| 5067 | |||
| 5068 | **Signature:** | ||
| 5069 | |||
| 5070 | ```lua | ||
| 5071 | dirsep: string | ||
| 5072 | ``` | ||
| 5073 | |||
| 5074 | ### yue_compiled | ||
| 5075 | |||
| 5076 | **Type:** Field. | ||
| 5077 | |||
| 5078 | **Description:** | ||
| 5079 | |||
| 5080 | The compiled module code cache. | ||
| 5081 | |||
| 5082 | **Signature:** | ||
| 5083 | |||
| 5084 | ```lua | ||
| 5085 | yue_compiled: {string: string} | ||
| 5086 | ``` | ||
| 5087 | |||
| 5088 | ### to_lua | ||
| 5089 | |||
| 5090 | **Type:** Function. | ||
| 5091 | |||
| 5092 | **Description:** | ||
| 5093 | |||
| 5094 | The YueScript compiling function. It compiles the YueScript code to Lua code. | ||
| 5095 | |||
| 5096 | **Signature:** | ||
| 5097 | |||
| 5098 | ```lua | ||
| 5099 | to_lua: function(code: string, config?: Config): | ||
| 5100 | --[[codes]] string | nil, | ||
| 5101 | --[[error]] string | nil, | ||
| 5102 | --[[globals]] {{string, integer, integer}} | nil | ||
| 5103 | ``` | ||
| 5104 | |||
| 5105 | **Parameters:** | ||
| 5106 | |||
| 5107 | | Parameter | Type | Description | | ||
| 5108 | | --------- | ------ | -------------------------------- | | ||
| 5109 | | code | string | The YueScript code. | | ||
| 5110 | | config | Config | [Optional] The compiler options. | | ||
| 5111 | |||
| 5112 | **Returns:** | ||
| 5113 | |||
| 5114 | | Return Type | Description | | ||
| 5115 | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | ||
| 5116 | | string \| nil | The compiled Lua code, or nil if the compilation failed. | | ||
| 5117 | | string \| nil | The error message, or nil if the compilation succeeded. | | ||
| 5118 | | {{string, integer, integer}} \| nil | The global variables appearing in the code (with name, row and column), or nil if the compiler option `lint_global` is false. | | ||
| 5119 | |||
| 5120 | ### file_exist | ||
| 5121 | |||
| 5122 | **Type:** Function. | ||
| 5123 | |||
| 5124 | **Description:** | ||
| 5125 | |||
| 5126 | The source file existence checking function. Can be overridden to customize the behavior. | ||
| 5127 | |||
| 5128 | **Signature:** | ||
| 5129 | |||
| 5130 | ```lua | ||
| 5131 | file_exist: function(filename: string): boolean | ||
| 5132 | ``` | ||
| 5133 | |||
| 5134 | **Parameters:** | ||
| 5135 | |||
| 5136 | | Parameter | Type | Description | | ||
| 5137 | | --------- | ------ | -------------- | | ||
| 5138 | | filename | string | The file name. | | ||
| 5139 | |||
| 5140 | **Returns:** | ||
| 5141 | |||
| 5142 | | Return Type | Description | | ||
| 5143 | | ----------- | ------------------------ | | ||
| 5144 | | boolean | Whether the file exists. | | ||
| 5145 | |||
| 5146 | ### read_file | ||
| 5147 | |||
| 5148 | **Type:** Function. | ||
| 5149 | |||
| 5150 | **Description:** | ||
| 5151 | |||
| 5152 | The source file reading function. Can be overridden to customize the behavior. | ||
| 5153 | |||
| 5154 | **Signature:** | ||
| 5155 | |||
| 5156 | ```lua | ||
| 5157 | read_file: function(filename: string): string | ||
| 5158 | ``` | ||
| 5159 | |||
| 5160 | **Parameters:** | ||
| 5161 | |||
| 5162 | | Parameter | Type | Description | | ||
| 5163 | | --------- | ------ | -------------- | | ||
| 5164 | | filename | string | The file name. | | ||
| 5165 | |||
| 5166 | **Returns:** | ||
| 5167 | |||
| 5168 | | Return Type | Description | | ||
| 5169 | | ----------- | ----------------- | | ||
| 5170 | | string | The file content. | | ||
| 5171 | |||
| 5172 | ### insert_loader | ||
| 5173 | |||
| 5174 | **Type:** Function. | ||
| 5175 | |||
| 5176 | **Description:** | ||
| 5177 | |||
| 5178 | Insert the YueScript loader to the package loaders (searchers). | ||
| 5179 | |||
| 5180 | **Signature:** | ||
| 5181 | |||
| 5182 | ```lua | ||
| 5183 | insert_loader: function(pos?: integer): boolean | ||
| 5184 | ``` | ||
| 5185 | |||
| 5186 | **Parameters:** | ||
| 5187 | |||
| 5188 | | Parameter | Type | Description | | ||
| 5189 | | --------- | ------- | ----------------------------------------------------------- | | ||
| 5190 | | pos | integer | [Optional] The position to insert the loader. Default is 3. | | ||
| 5191 | |||
| 5192 | **Returns:** | ||
| 5193 | |||
| 5194 | | Return Type | Description | | ||
| 5195 | | ----------- | -------------------------------------------------------------------------------------------- | | ||
| 5196 | | boolean | Whether the loader is inserted successfully. It will fail if the loader is already inserted. | | ||
| 5197 | |||
| 5198 | ### remove_loader | ||
| 5199 | |||
| 5200 | **Type:** Function. | ||
| 5201 | |||
| 5202 | **Description:** | ||
| 5203 | |||
| 5204 | Remove the YueScript loader from the package loaders (searchers). | ||
| 5205 | |||
| 5206 | **Signature:** | ||
| 5207 | |||
| 5208 | ```lua | ||
| 5209 | remove_loader: function(): boolean | ||
| 5210 | ``` | ||
| 5211 | |||
| 5212 | **Returns:** | ||
| 5213 | |||
| 5214 | | Return Type | Description | | ||
| 5215 | | ----------- | --------------------------------------------------------------------------------------- | | ||
| 5216 | | boolean | Whether the loader is removed successfully. It will fail if the loader is not inserted. | | ||
| 5217 | |||
| 5218 | ### loadstring | ||
| 5219 | |||
| 5220 | **Type:** Function. | ||
| 5221 | |||
| 5222 | **Description:** | ||
| 5223 | |||
| 5224 | Loads YueScript code from a string into a function. | ||
| 5225 | |||
| 5226 | **Signature:** | ||
| 5227 | |||
| 5228 | ```lua | ||
| 5229 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | ||
| 5230 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5231 | --[[error]] string | nil | ||
| 5232 | ``` | ||
| 5233 | |||
| 5234 | **Parameters:** | ||
| 5235 | |||
| 5236 | | Parameter | Type | Description | | ||
| 5237 | | --------- | ------ | -------------------------------- | | ||
| 5238 | | input | string | The YueScript code. | | ||
| 5239 | | chunkname | string | The name of the code chunk. | | ||
| 5240 | | env | table | The environment table. | | ||
| 5241 | | config | Config | [Optional] The compiler options. | | ||
| 5242 | |||
| 5243 | **Returns:** | ||
| 5244 | |||
| 5245 | | Return Type | Description | | ||
| 5246 | | --------------- | --------------------------------------------------- | | ||
| 5247 | | function \| nil | The loaded function, or nil if the loading failed. | | ||
| 5248 | | string \| nil | The error message, or nil if the loading succeeded. | | ||
| 5249 | |||
| 5250 | ### loadstring | ||
| 5251 | |||
| 5252 | **Type:** Function. | ||
| 5253 | |||
| 5254 | **Description:** | ||
| 5255 | |||
| 5256 | Loads YueScript code from a string into a function. | ||
| 5257 | |||
| 5258 | **Signature:** | ||
| 5259 | |||
| 5260 | ```lua | ||
| 5261 | loadstring: function(input: string, chunkname: string, config?: Config): | ||
| 5262 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5263 | --[[error]] string | nil | ||
| 5264 | ``` | ||
| 5265 | |||
| 5266 | **Parameters:** | ||
| 5267 | |||
| 5268 | | Parameter | Type | Description | | ||
| 5269 | | --------- | ------ | -------------------------------- | | ||
| 5270 | | input | string | The YueScript code. | | ||
| 5271 | | chunkname | string | The name of the code chunk. | | ||
| 5272 | | config | Config | [Optional] The compiler options. | | ||
| 5273 | |||
| 5274 | **Returns:** | ||
| 5275 | |||
| 5276 | | Return Type | Description | | ||
| 5277 | | --------------- | --------------------------------------------------- | | ||
| 5278 | | function \| nil | The loaded function, or nil if the loading failed. | | ||
| 5279 | | string \| nil | The error message, or nil if the loading succeeded. | | ||
| 5280 | |||
| 5281 | ### loadstring | ||
| 5282 | |||
| 5283 | **Type:** Function. | ||
| 5284 | |||
| 5285 | **Description:** | ||
| 5286 | |||
| 5287 | Loads YueScript code from a string into a function. | ||
| 5288 | |||
| 5289 | **Signature:** | ||
| 5290 | |||
| 5291 | ```lua | ||
| 5292 | loadstring: function(input: string, config?: Config): | ||
| 5293 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5294 | --[[error]] string | nil | ||
| 5295 | ``` | ||
| 5296 | |||
| 5297 | **Parameters:** | ||
| 5298 | |||
| 5299 | | Parameter | Type | Description | | ||
| 5300 | | --------- | ------ | -------------------------------- | | ||
| 5301 | | input | string | The YueScript code. | | ||
| 5302 | | config | Config | [Optional] The compiler options. | | ||
| 5303 | |||
| 5304 | **Returns:** | ||
| 5305 | |||
| 5306 | | Return Type | Description | | ||
| 5307 | | --------------- | --------------------------------------------------- | | ||
| 5308 | | function \| nil | The loaded function, or nil if the loading failed. | | ||
| 5309 | | string \| nil | The error message, or nil if the loading succeeded. | | ||
| 5310 | |||
| 5311 | ### loadfile | ||
| 5312 | |||
| 5313 | **Type:** Function. | ||
| 5314 | |||
| 5315 | **Description:** | ||
| 5316 | |||
| 5317 | Loads YueScript code from a file into a function. | ||
| 5318 | |||
| 5319 | **Signature:** | ||
| 5320 | |||
| 5321 | ```lua | ||
| 5322 | loadfile: function(filename: string, env: table, config?: Config): | ||
| 5323 | nil | function(...: any): (any...), | ||
| 5324 | string | nil | ||
| 5325 | ``` | ||
| 5326 | |||
| 5327 | **Parameters:** | ||
| 5328 | |||
| 5329 | | Parameter | Type | Description | | ||
| 5330 | | --------- | ------ | -------------------------------- | | ||
| 5331 | | filename | string | The file name. | | ||
| 5332 | | env | table | The environment table. | | ||
| 5333 | | config | Config | [Optional] The compiler options. | | ||
| 5334 | |||
| 5335 | **Returns:** | ||
| 5336 | |||
| 5337 | | Return Type | Description | | ||
| 5338 | | --------------- | --------------------------------------------------- | | ||
| 5339 | | function \| nil | The loaded function, or nil if the loading failed. | | ||
| 5340 | | string \| nil | The error message, or nil if the loading succeeded. | | ||
| 5341 | |||
| 5342 | ### loadfile | ||
| 5343 | |||
| 5344 | **Type:** Function. | ||
| 5345 | |||
| 5346 | **Description:** | ||
| 5347 | |||
| 5348 | Loads YueScript code from a file into a function. | ||
| 5349 | |||
| 5350 | **Signature:** | ||
| 5351 | |||
| 5352 | ```lua | ||
| 5353 | loadfile: function(filename: string, config?: Config): | ||
| 5354 | nil | function(...: any): (any...), | ||
| 5355 | string | nil | ||
| 5356 | ``` | ||
| 5357 | |||
| 5358 | **Parameters:** | ||
| 5359 | |||
| 5360 | | Parameter | Type | Description | | ||
| 5361 | | --------- | ------ | -------------------------------- | | ||
| 5362 | | filename | string | The file name. | | ||
| 5363 | | config | Config | [Optional] The compiler options. | | ||
| 5364 | |||
| 5365 | **Returns:** | ||
| 5366 | |||
| 5367 | | Return Type | Description | | ||
| 5368 | | --------------- | --------------------------------------------------- | | ||
| 5369 | | function \| nil | The loaded function, or nil if the loading failed. | | ||
| 5370 | | string \| nil | The error message, or nil if the loading succeeded. | | ||
| 5371 | |||
| 5372 | ### dofile | ||
| 5373 | |||
| 5374 | **Type:** Function. | ||
| 5375 | |||
| 5376 | **Description:** | ||
| 5377 | |||
| 5378 | Loads YueScript code from a file into a function and executes it. | ||
| 5379 | |||
| 5380 | **Signature:** | ||
| 5381 | |||
| 5382 | ```lua | ||
| 5383 | dofile: function(filename: string, env: table, config?: Config): any... | ||
| 5384 | ``` | ||
| 5385 | |||
| 5386 | **Parameters:** | ||
| 5387 | |||
| 5388 | | Parameter | Type | Description | | ||
| 5389 | | --------- | ------ | -------------------------------- | | ||
| 5390 | | filename | string | The file name. | | ||
| 5391 | | env | table | The environment table. | | ||
| 5392 | | config | Config | [Optional] The compiler options. | | ||
| 5393 | |||
| 5394 | **Returns:** | ||
| 5395 | |||
| 5396 | | Return Type | Description | | ||
| 5397 | | ----------- | ----------------------------------------- | | ||
| 5398 | | any... | The return values of the loaded function. | | ||
| 5399 | |||
| 5400 | ### dofile | ||
| 5401 | |||
| 5402 | **Type:** Function. | ||
| 5403 | |||
| 5404 | **Description:** | ||
| 5405 | |||
| 5406 | Loads YueScript code from a file into a function and executes it. | ||
| 5407 | |||
| 5408 | **Signature:** | ||
| 5409 | |||
| 5410 | ```lua | ||
| 5411 | dofile: function(filename: string, config?: Config): any... | ||
| 5412 | ``` | ||
| 5413 | |||
| 5414 | **Parameters:** | ||
| 5415 | |||
| 5416 | | Parameter | Type | Description | | ||
| 5417 | | --------- | ------ | -------------------------------- | | ||
| 5418 | | filename | string | The file name. | | ||
| 5419 | | config | Config | [Optional] The compiler options. | | ||
| 5420 | |||
| 5421 | **Returns:** | ||
| 5422 | |||
| 5423 | | Return Type | Description | | ||
| 5424 | | ----------- | ----------------------------------------- | | ||
| 5425 | | any... | The return values of the loaded function. | | ||
| 5426 | |||
| 5427 | ### find_modulepath | ||
| 5428 | |||
| 5429 | **Type:** Function. | ||
| 5430 | |||
| 5431 | **Description:** | ||
| 5432 | |||
| 5433 | Resolves the YueScript module name to the file path. | ||
| 5434 | |||
| 5435 | **Signature:** | ||
| 5436 | |||
| 5437 | ```lua | ||
| 5438 | find_modulepath: function(name: string): string | ||
| 5439 | ``` | ||
| 5440 | |||
| 5441 | **Parameters:** | ||
| 5442 | |||
| 5443 | | Parameter | Type | Description | | ||
| 5444 | | --------- | ------ | ---------------- | | ||
| 5445 | | name | string | The module name. | | ||
| 5446 | |||
| 5447 | **Returns:** | ||
| 5448 | |||
| 5449 | | Return Type | Description | | ||
| 5450 | | ----------- | -------------- | | ||
| 5451 | | string | The file path. | | ||
| 5452 | |||
| 5453 | ### pcall | ||
| 5454 | |||
| 5455 | **Type:** Function. | ||
| 5456 | |||
| 5457 | **Description:** | ||
| 5458 | |||
| 5459 | Calls a function in protected mode. | ||
| 5460 | Catches any errors and returns a status code and results or error object. | ||
| 5461 | Rewrites the error line number to the original line number in the YueScript code when errors occur. | ||
| 5462 | |||
| 5463 | **Signature:** | ||
| 5464 | |||
| 5465 | ```lua | ||
| 5466 | pcall: function(f: function, ...: any): boolean, any... | ||
| 5467 | ``` | ||
| 5468 | |||
| 5469 | **Parameters:** | ||
| 5470 | |||
| 5471 | | Parameter | Type | Description | | ||
| 5472 | | --------- | -------- | ---------------------------------- | | ||
| 5473 | | f | function | The function to call. | | ||
| 5474 | | ... | any | Arguments to pass to the function. | | ||
| 5475 | |||
| 5476 | **Returns:** | ||
| 5477 | |||
| 5478 | | Return Type | Description | | ||
| 5479 | | ------------ | ------------------------------------------------- | | ||
| 5480 | | boolean, ... | Status code and function results or error object. | | ||
| 5481 | |||
| 5482 | ### require | ||
| 5483 | |||
| 5484 | **Type:** Function. | ||
| 5485 | |||
| 5486 | **Description:** | ||
| 5487 | |||
| 5488 | Loads a given module. Can be either a Lua module or a YueScript module. | ||
| 5489 | Rewrites the error line number to the original line number in the YueScript code if the module is a YueScript module and loading fails. | ||
| 5490 | |||
| 5491 | **Signature:** | ||
| 5492 | |||
| 5493 | ```lua | ||
| 5494 | require: function(name: string): any... | ||
| 5495 | ``` | ||
| 5496 | |||
| 5497 | **Parameters:** | ||
| 5498 | |||
| 5499 | | Parameter | Type | Description | | ||
| 5500 | | --------- | ------ | ------------------------------- | | ||
| 5501 | | modname | string | The name of the module to load. | | ||
| 5502 | |||
| 5503 | **Returns:** | ||
| 5504 | |||
| 5505 | | Return Type | Description | | ||
| 5506 | | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5507 | | any | The value stored at package.loaded[modname] if the module is already loaded.Otherwise, tries to find a loader and returns the final value of package.loaded[modname] and a loader data as a second result. | | ||
| 5508 | |||
| 5509 | ### p | ||
| 5510 | |||
| 5511 | **Type:** Function. | ||
| 5512 | |||
| 5513 | **Description:** | ||
| 5514 | |||
| 5515 | Inspects the structures of the passed values and prints string representations. | ||
| 5516 | |||
| 5517 | **Signature:** | ||
| 5518 | |||
| 5519 | ```lua | ||
| 5520 | p: function(...: any) | ||
| 5521 | ``` | ||
| 5522 | |||
| 5523 | **Parameters:** | ||
| 5524 | |||
| 5525 | | Parameter | Type | Description | | ||
| 5526 | | --------- | ---- | ---------------------- | | ||
| 5527 | | ... | any | The values to inspect. | | ||
| 5528 | |||
| 5529 | ### options | ||
| 5530 | |||
| 5531 | **Type:** Field. | ||
| 5532 | |||
| 5533 | **Description:** | ||
| 5534 | |||
| 5535 | The current compiler options. | ||
| 5536 | |||
| 5537 | **Signature:** | ||
| 5538 | |||
| 5539 | ```lua | ||
| 5540 | options: Config.Options | ||
| 5541 | ``` | ||
| 5542 | |||
| 5543 | ### traceback | ||
| 5544 | |||
| 5545 | **Type:** Function. | ||
| 5546 | |||
| 5547 | **Description:** | ||
| 5548 | |||
| 5549 | The traceback function that rewrites the stack trace line numbers to the original line numbers in the YueScript code. | ||
| 5550 | |||
| 5551 | **Signature:** | ||
| 5552 | |||
| 5553 | ```lua | ||
| 5554 | traceback: function(message: string): string | ||
| 5555 | ``` | ||
| 5556 | |||
| 5557 | **Parameters:** | ||
| 5558 | |||
| 5559 | | Parameter | Type | Description | | ||
| 5560 | | --------- | ------ | ---------------------- | | ||
| 5561 | | message | string | The traceback message. | | ||
| 5562 | |||
| 5563 | **Returns:** | ||
| 5564 | |||
| 5565 | | Return Type | Description | | ||
| 5566 | | ----------- | -------------------------------- | | ||
| 5567 | | string | The rewritten traceback message. | | ||
| 5568 | |||
| 5569 | ### is_ast | ||
| 5570 | |||
| 5571 | **Type:** Function. | ||
| 5572 | |||
| 5573 | **Description:** | ||
| 5574 | |||
| 5575 | Checks whether the code matches the specified AST. | ||
| 5576 | |||
| 5577 | **Signature:** | ||
| 5578 | |||
| 5579 | ```lua | ||
| 5580 | is_ast: function(astName: string, code: string): boolean | ||
| 5581 | ``` | ||
| 5582 | |||
| 5583 | **Parameters:** | ||
| 5584 | |||
| 5585 | | Parameter | Type | Description | | ||
| 5586 | | --------- | ------ | ------------- | | ||
| 5587 | | astName | string | The AST name. | | ||
| 5588 | | code | string | The code. | | ||
| 5589 | |||
| 5590 | **Returns:** | ||
| 5591 | |||
| 5592 | | Return Type | Description | | ||
| 5593 | | ----------- | --------------------------------- | | ||
| 5594 | | boolean | Whether the code matches the AST. | | ||
| 5595 | |||
| 5596 | ### AST | ||
| 5597 | |||
| 5598 | **Type:** Field. | ||
| 5599 | |||
| 5600 | **Description:** | ||
| 5601 | |||
| 5602 | The AST type definition with name, row, column and sub nodes. | ||
| 5603 | |||
| 5604 | **Signature:** | ||
| 5605 | |||
| 5606 | ```lua | ||
| 5607 | type AST = {string, integer, integer, any} | ||
| 5608 | ``` | ||
| 5609 | |||
| 5610 | ### to_ast | ||
| 5611 | |||
| 5612 | **Type:** Function. | ||
| 5613 | |||
| 5614 | **Description:** | ||
| 5615 | |||
| 5616 | Converts the code to the AST. | ||
| 5617 | |||
| 5618 | **Signature:** | ||
| 5619 | |||
| 5620 | ```lua | ||
| 5621 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): | ||
| 5622 | --[[AST]] AST | nil, | ||
| 5623 | --[[error]] nil | string | ||
| 5624 | ``` | ||
| 5625 | |||
| 5626 | **Parameters:** | ||
| 5627 | |||
| 5628 | | Parameter | Type | Description | | ||
| 5629 | | -------------- | ------- | --------------------------------------------------------------------------------------------- | | ||
| 5630 | | code | string | The code. | | ||
| 5631 | | flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | | ||
| 5632 | | astName | string | [Optional] The AST name. Default is "File". | | ||
| 5633 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. | | ||
| 5634 | |||
| 5635 | **Returns:** | ||
| 5636 | |||
| 5637 | | Return Type | Description | | ||
| 5638 | | ------------- | ------------------------------------------------------ | | ||
| 5639 | | AST \| nil | The AST, or nil if the conversion failed. | | ||
| 5640 | | string \| nil | The error message, or nil if the conversion succeeded. | | ||
| 5641 | |||
| 5642 | ### format | ||
| 5643 | |||
| 5644 | **Type:** Function. | ||
| 5645 | |||
| 5646 | **Description:** | ||
| 5647 | |||
| 5648 | Formats the YueScript code. | ||
| 5649 | |||
| 5650 | **Signature:** | ||
| 5651 | |||
| 5652 | ```lua | ||
| 5653 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 5654 | ``` | ||
| 5655 | |||
| 5656 | **Parameters:** | ||
| 5657 | |||
| 5658 | | Parameter | Type | Description | | ||
| 5659 | | -------------- | ------- | --------------------------------------------------------------------- | | ||
| 5660 | | code | string | The code. | | ||
| 5661 | | tabSize | integer | [Optional] The tab size. Default is 4. | | ||
| 5662 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. | | ||
| 5663 | |||
| 5664 | **Returns:** | ||
| 5665 | |||
| 5666 | | Return Type | Description | | ||
| 5667 | | ----------- | ------------------- | | ||
| 5668 | | string | The formatted code. | | ||
| 5669 | |||
| 5670 | ### \_\_call | ||
| 5671 | |||
| 5672 | **Type:** Metamethod. | ||
| 5673 | |||
| 5674 | **Description:** | ||
| 5675 | |||
| 5676 | Requires the YueScript module. | ||
| 5677 | Rewrites the error line number to the original line number in the YueScript code when loading fails. | ||
| 5678 | |||
| 5679 | **Signature:** | ||
| 5680 | |||
| 5681 | ```lua | ||
| 5682 | metamethod __call: function(self: yue, module: string): any... | ||
| 5683 | ``` | ||
| 5684 | |||
| 5685 | **Parameters:** | ||
| 5686 | |||
| 5687 | | Parameter | Type | Description | | ||
| 5688 | | --------- | ------ | ---------------- | | ||
| 5689 | | module | string | The module name. | | ||
| 5690 | |||
| 5691 | **Returns:** | ||
| 5692 | |||
| 5693 | | Return Type | Description | | ||
| 5694 | | ----------- | ----------------- | | ||
| 5695 | | any | The module value. | | ||
| 5696 | |||
| 5697 | ## Config | ||
| 5698 | |||
| 5699 | **Description:** | ||
| 5700 | |||
| 5701 | The compiler compile options. | ||
| 5702 | |||
| 5703 | ### lint_global | ||
| 5704 | |||
| 5705 | **Type:** Field. | ||
| 5706 | |||
| 5707 | **Description:** | ||
| 5708 | |||
| 5709 | Whether the compiler should collect the global variables appearing in the code. | ||
| 5710 | |||
| 5711 | **Signature:** | ||
| 5712 | |||
| 5713 | ```lua | ||
| 5714 | lint_global: boolean | ||
| 5715 | ``` | ||
| 5716 | |||
| 5717 | ### implicit_return_root | ||
| 5718 | |||
| 5719 | **Type:** Field. | ||
| 5720 | |||
| 5721 | **Description:** | ||
| 5722 | |||
| 5723 | Whether the compiler should do an implicit return for the root code block. | ||
| 5724 | |||
| 5725 | **Signature:** | ||
| 5726 | |||
| 5727 | ```lua | ||
| 5728 | implicit_return_root: boolean | ||
| 5729 | ``` | ||
| 5730 | |||
| 5731 | ### reserve_line_number | ||
| 5732 | |||
| 5733 | **Type:** Field. | ||
| 5734 | |||
| 5735 | **Description:** | ||
| 5736 | |||
| 5737 | Whether the compiler should reserve the original line number in the compiled code. | ||
| 5738 | |||
| 5739 | **Signature:** | ||
| 5740 | |||
| 5741 | ```lua | ||
| 5742 | reserve_line_number: boolean | ||
| 5743 | ``` | ||
| 5744 | |||
| 5745 | ### reserve_comment | ||
| 5746 | |||
| 5747 | **Type:** Field. | ||
| 5748 | |||
| 5749 | **Description:** | ||
| 5750 | |||
| 5751 | Whether the compiler should reserve the original comments in the compiled code. | ||
| 5752 | |||
| 5753 | **Signature:** | ||
| 5754 | |||
| 5755 | ```lua | ||
| 5756 | reserve_comment: boolean | ||
| 5757 | ``` | ||
| 5758 | |||
| 5759 | ### space_over_tab | ||
| 5760 | |||
| 5761 | **Type:** Field. | ||
| 5762 | |||
| 5763 | **Description:** | ||
| 5764 | |||
| 5765 | Whether the compiler should use the space character instead of the tab character in the compiled code. | ||
| 5766 | |||
| 5767 | **Signature:** | ||
| 5768 | |||
| 5769 | ```lua | ||
| 5770 | space_over_tab: boolean | ||
| 5771 | ``` | ||
| 5772 | |||
| 5773 | ### same_module | ||
| 5774 | |||
| 5775 | **Type:** Field. | ||
| 5776 | |||
| 5777 | **Description:** | ||
| 5778 | |||
| 5779 | Whether the compiler should treat the code to be compiled as the same currently being compiled module. For internal use only. | ||
| 5780 | |||
| 5781 | **Signature:** | ||
| 5782 | |||
| 5783 | ```lua | ||
| 5784 | same_module: boolean | ||
| 5785 | ``` | ||
| 5786 | |||
| 5787 | ### line_offset | ||
| 5788 | |||
| 5789 | **Type:** Field. | ||
| 5790 | |||
| 5791 | **Description:** | ||
| 5792 | |||
| 5793 | Whether the compiler error message should include the line number offset. For internal use only. | ||
| 5794 | |||
| 5795 | **Signature:** | ||
| 5796 | |||
| 5797 | ```lua | ||
| 5798 | line_offset: integer | ||
| 5799 | ``` | ||
| 5800 | |||
| 5801 | ### yue.Config.LuaTarget | ||
| 5802 | |||
| 5803 | **Type:** Enumeration. | ||
| 5804 | |||
| 5805 | **Description:** | ||
| 5806 | |||
| 5807 | The target Lua version enumeration. | ||
| 5808 | |||
| 5809 | **Signature:** | ||
| 5810 | |||
| 5811 | ```lua | ||
| 5812 | enum LuaTarget | ||
| 5813 | "5.1" | ||
| 5814 | "5.2" | ||
| 5815 | "5.3" | ||
| 5816 | "5.4" | ||
| 5817 | "5.5" | ||
| 5818 | end | ||
| 5819 | ``` | ||
| 5820 | |||
| 5821 | ### options | ||
| 5822 | |||
| 5823 | **Type:** Field. | ||
| 5824 | |||
| 5825 | **Description:** | ||
| 5826 | |||
| 5827 | The extra options to be passed to the compilation function. | ||
| 5828 | |||
| 5829 | **Signature:** | ||
| 5830 | |||
| 5831 | ```lua | ||
| 5832 | options: Options | ||
| 5833 | ``` | ||
| 5834 | |||
| 5835 | ## Options | ||
| 5836 | |||
| 5837 | **Description:** | ||
| 5838 | |||
| 5839 | The extra compiler options definition. | ||
| 5840 | |||
| 5841 | ### target | ||
| 5842 | |||
| 5843 | **Type:** Field. | ||
| 5844 | |||
| 5845 | **Description:** | ||
| 5846 | |||
| 5847 | The target Lua version for the compilation. | ||
| 5848 | |||
| 5849 | **Signature:** | ||
| 5850 | |||
| 5851 | ```lua | ||
| 5852 | target: LuaTarget | ||
| 5853 | ``` | ||
| 5854 | |||
| 5855 | ### path | ||
| 5856 | |||
| 5857 | **Type:** Field. | ||
| 5858 | |||
| 5859 | **Description:** | ||
| 5860 | |||
| 5861 | The extra module search path. | ||
| 5862 | |||
| 5863 | **Signature:** | ||
| 5864 | |||
| 5865 | ```lua | ||
| 5866 | path: string | ||
| 5867 | ``` | ||
| 5868 | |||
| 5869 | ### dump_locals | ||
| 5870 | |||
| 5871 | **Type:** Field. | ||
| 5872 | |||
| 5873 | **Description:** | ||
| 5874 | |||
| 5875 | Whether to dump the local variables in the traceback error message. Default is false. | ||
| 5876 | |||
| 5877 | **Signature:** | ||
| 5878 | |||
| 5879 | ```lua | ||
| 5880 | dump_locals: boolean | ||
| 5881 | ``` | ||
| 5882 | |||
| 5883 | ### simplified | ||
| 5884 | |||
| 5885 | **Type:** Field. | ||
| 5886 | |||
| 5887 | **Description:** | ||
| 5888 | |||
| 5889 | Whether to simplify the error message. Default is true. | ||
| 5890 | |||
| 5891 | **Signature:** | ||
| 5892 | |||
| 5893 | ```lua | ||
| 5894 | simplified: boolean | ||
| 5895 | ``` | ||
diff --git a/doc/yue-id-id.md b/doc/yue-id-id.md new file mode 100644 index 0000000..704ebe4 --- /dev/null +++ b/doc/yue-id-id.md | |||
| @@ -0,0 +1,5890 @@ | |||
| 1 | --- | ||
| 2 | title: Referensi | ||
| 3 | --- | ||
| 4 | |||
| 5 | # Dokumentasi YueScript | ||
| 6 | |||
| 7 | <img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em; padding-bottom: 2em;"/> | ||
| 8 | |||
| 9 | Selamat datang di dokumentasi resmi <b>YueScript</b>!<br/> | ||
| 10 | Di sini Anda dapat menemukan fitur bahasa, penggunaan, contoh referensi, dan sumber daya.<br/> | ||
| 11 | Silakan pilih bab dari sidebar untuk mulai mempelajari YueScript. | ||
| 12 | |||
| 13 | # Do | ||
| 14 | |||
| 15 | Saat digunakan sebagai pernyataan, `do` bekerja seperti di Lua. | ||
| 16 | |||
| 17 | ```yuescript | ||
| 18 | do | ||
| 19 | var = "hello" | ||
| 20 | print var | ||
| 21 | print var -- nil di sini | ||
| 22 | ``` | ||
| 23 | |||
| 24 | <YueDisplay> | ||
| 25 | |||
| 26 | ```yue | ||
| 27 | do | ||
| 28 | var = "hello" | ||
| 29 | print var | ||
| 30 | print var -- nil di sini | ||
| 31 | ``` | ||
| 32 | |||
| 33 | </YueDisplay> | ||
| 34 | |||
| 35 | `do` di YueScript juga bisa digunakan sebagai ekspresi, memungkinkan Anda menggabungkan beberapa baris menjadi satu. Hasil ekspresi `do` adalah pernyataan terakhir di badannya. Ekspresi `do` mendukung penggunaan `break` untuk memutus alur eksekusi dan mengembalikan banyak nilai lebih awal. | ||
| 36 | |||
| 37 | ```yuescript | ||
| 38 | status, value = do | ||
| 39 | n = 12 | ||
| 40 | if n > 10 | ||
| 41 | break "large", n | ||
| 42 | break "small", n | ||
| 43 | ``` | ||
| 44 | |||
| 45 | <YueDisplay> | ||
| 46 | |||
| 47 | ```yue | ||
| 48 | status, value = do | ||
| 49 | n = 12 | ||
| 50 | if n > 10 | ||
| 51 | break "large", n | ||
| 52 | break "small", n | ||
| 53 | ``` | ||
| 54 | |||
| 55 | </YueDisplay> | ||
| 56 | |||
| 57 | ```yuescript | ||
| 58 | counter = do | ||
| 59 | i = 0 | ||
| 60 | -> | ||
| 61 | i += 1 | ||
| 62 | i | ||
| 63 | |||
| 64 | print counter! | ||
| 65 | print counter! | ||
| 66 | ``` | ||
| 67 | |||
| 68 | <YueDisplay> | ||
| 69 | |||
| 70 | ```yue | ||
| 71 | counter = do | ||
| 72 | i = 0 | ||
| 73 | -> | ||
| 74 | i += 1 | ||
| 75 | i | ||
| 76 | |||
| 77 | print counter! | ||
| 78 | print counter! | ||
| 79 | ``` | ||
| 80 | |||
| 81 | </YueDisplay> | ||
| 82 | |||
| 83 | ```yuescript | ||
| 84 | tbl = { | ||
| 85 | key: do | ||
| 86 | print "assigning key!" | ||
| 87 | 1234 | ||
| 88 | } | ||
| 89 | ``` | ||
| 90 | |||
| 91 | <YueDisplay> | ||
| 92 | |||
| 93 | ```yue | ||
| 94 | tbl = { | ||
| 95 | key: do | ||
| 96 | print "assigning key!" | ||
| 97 | 1234 | ||
| 98 | } | ||
| 99 | ``` | ||
| 100 | |||
| 101 | </YueDisplay> | ||
| 102 | |||
| 103 | # Dekorator Baris | ||
| 104 | |||
| 105 | Untuk kemudahan, loop for dan pernyataan if dapat diterapkan pada pernyataan tunggal di akhir baris: | ||
| 106 | |||
| 107 | ```yuescript | ||
| 108 | print "hello world" if name == "Rob" | ||
| 109 | ``` | ||
| 110 | |||
| 111 | <YueDisplay> | ||
| 112 | |||
| 113 | ```yue | ||
| 114 | print "hello world" if name == "Rob" | ||
| 115 | ``` | ||
| 116 | |||
| 117 | </YueDisplay> | ||
| 118 | |||
| 119 | Dan dengan loop dasar: | ||
| 120 | |||
| 121 | ```yuescript | ||
| 122 | print "item: ", item for item in *items | ||
| 123 | ``` | ||
| 124 | |||
| 125 | <YueDisplay> | ||
| 126 | |||
| 127 | ```yue | ||
| 128 | print "item: ", item for item in *items | ||
| 129 | ``` | ||
| 130 | |||
| 131 | </YueDisplay> | ||
| 132 | |||
| 133 | Dan dengan loop while: | ||
| 134 | |||
| 135 | ```yuescript | ||
| 136 | game\update! while game\isRunning! | ||
| 137 | |||
| 138 | reader\parse_line! until reader\eof! | ||
| 139 | ``` | ||
| 140 | |||
| 141 | <YueDisplay> | ||
| 142 | |||
| 143 | ```yue | ||
| 144 | game\update! while game\isRunning! | ||
| 145 | |||
| 146 | reader\parse_line! until reader\eof! | ||
| 147 | ``` | ||
| 148 | |||
| 149 | </YueDisplay> | ||
| 150 | |||
| 151 | # Makro | ||
| 152 | |||
| 153 | ## Penggunaan Umum | ||
| 154 | |||
| 155 | Fungsi macro digunakan untuk mengevaluasi string pada waktu kompilasi dan menyisipkan kode yang dihasilkan ke kompilasi akhir. | ||
| 156 | |||
| 157 | ```yuescript | ||
| 158 | macro PI2 = -> math.pi * 2 | ||
| 159 | area = $PI2 * 5 | ||
| 160 | |||
| 161 | macro HELLO = -> "'hello world'" | ||
| 162 | print $HELLO | ||
| 163 | |||
| 164 | macro config = (debugging) -> | ||
| 165 | global debugMode = debugging == "true" | ||
| 166 | "" | ||
| 167 | |||
| 168 | macro asserts = (cond) -> | ||
| 169 | debugMode and "assert #{cond}" or "" | ||
| 170 | |||
| 171 | macro assert = (cond) -> | ||
| 172 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 173 | |||
| 174 | $config true | ||
| 175 | $asserts item ~= nil | ||
| 176 | |||
| 177 | $config false | ||
| 178 | value = $assert item | ||
| 179 | |||
| 180 | -- ekspresi yang dikirim diperlakukan sebagai string | ||
| 181 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 182 | if $and f1!, f2!, f3! | ||
| 183 | print "OK" | ||
| 184 | ``` | ||
| 185 | |||
| 186 | <YueDisplay> | ||
| 187 | |||
| 188 | ```yue | ||
| 189 | macro PI2 = -> math.pi * 2 | ||
| 190 | area = $PI2 * 5 | ||
| 191 | |||
| 192 | macro HELLO = -> "'hello world'" | ||
| 193 | print $HELLO | ||
| 194 | |||
| 195 | macro config = (debugging) -> | ||
| 196 | global debugMode = debugging == "true" | ||
| 197 | "" | ||
| 198 | |||
| 199 | macro asserts = (cond) -> | ||
| 200 | debugMode and "assert #{cond}" or "" | ||
| 201 | |||
| 202 | macro assert = (cond) -> | ||
| 203 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 204 | |||
| 205 | $config true | ||
| 206 | $asserts item ~= nil | ||
| 207 | |||
| 208 | $config false | ||
| 209 | value = $assert item | ||
| 210 | |||
| 211 | -- ekspresi yang dikirim diperlakukan sebagai string | ||
| 212 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 213 | if $and f1!, f2!, f3! | ||
| 214 | print "OK" | ||
| 215 | ``` | ||
| 216 | |||
| 217 | </YueDisplay> | ||
| 218 | |||
| 219 | ## Menyisipkan Kode Mentah | ||
| 220 | |||
| 221 | Fungsi macro bisa mengembalikan string YueScript atau tabel konfigurasi yang berisi kode Lua. | ||
| 222 | |||
| 223 | ```yuescript | ||
| 224 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 225 | $yueFunc funcA | ||
| 226 | funcA = -> "gagal meng-assign ke variabel yang didefinisikan oleh macro Yue" | ||
| 227 | |||
| 228 | macro luaFunc = (var) -> { | ||
| 229 | code: "local function #{var}() end" | ||
| 230 | type: "lua" | ||
| 231 | } | ||
| 232 | $luaFunc funcB | ||
| 233 | funcB = -> "gagal meng-assign ke variabel yang didefinisikan oleh macro Lua" | ||
| 234 | |||
| 235 | macro lua = (code) -> { | ||
| 236 | :code | ||
| 237 | type: "lua" | ||
| 238 | } | ||
| 239 | |||
| 240 | -- simbol awal dan akhir string mentah otomatis di-trim | ||
| 241 | $lua[==[ | ||
| 242 | -- penyisipan kode Lua mentah | ||
| 243 | if cond then | ||
| 244 | print("output") | ||
| 245 | end | ||
| 246 | ]==] | ||
| 247 | ``` | ||
| 248 | |||
| 249 | <YueDisplay> | ||
| 250 | |||
| 251 | ```yue | ||
| 252 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 253 | $yueFunc funcA | ||
| 254 | funcA = -> "gagal meng-assign ke variabel yang didefinisikan oleh macro Yue" | ||
| 255 | |||
| 256 | macro luaFunc = (var) -> { | ||
| 257 | code: "local function #{var}() end" | ||
| 258 | type: "lua" | ||
| 259 | } | ||
| 260 | $luaFunc funcB | ||
| 261 | funcB = -> "gagal meng-assign ke variabel yang didefinisikan oleh macro Lua" | ||
| 262 | |||
| 263 | macro lua = (code) -> { | ||
| 264 | :code | ||
| 265 | type: "lua" | ||
| 266 | } | ||
| 267 | |||
| 268 | -- simbol awal dan akhir string mentah otomatis di-trim | ||
| 269 | $lua[==[ | ||
| 270 | -- penyisipan kode Lua mentah | ||
| 271 | if cond then | ||
| 272 | print("output") | ||
| 273 | end | ||
| 274 | ]==] | ||
| 275 | ``` | ||
| 276 | |||
| 277 | </YueDisplay> | ||
| 278 | |||
| 279 | ## Export Macro | ||
| 280 | |||
| 281 | Fungsi macro dapat diekspor dari modul dan diimpor di modul lain. Anda harus menaruh fungsi macro export dalam satu file agar dapat digunakan, dan hanya definisi macro, impor macro, dan ekspansi macro yang boleh ada di modul export macro. | ||
| 282 | |||
| 283 | ```yuescript | ||
| 284 | -- file: utils.yue | ||
| 285 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 286 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 287 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 288 | #{action}" | ||
| 289 | |||
| 290 | -- file main.yue | ||
| 291 | import "utils" as { | ||
| 292 | $, -- simbol untuk mengimpor semua macro | ||
| 293 | $foreach: $each -- ganti nama macro $foreach menjadi $each | ||
| 294 | } | ||
| 295 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 296 | ``` | ||
| 297 | |||
| 298 | <YueDisplay> | ||
| 299 | |||
| 300 | ```yue | ||
| 301 | -- file: utils.yue | ||
| 302 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 303 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 304 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 305 | #{action}" | ||
| 306 | |||
| 307 | -- file main.yue | ||
| 308 | -- fungsi import tidak tersedia di browser, coba di lingkungan nyata | ||
| 309 | --[[ | ||
| 310 | import "utils" as { | ||
| 311 | $, -- simbol untuk mengimpor semua macro | ||
| 312 | $foreach: $each -- ganti nama macro $foreach menjadi $each | ||
| 313 | } | ||
| 314 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 315 | ]] | ||
| 316 | ``` | ||
| 317 | |||
| 318 | </YueDisplay> | ||
| 319 | |||
| 320 | ## Macro Bawaan | ||
| 321 | |||
| 322 | Ada beberapa macro bawaan tetapi Anda bisa menimpanya dengan mendeklarasikan macro dengan nama yang sama. | ||
| 323 | |||
| 324 | ```yuescript | ||
| 325 | print $FILE -- mendapatkan string nama modul saat ini | ||
| 326 | print $LINE -- mendapatkan angka 2 | ||
| 327 | ``` | ||
| 328 | |||
| 329 | <YueDisplay> | ||
| 330 | |||
| 331 | ```yue | ||
| 332 | print $FILE -- mendapatkan string nama modul saat ini | ||
| 333 | print $LINE -- mendapatkan angka 2 | ||
| 334 | ``` | ||
| 335 | |||
| 336 | </YueDisplay> | ||
| 337 | |||
| 338 | ## Menghasilkan Macro dengan Macro | ||
| 339 | |||
| 340 | Di YueScript, fungsi macro memungkinkan Anda menghasilkan kode pada waktu kompilasi. Dengan menumpuk fungsi macro, Anda dapat membuat pola generasi yang lebih kompleks. Fitur ini memungkinkan Anda mendefinisikan fungsi macro yang menghasilkan fungsi macro lain, sehingga menghasilkan kode yang lebih dinamis. | ||
| 341 | |||
| 342 | ```yuescript | ||
| 343 | macro Enum = (...) -> | ||
| 344 | items = {...} | ||
| 345 | itemSet = {item, true for item in *items} | ||
| 346 | (item) -> | ||
| 347 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 348 | "\"#{item}\"" | ||
| 349 | |||
| 350 | macro BodyType = $Enum( | ||
| 351 | Static | ||
| 352 | Dynamic | ||
| 353 | Kinematic | ||
| 354 | ) | ||
| 355 | |||
| 356 | print "Valid enum type:", $BodyType Static | ||
| 357 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 358 | ``` | ||
| 359 | |||
| 360 | <YueDisplay> | ||
| 361 | |||
| 362 | ```yue | ||
| 363 | macro Enum = (...) -> | ||
| 364 | items = {...} | ||
| 365 | itemSet = {item, true for item in *items} | ||
| 366 | (item) -> | ||
| 367 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 368 | "\"#{item}\"" | ||
| 369 | |||
| 370 | macro BodyType = $Enum( | ||
| 371 | Static | ||
| 372 | Dynamic | ||
| 373 | Kinematic | ||
| 374 | ) | ||
| 375 | |||
| 376 | print "Valid enum type:", $BodyType Static | ||
| 377 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 378 | ``` | ||
| 379 | |||
| 380 | </YueDisplay> | ||
| 381 | |||
| 382 | ## Validasi Argumen | ||
| 383 | |||
| 384 | Anda dapat mendeklarasikan tipe node AST yang diharapkan dalam daftar argumen, dan memeriksa apakah argumen macro yang masuk memenuhi harapan pada waktu kompilasi. | ||
| 385 | |||
| 386 | ```yuescript | ||
| 387 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 388 | print( | ||
| 389 | #{num} | ||
| 390 | #{str} | ||
| 391 | ) | ||
| 392 | |||
| 393 | $printNumAndStr 123, "hello" | ||
| 394 | ``` | ||
| 395 | |||
| 396 | <YueDisplay> | ||
| 397 | |||
| 398 | ```yue | ||
| 399 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 400 | print( | ||
| 401 | #{num} | ||
| 402 | #{str} | ||
| 403 | ) | ||
| 404 | |||
| 405 | $printNumAndStr 123, "hello" | ||
| 406 | ``` | ||
| 407 | |||
| 408 | </YueDisplay> | ||
| 409 | |||
| 410 | Jika Anda membutuhkan pengecekan argumen yang lebih fleksibel, Anda dapat menggunakan fungsi macro bawaan `$is_ast` untuk memeriksa secara manual pada tempat yang tepat. | ||
| 411 | |||
| 412 | ```yuescript | ||
| 413 | macro printNumAndStr = (num, str) -> | ||
| 414 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 415 | error "expected String as second argument" unless $is_ast String, str | ||
| 416 | "print(#{num}, #{str})" | ||
| 417 | |||
| 418 | $printNumAndStr 123, "hello" | ||
| 419 | ``` | ||
| 420 | |||
| 421 | <YueDisplay> | ||
| 422 | |||
| 423 | ```yue | ||
| 424 | macro printNumAndStr = (num, str) -> | ||
| 425 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 426 | error "expected String as second argument" unless $is_ast String, str | ||
| 427 | "print(#{num}, #{str})" | ||
| 428 | |||
| 429 | $printNumAndStr 123, "hello" | ||
| 430 | ``` | ||
| 431 | |||
| 432 | </YueDisplay> | ||
| 433 | |||
| 434 | Untuk detail lebih lanjut tentang node AST yang tersedia, silakan lihat definisi huruf besar di [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
| 435 | |||
| 436 | # Try | ||
| 437 | |||
| 438 | Sintaks untuk penanganan error Lua dalam bentuk umum. | ||
| 439 | |||
| 440 | ```yuescript | ||
| 441 | try | ||
| 442 | func 1, 2, 3 | ||
| 443 | catch err | ||
| 444 | print yue.traceback err | ||
| 445 | |||
| 446 | success, result = try | ||
| 447 | func 1, 2, 3 | ||
| 448 | catch err | ||
| 449 | yue.traceback err | ||
| 450 | |||
| 451 | try func 1, 2, 3 | ||
| 452 | catch err | ||
| 453 | print yue.traceback err | ||
| 454 | |||
| 455 | success, result = try func 1, 2, 3 | ||
| 456 | |||
| 457 | try | ||
| 458 | print "trying" | ||
| 459 | func 1, 2, 3 | ||
| 460 | |||
| 461 | -- bekerja dengan pola if assignment | ||
| 462 | if success, result := try func 1, 2, 3 | ||
| 463 | catch err | ||
| 464 | print yue.traceback err | ||
| 465 | print result | ||
| 466 | ``` | ||
| 467 | |||
| 468 | <YueDisplay> | ||
| 469 | |||
| 470 | ```yue | ||
| 471 | try | ||
| 472 | func 1, 2, 3 | ||
| 473 | catch err | ||
| 474 | print yue.traceback err | ||
| 475 | |||
| 476 | success, result = try | ||
| 477 | func 1, 2, 3 | ||
| 478 | catch err | ||
| 479 | yue.traceback err | ||
| 480 | |||
| 481 | try func 1, 2, 3 | ||
| 482 | catch err | ||
| 483 | print yue.traceback err | ||
| 484 | |||
| 485 | success, result = try func 1, 2, 3 | ||
| 486 | |||
| 487 | try | ||
| 488 | print "trying" | ||
| 489 | func 1, 2, 3 | ||
| 490 | |||
| 491 | -- bekerja dengan pola if assignment | ||
| 492 | if success, result := try func 1, 2, 3 | ||
| 493 | catch err | ||
| 494 | print yue.traceback err | ||
| 495 | print result | ||
| 496 | ``` | ||
| 497 | |||
| 498 | </YueDisplay> | ||
| 499 | |||
| 500 | ## Try? | ||
| 501 | |||
| 502 | `try?` adalah bentuk sederhana untuk penanganan error yang menghilangkan status boolean dari pernyataan `try`, dan akan mengembalikan hasil dari blok try ketika berhasil, atau mengembalikan nil alih-alih objek error bila gagal. | ||
| 503 | |||
| 504 | ```yuescript | ||
| 505 | a, b, c = try? func! | ||
| 506 | |||
| 507 | -- dengan operator nil coalescing | ||
| 508 | a = (try? func!) ?? "default" | ||
| 509 | |||
| 510 | -- sebagai argumen fungsi | ||
| 511 | f try? func! | ||
| 512 | |||
| 513 | -- dengan blok catch | ||
| 514 | f try? | ||
| 515 | print 123 | ||
| 516 | func! | ||
| 517 | catch e | ||
| 518 | print e | ||
| 519 | e | ||
| 520 | ``` | ||
| 521 | |||
| 522 | <YueDisplay> | ||
| 523 | |||
| 524 | ```yue | ||
| 525 | a, b, c = try? func! | ||
| 526 | |||
| 527 | -- dengan operator nil coalescing | ||
| 528 | a = (try? func!) ?? "default" | ||
| 529 | |||
| 530 | -- sebagai argumen fungsi | ||
| 531 | f try? func! | ||
| 532 | |||
| 533 | -- dengan blok catch | ||
| 534 | f try? | ||
| 535 | print 123 | ||
| 536 | func! | ||
| 537 | catch e | ||
| 538 | print e | ||
| 539 | e | ||
| 540 | ``` | ||
| 541 | |||
| 542 | </YueDisplay> | ||
| 543 | |||
| 544 | # Literal Tabel | ||
| 545 | |||
| 546 | Seperti di Lua, tabel dibatasi dengan kurung kurawal. | ||
| 547 | |||
| 548 | ```yuescript | ||
| 549 | some_values = [1, 2, 3, 4] | ||
| 550 | ``` | ||
| 551 | |||
| 552 | <YueDisplay> | ||
| 553 | |||
| 554 | ```yue | ||
| 555 | some_values = [1, 2, 3, 4] | ||
| 556 | ``` | ||
| 557 | |||
| 558 | </YueDisplay> | ||
| 559 | |||
| 560 | Berbeda dengan Lua, assignment nilai ke sebuah kunci di tabel dilakukan dengan **:** (bukan **=**). | ||
| 561 | |||
| 562 | ```yuescript | ||
| 563 | some_values = { | ||
| 564 | name: "Bill", | ||
| 565 | age: 200, | ||
| 566 | ["favorite food"]: "rice" | ||
| 567 | } | ||
| 568 | ``` | ||
| 569 | |||
| 570 | <YueDisplay> | ||
| 571 | |||
| 572 | ```yue | ||
| 573 | some_values = { | ||
| 574 | name: "Bill", | ||
| 575 | age: 200, | ||
| 576 | ["favorite food"]: "rice" | ||
| 577 | } | ||
| 578 | ``` | ||
| 579 | |||
| 580 | </YueDisplay> | ||
| 581 | |||
| 582 | Kurung kurawal dapat dihilangkan jika hanya satu tabel pasangan key-value yang di-assign. | ||
| 583 | |||
| 584 | ```yuescript | ||
| 585 | profile = | ||
| 586 | height: "4 feet", | ||
| 587 | shoe_size: 13, | ||
| 588 | favorite_foods: ["ice cream", "donuts"] | ||
| 589 | ``` | ||
| 590 | |||
| 591 | <YueDisplay> | ||
| 592 | |||
| 593 | ```yue | ||
| 594 | profile = | ||
| 595 | height: "4 feet", | ||
| 596 | shoe_size: 13, | ||
| 597 | favorite_foods: ["ice cream", "donuts"] | ||
| 598 | ``` | ||
| 599 | |||
| 600 | </YueDisplay> | ||
| 601 | |||
| 602 | Baris baru dapat digunakan untuk memisahkan nilai sebagai ganti koma (atau keduanya): | ||
| 603 | |||
| 604 | ```yuescript | ||
| 605 | values = { | ||
| 606 | 1, 2, 3, 4 | ||
| 607 | 5, 6, 7, 8 | ||
| 608 | name: "superman" | ||
| 609 | occupation: "crime fighting" | ||
| 610 | } | ||
| 611 | ``` | ||
| 612 | |||
| 613 | <YueDisplay> | ||
| 614 | |||
| 615 | ```yue | ||
| 616 | values = { | ||
| 617 | 1, 2, 3, 4 | ||
| 618 | 5, 6, 7, 8 | ||
| 619 | name: "superman" | ||
| 620 | occupation: "crime fighting" | ||
| 621 | } | ||
| 622 | ``` | ||
| 623 | |||
| 624 | </YueDisplay> | ||
| 625 | |||
| 626 | Saat membuat literal tabel satu baris, kurung kurawal juga bisa dihilangkan: | ||
| 627 | |||
| 628 | ```yuescript | ||
| 629 | my_function dance: "Tango", partner: "none" | ||
| 630 | |||
| 631 | y = type: "dog", legs: 4, tails: 1 | ||
| 632 | ``` | ||
| 633 | |||
| 634 | <YueDisplay> | ||
| 635 | |||
| 636 | ```yue | ||
| 637 | my_function dance: "Tango", partner: "none" | ||
| 638 | |||
| 639 | y = type: "dog", legs: 4, tails: 1 | ||
| 640 | ``` | ||
| 641 | |||
| 642 | </YueDisplay> | ||
| 643 | |||
| 644 | Kunci literal tabel dapat berupa kata kunci bahasa tanpa perlu di-escape: | ||
| 645 | |||
| 646 | ```yuescript | ||
| 647 | tbl = { | ||
| 648 | do: "something" | ||
| 649 | end: "hunger" | ||
| 650 | } | ||
| 651 | ``` | ||
| 652 | |||
| 653 | <YueDisplay> | ||
| 654 | |||
| 655 | ```yue | ||
| 656 | tbl = { | ||
| 657 | do: "something" | ||
| 658 | end: "hunger" | ||
| 659 | } | ||
| 660 | ``` | ||
| 661 | |||
| 662 | </YueDisplay> | ||
| 663 | |||
| 664 | Jika Anda membangun tabel dari variabel dan ingin kunci sama dengan nama variabel, maka operator prefiks **:** dapat digunakan: | ||
| 665 | |||
| 666 | ```yuescript | ||
| 667 | hair = "golden" | ||
| 668 | height = 200 | ||
| 669 | person = { :hair, :height, shoe_size: 40 } | ||
| 670 | |||
| 671 | print_table :hair, :height | ||
| 672 | ``` | ||
| 673 | |||
| 674 | <YueDisplay> | ||
| 675 | |||
| 676 | ```yue | ||
| 677 | hair = "golden" | ||
| 678 | height = 200 | ||
| 679 | person = { :hair, :height, shoe_size: 40 } | ||
| 680 | |||
| 681 | print_table :hair, :height | ||
| 682 | ``` | ||
| 683 | |||
| 684 | </YueDisplay> | ||
| 685 | |||
| 686 | Jika Anda ingin kunci field dalam tabel menjadi hasil suatu ekspresi, Anda dapat membungkusnya dengan **[ ]**, seperti di Lua. Anda juga bisa menggunakan literal string langsung sebagai kunci tanpa tanda kurung siku. Ini berguna jika kunci memiliki karakter khusus. | ||
| 687 | |||
| 688 | ```yuescript | ||
| 689 | t = { | ||
| 690 | [1 + 2]: "hello" | ||
| 691 | "hello world": true | ||
| 692 | } | ||
| 693 | ``` | ||
| 694 | |||
| 695 | <YueDisplay> | ||
| 696 | |||
| 697 | ```yue | ||
| 698 | t = { | ||
| 699 | [1 + 2]: "hello" | ||
| 700 | "hello world": true | ||
| 701 | } | ||
| 702 | ``` | ||
| 703 | |||
| 704 | </YueDisplay> | ||
| 705 | |||
| 706 | Tabel Lua memiliki bagian array dan bagian hash, tetapi terkadang Anda ingin membedakan penggunaan array dan hash secara semantik saat menulis tabel Lua. Maka Anda bisa menulis tabel Lua dengan **[ ]** alih-alih **{ }** untuk merepresentasikan tabel array, dan menuliskan pasangan key-value di tabel list tidak akan diizinkan. | ||
| 707 | |||
| 708 | ```yuescript | ||
| 709 | some_values = [1, 2, 3, 4] | ||
| 710 | list_with_one_element = [1, ] | ||
| 711 | ``` | ||
| 712 | |||
| 713 | <YueDisplay> | ||
| 714 | |||
| 715 | ```yue | ||
| 716 | some_values = [1, 2, 3, 4] | ||
| 717 | list_with_one_element = [1, ] | ||
| 718 | ``` | ||
| 719 | |||
| 720 | </YueDisplay> | ||
| 721 | |||
| 722 | # Komprehensi | ||
| 723 | |||
| 724 | Komprehensi menyediakan sintaks yang nyaman untuk membangun tabel baru dengan mengiterasi objek yang ada dan menerapkan ekspresi pada nilainya. Ada dua jenis komprehensi: komprehensi list dan komprehensi tabel. Keduanya menghasilkan tabel Lua; komprehensi list mengakumulasi nilai ke tabel mirip array, dan komprehensi tabel memungkinkan Anda menetapkan kunci dan nilai pada setiap iterasi. | ||
| 725 | |||
| 726 | ## Komprehensi List | ||
| 727 | |||
| 728 | Berikut membuat salinan tabel `items` tetapi semua nilainya digandakan. | ||
| 729 | |||
| 730 | ```yuescript | ||
| 731 | items = [ 1, 2, 3, 4 ] | ||
| 732 | doubled = [item * 2 for i, item in ipairs items] | ||
| 733 | ``` | ||
| 734 | |||
| 735 | <YueDisplay> | ||
| 736 | |||
| 737 | ```yue | ||
| 738 | items = [ 1, 2, 3, 4 ] | ||
| 739 | doubled = [item * 2 for i, item in ipairs items] | ||
| 740 | ``` | ||
| 741 | |||
| 742 | </YueDisplay> | ||
| 743 | |||
| 744 | Item yang disertakan dalam tabel baru bisa dibatasi dengan klausa `when`: | ||
| 745 | |||
| 746 | ```yuescript | ||
| 747 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 748 | ``` | ||
| 749 | |||
| 750 | <YueDisplay> | ||
| 751 | |||
| 752 | ```yue | ||
| 753 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 754 | ``` | ||
| 755 | |||
| 756 | </YueDisplay> | ||
| 757 | |||
| 758 | Karena umum untuk mengiterasi nilai dari tabel berindeks numerik, operator **\*** diperkenalkan. Contoh `doubled` bisa ditulis ulang sebagai: | ||
| 759 | |||
| 760 | ```yuescript | ||
| 761 | doubled = [item * 2 for item in *items] | ||
| 762 | ``` | ||
| 763 | |||
| 764 | <YueDisplay> | ||
| 765 | |||
| 766 | ```yue | ||
| 767 | doubled = [item * 2 for item in *items] | ||
| 768 | ``` | ||
| 769 | |||
| 770 | </YueDisplay> | ||
| 771 | |||
| 772 | Dalam komprehensi list, Anda juga bisa menggunakan operator spread `...` untuk meratakan list bertingkat, menghasilkan efek flat map: | ||
| 773 | |||
| 774 | ```yuescript | ||
| 775 | data = | ||
| 776 | a: [1, 2, 3] | ||
| 777 | b: [4, 5, 6] | ||
| 778 | |||
| 779 | flat = [...v for k,v in pairs data] | ||
| 780 | -- flat sekarang [1, 2, 3, 4, 5, 6] | ||
| 781 | ``` | ||
| 782 | |||
| 783 | <YueDisplay> | ||
| 784 | |||
| 785 | ```yue | ||
| 786 | data = | ||
| 787 | a: [1, 2, 3] | ||
| 788 | b: [4, 5, 6] | ||
| 789 | |||
| 790 | flat = [...v for k,v in pairs data] | ||
| 791 | -- flat sekarang [1, 2, 3, 4, 5, 6] | ||
| 792 | ``` | ||
| 793 | |||
| 794 | </YueDisplay> | ||
| 795 | |||
| 796 | Klausa `for` dan `when` dapat dirantai sebanyak yang diinginkan. Satu-satunya syarat adalah komprehensi memiliki setidaknya satu klausa `for`. | ||
| 797 | |||
| 798 | Menggunakan beberapa klausa `for` sama seperti menggunakan loop bertingkat: | ||
| 799 | |||
| 800 | ```yuescript | ||
| 801 | x_coords = [4, 5, 6, 7] | ||
| 802 | y_coords = [9, 2, 3] | ||
| 803 | |||
| 804 | points = [ [x, y] for x in *x_coords \ | ||
| 805 | for y in *y_coords] | ||
| 806 | ``` | ||
| 807 | |||
| 808 | <YueDisplay> | ||
| 809 | |||
| 810 | ```yue | ||
| 811 | x_coords = [4, 5, 6, 7] | ||
| 812 | y_coords = [9, 2, 3] | ||
| 813 | |||
| 814 | points = [ [x, y] for x in *x_coords \ | ||
| 815 | for y in *y_coords] | ||
| 816 | ``` | ||
| 817 | |||
| 818 | </YueDisplay> | ||
| 819 | |||
| 820 | Perulangan for numerik juga bisa digunakan dalam komprehensi: | ||
| 821 | |||
| 822 | ```yuescript | ||
| 823 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 824 | ``` | ||
| 825 | |||
| 826 | <YueDisplay> | ||
| 827 | |||
| 828 | ```yue | ||
| 829 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 830 | ``` | ||
| 831 | |||
| 832 | </YueDisplay> | ||
| 833 | |||
| 834 | ## Komprehensi Tabel | ||
| 835 | |||
| 836 | Sintaks untuk komprehensi tabel sangat mirip, hanya berbeda dengan penggunaan **{** dan **}** serta mengambil dua nilai dari setiap iterasi. | ||
| 837 | |||
| 838 | Contoh ini membuat salinan tabel `thing`: | ||
| 839 | |||
| 840 | ```yuescript | ||
| 841 | thing = { | ||
| 842 | color: "red" | ||
| 843 | name: "fast" | ||
| 844 | width: 123 | ||
| 845 | } | ||
| 846 | |||
| 847 | thing_copy = {k, v for k, v in pairs thing} | ||
| 848 | ``` | ||
| 849 | |||
| 850 | <YueDisplay> | ||
| 851 | |||
| 852 | ```yue | ||
| 853 | thing = { | ||
| 854 | color: "red" | ||
| 855 | name: "fast" | ||
| 856 | width: 123 | ||
| 857 | } | ||
| 858 | |||
| 859 | thing_copy = {k, v for k, v in pairs thing} | ||
| 860 | ``` | ||
| 861 | |||
| 862 | </YueDisplay> | ||
| 863 | |||
| 864 | ```yuescript | ||
| 865 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 866 | ``` | ||
| 867 | |||
| 868 | <YueDisplay> | ||
| 869 | |||
| 870 | ```yue | ||
| 871 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 872 | ``` | ||
| 873 | |||
| 874 | </YueDisplay> | ||
| 875 | |||
| 876 | Operator **\*** juga didukung. Di sini kita membuat tabel lookup akar kuadrat untuk beberapa angka. | ||
| 877 | |||
| 878 | ```yuescript | ||
| 879 | numbers = [1, 2, 3, 4] | ||
| 880 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 881 | ``` | ||
| 882 | |||
| 883 | <YueDisplay> | ||
| 884 | |||
| 885 | ```yue | ||
| 886 | numbers = [1, 2, 3, 4] | ||
| 887 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 888 | ``` | ||
| 889 | |||
| 890 | </YueDisplay> | ||
| 891 | |||
| 892 | Tuple key-value dalam komprehensi tabel juga bisa berasal dari satu ekspresi, yang berarti ekspresi tersebut harus mengembalikan dua nilai. Nilai pertama digunakan sebagai kunci dan nilai kedua digunakan sebagai nilai: | ||
| 893 | |||
| 894 | Dalam contoh ini kita mengonversi array pasangan menjadi tabel di mana item pertama dalam pasangan menjadi kunci dan item kedua menjadi nilai. | ||
| 895 | |||
| 896 | ```yuescript | ||
| 897 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 898 | tbl = {unpack tuple for tuple in *tuples} | ||
| 899 | ``` | ||
| 900 | |||
| 901 | <YueDisplay> | ||
| 902 | |||
| 903 | ```yue | ||
| 904 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 905 | tbl = {unpack tuple for tuple in *tuples} | ||
| 906 | ``` | ||
| 907 | |||
| 908 | </YueDisplay> | ||
| 909 | |||
| 910 | ## Slicing | ||
| 911 | |||
| 912 | Sintaks khusus disediakan untuk membatasi item yang diiterasi saat menggunakan operator **\***. Ini setara dengan mengatur batas iterasi dan ukuran langkah pada loop for. | ||
| 913 | |||
| 914 | Di sini kita bisa menetapkan batas minimum dan maksimum, mengambil semua item dengan indeks antara 1 dan 5 (inklusif): | ||
| 915 | |||
| 916 | ```yuescript | ||
| 917 | slice = [item for item in *items[1, 5]] | ||
| 918 | ``` | ||
| 919 | |||
| 920 | <YueDisplay> | ||
| 921 | |||
| 922 | ```yue | ||
| 923 | slice = [item for item in *items[1, 5]] | ||
| 924 | ``` | ||
| 925 | |||
| 926 | </YueDisplay> | ||
| 927 | |||
| 928 | Salah satu argumen slice boleh dikosongkan untuk menggunakan default yang masuk akal. Pada contoh ini, jika indeks maksimum dikosongkan, defaultnya adalah panjang tabel. Ini akan mengambil semua item kecuali elemen pertama: | ||
| 929 | |||
| 930 | ```yuescript | ||
| 931 | slice = [item for item in *items[2,]] | ||
| 932 | ``` | ||
| 933 | |||
| 934 | <YueDisplay> | ||
| 935 | |||
| 936 | ```yue | ||
| 937 | slice = [item for item in *items[2,]] | ||
| 938 | ``` | ||
| 939 | |||
| 940 | </YueDisplay> | ||
| 941 | |||
| 942 | Jika batas minimum dikosongkan, defaultnya adalah 1. Di sini kita hanya memberikan ukuran langkah dan membiarkan batas lainnya kosong. Ini akan mengambil semua item berindeks ganjil: (1, 3, 5, …) | ||
| 943 | |||
| 944 | ```yuescript | ||
| 945 | slice = [item for item in *items[,,2]] | ||
| 946 | ``` | ||
| 947 | |||
| 948 | <YueDisplay> | ||
| 949 | |||
| 950 | ```yue | ||
| 951 | slice = [item for item in *items[,,2]] | ||
| 952 | ``` | ||
| 953 | |||
| 954 | </YueDisplay> | ||
| 955 | |||
| 956 | Batas minimum dan maksimum bisa bernilai negatif, yang berarti batas dihitung dari akhir tabel. | ||
| 957 | |||
| 958 | ```yuescript | ||
| 959 | -- ambil 4 item terakhir | ||
| 960 | slice = [item for item in *items[-4,-1]] | ||
| 961 | ``` | ||
| 962 | |||
| 963 | <YueDisplay> | ||
| 964 | |||
| 965 | ```yue | ||
| 966 | -- ambil 4 item terakhir | ||
| 967 | slice = [item for item in *items[-4,-1]] | ||
| 968 | ``` | ||
| 969 | |||
| 970 | </YueDisplay> | ||
| 971 | |||
| 972 | Ukuran langkah juga bisa negatif, yang berarti item diambil dalam urutan terbalik. | ||
| 973 | |||
| 974 | ```yuescript | ||
| 975 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 976 | ``` | ||
| 977 | |||
| 978 | <YueDisplay> | ||
| 979 | |||
| 980 | ```yue | ||
| 981 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 982 | ``` | ||
| 983 | |||
| 984 | </YueDisplay> | ||
| 985 | |||
| 986 | ### Ekspresi Slicing | ||
| 987 | |||
| 988 | Slicing juga bisa digunakan sebagai ekspresi. Ini berguna untuk mendapatkan sub-list dari sebuah tabel. | ||
| 989 | |||
| 990 | ```yuescript | ||
| 991 | -- ambil item ke-2 dan ke-4 sebagai list baru | ||
| 992 | sub_list = items[2, 4] | ||
| 993 | |||
| 994 | -- ambil 4 item terakhir | ||
| 995 | last_four_items = items[-4, -1] | ||
| 996 | ``` | ||
| 997 | |||
| 998 | <YueDisplay> | ||
| 999 | |||
| 1000 | ```yue | ||
| 1001 | -- ambil item ke-2 dan ke-4 sebagai list baru | ||
| 1002 | sub_list = items[2, 4] | ||
| 1003 | |||
| 1004 | -- ambil 4 item terakhir | ||
| 1005 | last_four_items = items[-4, -1] | ||
| 1006 | ``` | ||
| 1007 | |||
| 1008 | </YueDisplay> | ||
| 1009 | |||
| 1010 | # Pemrograman Berorientasi Objek | ||
| 1011 | |||
| 1012 | Dalam contoh-contoh ini, kode Lua yang dihasilkan mungkin tampak berat. Sebaiknya fokus dulu pada makna kode YueScript, lalu lihat kode Lua jika Anda ingin mengetahui detail implementasinya. | ||
| 1013 | |||
| 1014 | Kelas sederhana: | ||
| 1015 | |||
| 1016 | ```yuescript | ||
| 1017 | class Inventory | ||
| 1018 | new: => | ||
| 1019 | @items = {} | ||
| 1020 | |||
| 1021 | add_item: (name) => | ||
| 1022 | if @items[name] | ||
| 1023 | @items[name] += 1 | ||
| 1024 | else | ||
| 1025 | @items[name] = 1 | ||
| 1026 | ``` | ||
| 1027 | |||
| 1028 | <YueDisplay> | ||
| 1029 | |||
| 1030 | ```yue | ||
| 1031 | class Inventory | ||
| 1032 | new: => | ||
| 1033 | @items = {} | ||
| 1034 | |||
| 1035 | add_item: (name) => | ||
| 1036 | if @items[name] | ||
| 1037 | @items[name] += 1 | ||
| 1038 | else | ||
| 1039 | @items[name] = 1 | ||
| 1040 | ``` | ||
| 1041 | |||
| 1042 | </YueDisplay> | ||
| 1043 | |||
| 1044 | Kelas dideklarasikan dengan pernyataan `class` diikuti deklarasi mirip tabel di mana semua method dan properti dicantumkan. | ||
| 1045 | |||
| 1046 | Properti `new` bersifat khusus karena akan menjadi konstruktor. | ||
| 1047 | |||
| 1048 | Perhatikan bahwa semua method di kelas menggunakan sintaks fungsi panah tebal. Saat memanggil method pada instance, instance itu sendiri dikirim sebagai argumen pertama. Panah tebal menangani pembuatan argumen `self`. | ||
| 1049 | |||
| 1050 | Prefiks `@` pada nama variabel adalah singkatan untuk `self.`. `@items` menjadi `self.items`. | ||
| 1051 | |||
| 1052 | Membuat instance kelas dilakukan dengan memanggil nama kelas sebagai fungsi. | ||
| 1053 | |||
| 1054 | ```yuescript | ||
| 1055 | inv = Inventory! | ||
| 1056 | inv\add_item "t-shirt" | ||
| 1057 | inv\add_item "pants" | ||
| 1058 | ``` | ||
| 1059 | |||
| 1060 | <YueDisplay> | ||
| 1061 | |||
| 1062 | ```yue | ||
| 1063 | inv = Inventory! | ||
| 1064 | inv\add_item "t-shirt" | ||
| 1065 | inv\add_item "pants" | ||
| 1066 | ``` | ||
| 1067 | |||
| 1068 | </YueDisplay> | ||
| 1069 | |||
| 1070 | Karena instance kelas perlu dikirim ke method saat dipanggil, operator `\` digunakan. | ||
| 1071 | |||
| 1072 | Semua properti kelas dibagikan di antara instance. Ini baik untuk fungsi, tetapi untuk jenis objek lain dapat menimbulkan hasil yang tidak diinginkan. | ||
| 1073 | |||
| 1074 | Pertimbangkan contoh di bawah ini, properti `clothes` dibagikan di antara semua instance, sehingga perubahan di satu instance akan terlihat di instance lainnya: | ||
| 1075 | |||
| 1076 | ```yuescript | ||
| 1077 | class Person | ||
| 1078 | clothes: [] | ||
| 1079 | give_item: (name) => | ||
| 1080 | table.insert @clothes, name | ||
| 1081 | |||
| 1082 | a = Person! | ||
| 1083 | b = Person! | ||
| 1084 | |||
| 1085 | a\give_item "pants" | ||
| 1086 | b\give_item "shirt" | ||
| 1087 | |||
| 1088 | -- akan mencetak pants dan shirt | ||
| 1089 | print item for item in *a.clothes | ||
| 1090 | ``` | ||
| 1091 | |||
| 1092 | <YueDisplay> | ||
| 1093 | |||
| 1094 | ```yue | ||
| 1095 | class Person | ||
| 1096 | clothes: [] | ||
| 1097 | give_item: (name) => | ||
| 1098 | table.insert @clothes, name | ||
| 1099 | |||
| 1100 | a = Person! | ||
| 1101 | b = Person! | ||
| 1102 | |||
| 1103 | a\give_item "pants" | ||
| 1104 | b\give_item "shirt" | ||
| 1105 | |||
| 1106 | -- akan mencetak pants dan shirt | ||
| 1107 | print item for item in *a.clothes | ||
| 1108 | ``` | ||
| 1109 | |||
| 1110 | </YueDisplay> | ||
| 1111 | |||
| 1112 | Cara yang benar untuk menghindari masalah ini adalah membuat state yang dapat berubah di konstruktor: | ||
| 1113 | |||
| 1114 | ```yuescript | ||
| 1115 | class Person | ||
| 1116 | new: => | ||
| 1117 | @clothes = [] | ||
| 1118 | ``` | ||
| 1119 | |||
| 1120 | <YueDisplay> | ||
| 1121 | |||
| 1122 | ```yue | ||
| 1123 | class Person | ||
| 1124 | new: => | ||
| 1125 | @clothes = [] | ||
| 1126 | ``` | ||
| 1127 | |||
| 1128 | </YueDisplay> | ||
| 1129 | |||
| 1130 | ## Pewarisan | ||
| 1131 | |||
| 1132 | Kata kunci `extends` dapat digunakan dalam deklarasi kelas untuk mewarisi properti dan method dari kelas lain. | ||
| 1133 | |||
| 1134 | ```yuescript | ||
| 1135 | class BackPack extends Inventory | ||
| 1136 | size: 10 | ||
| 1137 | add_item: (name) => | ||
| 1138 | if #@items > size then error "backpack is full" | ||
| 1139 | super name | ||
| 1140 | ``` | ||
| 1141 | |||
| 1142 | <YueDisplay> | ||
| 1143 | |||
| 1144 | ```yue | ||
| 1145 | class BackPack extends Inventory | ||
| 1146 | size: 10 | ||
| 1147 | add_item: (name) => | ||
| 1148 | if #@items > size then error "backpack is full" | ||
| 1149 | super name | ||
| 1150 | ``` | ||
| 1151 | |||
| 1152 | </YueDisplay> | ||
| 1153 | |||
| 1154 | Di sini kita memperluas kelas Inventory, dan membatasi jumlah item yang bisa dibawa. | ||
| 1155 | |||
| 1156 | Dalam contoh ini, kita tidak mendefinisikan konstruktor pada subclass, sehingga konstruktor kelas induk dipanggil ketika membuat instance baru. Jika kita mendefinisikan konstruktor, kita bisa menggunakan method `super` untuk memanggil konstruktor induk. | ||
| 1157 | |||
| 1158 | Setiap kali sebuah kelas mewarisi dari kelas lain, ia mengirim pesan ke kelas induk dengan memanggil method `__inherited` pada kelas induk jika ada. Fungsi menerima dua argumen, kelas yang diwarisi dan kelas anak. | ||
| 1159 | |||
| 1160 | ```yuescript | ||
| 1161 | class Shelf | ||
| 1162 | @__inherited: (child) => | ||
| 1163 | print @__name, "was inherited by", child.__name | ||
| 1164 | |||
| 1165 | -- akan mencetak: Shelf was inherited by Cupboard | ||
| 1166 | class Cupboard extends Shelf | ||
| 1167 | ``` | ||
| 1168 | |||
| 1169 | <YueDisplay> | ||
| 1170 | |||
| 1171 | ```yue | ||
| 1172 | class Shelf | ||
| 1173 | @__inherited: (child) => | ||
| 1174 | print @__name, "was inherited by", child.__name | ||
| 1175 | |||
| 1176 | -- akan mencetak: Shelf was inherited by Cupboard | ||
| 1177 | class Cupboard extends Shelf | ||
| 1178 | ``` | ||
| 1179 | |||
| 1180 | </YueDisplay> | ||
| 1181 | |||
| 1182 | ## Super | ||
| 1183 | |||
| 1184 | **super** adalah kata kunci khusus yang dapat digunakan dengan dua cara: sebagai objek, atau dipanggil seperti fungsi. Ia hanya memiliki fungsi khusus ketika berada di dalam kelas. | ||
| 1185 | |||
| 1186 | Ketika dipanggil sebagai fungsi, ia akan memanggil fungsi dengan nama yang sama di kelas induk. `self` saat ini akan otomatis dikirim sebagai argumen pertama. (Seperti pada contoh pewarisan di atas) | ||
| 1187 | |||
| 1188 | Ketika `super` digunakan sebagai nilai normal, ia merupakan referensi ke objek kelas induk. | ||
| 1189 | |||
| 1190 | Ia dapat diakses seperti objek biasa untuk mengambil nilai di kelas induk yang mungkin tertutup oleh kelas anak. | ||
| 1191 | |||
| 1192 | Ketika operator pemanggilan `\` digunakan dengan `super`, `self` disisipkan sebagai argumen pertama alih-alih nilai `super` itu sendiri. Saat menggunakan `.` untuk mengambil fungsi, fungsi mentah dikembalikan. | ||
| 1193 | |||
| 1194 | Beberapa contoh penggunaan `super` dengan cara berbeda: | ||
| 1195 | |||
| 1196 | ```yuescript | ||
| 1197 | class MyClass extends ParentClass | ||
| 1198 | a_method: => | ||
| 1199 | -- berikut memiliki efek yang sama: | ||
| 1200 | super "hello", "world" | ||
| 1201 | super\a_method "hello", "world" | ||
| 1202 | super.a_method self, "hello", "world" | ||
| 1203 | |||
| 1204 | -- super sebagai nilai sama dengan kelas induk: | ||
| 1205 | assert super == ParentClass | ||
| 1206 | ``` | ||
| 1207 | |||
| 1208 | <YueDisplay> | ||
| 1209 | |||
| 1210 | ```yue | ||
| 1211 | class MyClass extends ParentClass | ||
| 1212 | a_method: => | ||
| 1213 | -- berikut memiliki efek yang sama: | ||
| 1214 | super "hello", "world" | ||
| 1215 | super\a_method "hello", "world" | ||
| 1216 | super.a_method self, "hello", "world" | ||
| 1217 | |||
| 1218 | -- super sebagai nilai sama dengan kelas induk: | ||
| 1219 | assert super == ParentClass | ||
| 1220 | ``` | ||
| 1221 | |||
| 1222 | </YueDisplay> | ||
| 1223 | |||
| 1224 | **super** juga dapat digunakan di sisi kiri Function Stub. Perbedaan utamanya adalah, alih-alih fungsi hasil terikat pada nilai `super`, fungsi terikat pada `self`. | ||
| 1225 | |||
| 1226 | ## Tipe | ||
| 1227 | |||
| 1228 | Setiap instance kelas membawa tipenya sendiri. Ini disimpan di properti khusus `__class`. Properti ini memuat objek kelas. Objek kelas adalah yang kita panggil untuk membuat instance baru. Kita juga dapat mengindeks objek kelas untuk mengambil method dan properti kelas. | ||
| 1229 | |||
| 1230 | ```yuescript | ||
| 1231 | b = BackPack! | ||
| 1232 | assert b.__class == BackPack | ||
| 1233 | |||
| 1234 | print BackPack.size -- mencetak 10 | ||
| 1235 | ``` | ||
| 1236 | |||
| 1237 | <YueDisplay> | ||
| 1238 | |||
| 1239 | ```yue | ||
| 1240 | b = BackPack! | ||
| 1241 | assert b.__class == BackPack | ||
| 1242 | |||
| 1243 | print BackPack.size -- mencetak 10 | ||
| 1244 | ``` | ||
| 1245 | |||
| 1246 | </YueDisplay> | ||
| 1247 | |||
| 1248 | ## Objek Kelas | ||
| 1249 | |||
| 1250 | Objek kelas adalah yang kita buat saat menggunakan pernyataan `class`. Objek kelas disimpan dalam variabel dengan nama yang sama dengan kelas. | ||
| 1251 | |||
| 1252 | Objek kelas dapat dipanggil seperti fungsi untuk membuat instance baru. Begitulah cara kita membuat instance kelas pada contoh di atas. | ||
| 1253 | |||
| 1254 | Sebuah kelas terdiri dari dua tabel: tabel kelas itu sendiri dan tabel base. Base digunakan sebagai metatable untuk semua instance. Semua properti yang dicantumkan dalam deklarasi kelas ditempatkan di base. | ||
| 1255 | |||
| 1256 | Metatable objek kelas membaca properti dari base jika tidak ada di objek kelas. Ini berarti kita dapat mengakses fungsi dan properti langsung dari kelas. | ||
| 1257 | |||
| 1258 | Penting untuk dicatat bahwa assignment ke objek kelas tidak meng-assign ke base, sehingga itu bukan cara yang valid untuk menambahkan method baru ke instance. Sebagai gantinya, base harus diubah secara eksplisit. Lihat field `__base` di bawah. | ||
| 1259 | |||
| 1260 | Objek kelas memiliki beberapa properti khusus: | ||
| 1261 | |||
| 1262 | Nama kelas saat dideklarasikan disimpan sebagai string di field `__name` pada objek kelas. | ||
| 1263 | |||
| 1264 | ```yuescript | ||
| 1265 | print BackPack.__name -- mencetak Backpack | ||
| 1266 | ``` | ||
| 1267 | |||
| 1268 | <YueDisplay> | ||
| 1269 | |||
| 1270 | ```yue | ||
| 1271 | print BackPack.__name -- mencetak Backpack | ||
| 1272 | ``` | ||
| 1273 | |||
| 1274 | </YueDisplay> | ||
| 1275 | |||
| 1276 | Objek base disimpan di `__base`. Kita dapat memodifikasi tabel ini untuk menambahkan fungsionalitas ke instance yang sudah dibuat maupun yang akan dibuat. | ||
| 1277 | |||
| 1278 | Jika kelas memperluas kelas lain, objek kelas induk disimpan di `__parent`. | ||
| 1279 | |||
| 1280 | ## Variabel Kelas | ||
| 1281 | |||
| 1282 | Kita dapat membuat variabel langsung di objek kelas alih-alih di base dengan menggunakan `@` di depan nama properti pada deklarasi kelas. | ||
| 1283 | |||
| 1284 | ```yuescript | ||
| 1285 | class Things | ||
| 1286 | @some_func: => print "Hello from", @__name | ||
| 1287 | |||
| 1288 | Things\some_func! | ||
| 1289 | |||
| 1290 | -- variabel kelas tidak terlihat pada instance | ||
| 1291 | assert Things().some_func == nil | ||
| 1292 | ``` | ||
| 1293 | |||
| 1294 | <YueDisplay> | ||
| 1295 | |||
| 1296 | ```yue | ||
| 1297 | class Things | ||
| 1298 | @some_func: => print "Hello from", @__name | ||
| 1299 | |||
| 1300 | Things\some_func! | ||
| 1301 | |||
| 1302 | -- variabel kelas tidak terlihat pada instance | ||
| 1303 | assert Things().some_func == nil | ||
| 1304 | ``` | ||
| 1305 | |||
| 1306 | </YueDisplay> | ||
| 1307 | |||
| 1308 | Dalam ekspresi, kita dapat menggunakan `@@` untuk mengakses nilai yang disimpan di `__class` milik `self`. Jadi, `@@hello` adalah singkatan dari `self.__class.hello`. | ||
| 1309 | |||
| 1310 | ```yuescript | ||
| 1311 | class Counter | ||
| 1312 | @count: 0 | ||
| 1313 | |||
| 1314 | new: => | ||
| 1315 | @@count += 1 | ||
| 1316 | |||
| 1317 | Counter! | ||
| 1318 | Counter! | ||
| 1319 | |||
| 1320 | print Counter.count -- mencetak 2 | ||
| 1321 | ``` | ||
| 1322 | |||
| 1323 | <YueDisplay> | ||
| 1324 | |||
| 1325 | ```yue | ||
| 1326 | class Counter | ||
| 1327 | @count: 0 | ||
| 1328 | |||
| 1329 | new: => | ||
| 1330 | @@count += 1 | ||
| 1331 | |||
| 1332 | Counter! | ||
| 1333 | Counter! | ||
| 1334 | |||
| 1335 | print Counter.count -- mencetak 2 | ||
| 1336 | ``` | ||
| 1337 | |||
| 1338 | </YueDisplay> | ||
| 1339 | |||
| 1340 | Semantik pemanggilan `@@` mirip dengan `@`. Memanggil nama `@@` akan meneruskan kelas sebagai argumen pertama menggunakan sintaks kolon Lua. | ||
| 1341 | |||
| 1342 | ```yuescript | ||
| 1343 | @@hello 1,2,3,4 | ||
| 1344 | ``` | ||
| 1345 | |||
| 1346 | <YueDisplay> | ||
| 1347 | |||
| 1348 | ```yue | ||
| 1349 | @@hello 1,2,3,4 | ||
| 1350 | ``` | ||
| 1351 | |||
| 1352 | </YueDisplay> | ||
| 1353 | |||
| 1354 | ## Pernyataan Deklarasi Kelas | ||
| 1355 | |||
| 1356 | Di dalam badan deklarasi kelas, kita bisa memiliki ekspresi normal selain pasangan key/value. Dalam konteks ini, `self` sama dengan objek kelas. | ||
| 1357 | |||
| 1358 | Berikut cara alternatif untuk membuat variabel kelas dibandingkan yang dijelaskan di atas: | ||
| 1359 | |||
| 1360 | ```yuescript | ||
| 1361 | class Things | ||
| 1362 | @class_var = "hello world" | ||
| 1363 | ``` | ||
| 1364 | |||
| 1365 | <YueDisplay> | ||
| 1366 | |||
| 1367 | ```yue | ||
| 1368 | class Things | ||
| 1369 | @class_var = "hello world" | ||
| 1370 | ``` | ||
| 1371 | |||
| 1372 | </YueDisplay> | ||
| 1373 | |||
| 1374 | Ekspresi ini dieksekusi setelah semua properti ditambahkan ke base. | ||
| 1375 | |||
| 1376 | Semua variabel yang dideklarasikan di badan kelas bersifat lokal terhadap properti kelas. Ini berguna untuk menempatkan nilai privat atau fungsi pembantu yang hanya dapat diakses oleh method kelas: | ||
| 1377 | |||
| 1378 | ```yuescript | ||
| 1379 | class MoreThings | ||
| 1380 | secret = 123 | ||
| 1381 | log = (msg) -> print "LOG:", msg | ||
| 1382 | |||
| 1383 | some_method: => | ||
| 1384 | log "hello world: " .. secret | ||
| 1385 | ``` | ||
| 1386 | |||
| 1387 | <YueDisplay> | ||
| 1388 | |||
| 1389 | ```yue | ||
| 1390 | class MoreThings | ||
| 1391 | secret = 123 | ||
| 1392 | log = (msg) -> print "LOG:", msg | ||
| 1393 | |||
| 1394 | some_method: => | ||
| 1395 | log "hello world: " .. secret | ||
| 1396 | ``` | ||
| 1397 | |||
| 1398 | </YueDisplay> | ||
| 1399 | |||
| 1400 | ## Nilai @ dan @@ | ||
| 1401 | |||
| 1402 | Ketika `@` dan `@@` diprefiks di depan sebuah nama, masing-masing merepresentasikan nama tersebut yang diakses di `self` dan `self.__class`. | ||
| 1403 | |||
| 1404 | Jika digunakan sendirian, keduanya adalah alias untuk `self` dan `self.__class`. | ||
| 1405 | |||
| 1406 | ```yuescript | ||
| 1407 | assert @ == self | ||
| 1408 | assert @@ == self.__class | ||
| 1409 | ``` | ||
| 1410 | |||
| 1411 | <YueDisplay> | ||
| 1412 | |||
| 1413 | ```yue | ||
| 1414 | assert @ == self | ||
| 1415 | assert @@ == self.__class | ||
| 1416 | ``` | ||
| 1417 | |||
| 1418 | </YueDisplay> | ||
| 1419 | |||
| 1420 | Contohnya, cara cepat untuk membuat instance baru dari kelas yang sama dari method instance menggunakan `@@`: | ||
| 1421 | |||
| 1422 | ```yuescript | ||
| 1423 | some_instance_method = (...) => @@ ... | ||
| 1424 | ``` | ||
| 1425 | |||
| 1426 | <YueDisplay> | ||
| 1427 | |||
| 1428 | ```yue | ||
| 1429 | some_instance_method = (...) => @@ ... | ||
| 1430 | ``` | ||
| 1431 | |||
| 1432 | </YueDisplay> | ||
| 1433 | |||
| 1434 | ## Promosi Properti Konstruktor | ||
| 1435 | |||
| 1436 | Untuk mengurangi boilerplate saat mendefinisikan objek nilai sederhana, Anda dapat menulis kelas sederhana seperti: | ||
| 1437 | |||
| 1438 | ```yuescript | ||
| 1439 | class Something | ||
| 1440 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1441 | |||
| 1442 | -- Yang merupakan singkatan dari | ||
| 1443 | |||
| 1444 | class Something | ||
| 1445 | new: (foo, bar, biz, baz) => | ||
| 1446 | @foo = foo | ||
| 1447 | @bar = bar | ||
| 1448 | @@biz = biz | ||
| 1449 | @@baz = baz | ||
| 1450 | ``` | ||
| 1451 | |||
| 1452 | <YueDisplay> | ||
| 1453 | |||
| 1454 | ```yue | ||
| 1455 | class Something | ||
| 1456 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1457 | |||
| 1458 | -- Yang merupakan singkatan dari | ||
| 1459 | |||
| 1460 | class Something | ||
| 1461 | new: (foo, bar, biz, baz) => | ||
| 1462 | @foo = foo | ||
| 1463 | @bar = bar | ||
| 1464 | @@biz = biz | ||
| 1465 | @@baz = baz | ||
| 1466 | ``` | ||
| 1467 | |||
| 1468 | </YueDisplay> | ||
| 1469 | |||
| 1470 | Anda juga bisa menggunakan sintaks ini untuk fungsi umum guna menginisialisasi field objek. | ||
| 1471 | |||
| 1472 | ```yuescript | ||
| 1473 | new = (@fieldA, @fieldB) => @ | ||
| 1474 | obj = new {}, 123, "abc" | ||
| 1475 | print obj | ||
| 1476 | ``` | ||
| 1477 | |||
| 1478 | <YueDisplay> | ||
| 1479 | |||
| 1480 | ```yue | ||
| 1481 | new = (@fieldA, @fieldB) => @ | ||
| 1482 | obj = new {}, 123, "abc" | ||
| 1483 | print obj | ||
| 1484 | ``` | ||
| 1485 | |||
| 1486 | </YueDisplay> | ||
| 1487 | |||
| 1488 | ## Ekspresi Kelas | ||
| 1489 | |||
| 1490 | Sintaks kelas juga bisa digunakan sebagai ekspresi yang dapat di-assign ke variabel atau di-return secara eksplisit. | ||
| 1491 | |||
| 1492 | ```yuescript | ||
| 1493 | x = class Bucket | ||
| 1494 | drops: 0 | ||
| 1495 | add_drop: => @drops += 1 | ||
| 1496 | ``` | ||
| 1497 | |||
| 1498 | <YueDisplay> | ||
| 1499 | |||
| 1500 | ```yue | ||
| 1501 | x = class Bucket | ||
| 1502 | drops: 0 | ||
| 1503 | add_drop: => @drops += 1 | ||
| 1504 | ``` | ||
| 1505 | |||
| 1506 | </YueDisplay> | ||
| 1507 | |||
| 1508 | ## Kelas Anonim | ||
| 1509 | |||
| 1510 | Nama bisa dihilangkan saat mendeklarasikan kelas. Atribut `__name` akan bernilai nil, kecuali ekspresi kelas berada dalam assignment. Nama di sisi kiri assignment digunakan sebagai ganti nil. | ||
| 1511 | |||
| 1512 | ```yuescript | ||
| 1513 | BigBucket = class extends Bucket | ||
| 1514 | add_drop: => @drops += 10 | ||
| 1515 | |||
| 1516 | assert Bucket.__name == "BigBucket" | ||
| 1517 | ``` | ||
| 1518 | |||
| 1519 | <YueDisplay> | ||
| 1520 | |||
| 1521 | ```yue | ||
| 1522 | BigBucket = class extends Bucket | ||
| 1523 | add_drop: => @drops += 10 | ||
| 1524 | |||
| 1525 | assert Bucket.__name == "BigBucket" | ||
| 1526 | ``` | ||
| 1527 | |||
| 1528 | </YueDisplay> | ||
| 1529 | |||
| 1530 | Anda bahkan bisa menghilangkan badan kelas, artinya Anda bisa menulis kelas anonim kosong seperti ini: | ||
| 1531 | |||
| 1532 | ```yuescript | ||
| 1533 | x = class | ||
| 1534 | ``` | ||
| 1535 | |||
| 1536 | <YueDisplay> | ||
| 1537 | |||
| 1538 | ```yue | ||
| 1539 | x = class | ||
| 1540 | ``` | ||
| 1541 | |||
| 1542 | </YueDisplay> | ||
| 1543 | |||
| 1544 | ## Pencampuran Kelas | ||
| 1545 | |||
| 1546 | Anda bisa melakukan mixing dengan kata kunci `using` untuk menyalin fungsi dari tabel biasa atau objek kelas yang sudah didefinisikan ke kelas baru Anda. Saat mixing dengan tabel biasa, Anda dapat mengganti fungsi pengindeksan kelas (metamethod `__index`) dengan implementasi kustom. Saat mixing dengan objek kelas yang sudah ada, metamethod objek kelas tidak akan disalin. | ||
| 1547 | |||
| 1548 | ```yuescript | ||
| 1549 | MyIndex = __index: var: 1 | ||
| 1550 | |||
| 1551 | class X using MyIndex | ||
| 1552 | func: => | ||
| 1553 | print 123 | ||
| 1554 | |||
| 1555 | x = X! | ||
| 1556 | print x.var | ||
| 1557 | |||
| 1558 | class Y using X | ||
| 1559 | |||
| 1560 | y = Y! | ||
| 1561 | y\func! | ||
| 1562 | |||
| 1563 | assert y.__class.__parent ~= X -- X bukan parent dari Y | ||
| 1564 | ``` | ||
| 1565 | |||
| 1566 | <YueDisplay> | ||
| 1567 | |||
| 1568 | ```yue | ||
| 1569 | MyIndex = __index: var: 1 | ||
| 1570 | |||
| 1571 | class X using MyIndex | ||
| 1572 | func: => | ||
| 1573 | print 123 | ||
| 1574 | |||
| 1575 | x = X! | ||
| 1576 | print x.var | ||
| 1577 | |||
| 1578 | class Y using X | ||
| 1579 | |||
| 1580 | y = Y! | ||
| 1581 | y\func! | ||
| 1582 | |||
| 1583 | assert y.__class.__parent ~= X -- X bukan parent dari Y | ||
| 1584 | ``` | ||
| 1585 | |||
| 1586 | </YueDisplay> | ||
| 1587 | |||
| 1588 | # Pernyataan With | ||
| 1589 | |||
| 1590 | Pola umum saat membuat objek adalah memanggil serangkaian fungsi dan mengatur serangkaian properti segera setelah objek dibuat. | ||
| 1591 | |||
| 1592 | Hal ini menyebabkan nama objek diulang berkali-kali di kode, menambah noise yang tidak perlu. Solusi umum untuk ini adalah meneruskan tabel sebagai argumen yang berisi kumpulan kunci dan nilai untuk ditimpa. Kekurangannya adalah konstruktor objek harus mendukung bentuk ini. | ||
| 1593 | |||
| 1594 | Blok `with` membantu mengatasi hal ini. Di dalam blok `with`, kita bisa menggunakan pernyataan khusus yang diawali dengan `.` atau `\` yang merepresentasikan operasi tersebut diterapkan pada objek yang sedang dipakai. | ||
| 1595 | |||
| 1596 | Sebagai contoh, kita bekerja dengan objek yang baru dibuat: | ||
| 1597 | |||
| 1598 | ```yuescript | ||
| 1599 | with Person! | ||
| 1600 | .name = "Oswald" | ||
| 1601 | \add_relative my_dad | ||
| 1602 | \save! | ||
| 1603 | print .name | ||
| 1604 | ``` | ||
| 1605 | |||
| 1606 | <YueDisplay> | ||
| 1607 | |||
| 1608 | ```yue | ||
| 1609 | with Person! | ||
| 1610 | .name = "Oswald" | ||
| 1611 | \add_relative my_dad | ||
| 1612 | \save! | ||
| 1613 | print .name | ||
| 1614 | ``` | ||
| 1615 | |||
| 1616 | </YueDisplay> | ||
| 1617 | |||
| 1618 | Pernyataan `with` juga bisa digunakan sebagai ekspresi yang mengembalikan nilai yang diberi akses. | ||
| 1619 | |||
| 1620 | ```yuescript | ||
| 1621 | file = with File "favorite_foods.txt" | ||
| 1622 | \set_encoding "utf8" | ||
| 1623 | ``` | ||
| 1624 | |||
| 1625 | <YueDisplay> | ||
| 1626 | |||
| 1627 | ```yue | ||
| 1628 | file = with File "favorite_foods.txt" | ||
| 1629 | \set_encoding "utf8" | ||
| 1630 | ``` | ||
| 1631 | |||
| 1632 | </YueDisplay> | ||
| 1633 | |||
| 1634 | Ekspresi `with` mendukung `break` dengan satu nilai: | ||
| 1635 | |||
| 1636 | ```yuescript | ||
| 1637 | result = with obj | ||
| 1638 | break .value | ||
| 1639 | ``` | ||
| 1640 | |||
| 1641 | <YueDisplay> | ||
| 1642 | |||
| 1643 | ```yue | ||
| 1644 | result = with obj | ||
| 1645 | break .value | ||
| 1646 | ``` | ||
| 1647 | |||
| 1648 | </YueDisplay> | ||
| 1649 | |||
| 1650 | Setelah `break value` digunakan di dalam `with`, ekspresi `with` tidak lagi mengembalikan objek targetnya, melainkan mengembalikan nilai dari `break`. | ||
| 1651 | |||
| 1652 | ```yuescript | ||
| 1653 | a = with obj | ||
| 1654 | .x = 1 | ||
| 1655 | -- a adalah obj | ||
| 1656 | |||
| 1657 | b = with obj | ||
| 1658 | break .x | ||
| 1659 | -- b adalah .x, bukan obj | ||
| 1660 | ``` | ||
| 1661 | |||
| 1662 | <YueDisplay> | ||
| 1663 | |||
| 1664 | ```yue | ||
| 1665 | a = with obj | ||
| 1666 | .x = 1 | ||
| 1667 | -- a adalah obj | ||
| 1668 | |||
| 1669 | b = with obj | ||
| 1670 | break .x | ||
| 1671 | -- b adalah .x, bukan obj | ||
| 1672 | ``` | ||
| 1673 | |||
| 1674 | </YueDisplay> | ||
| 1675 | |||
| 1676 | Berbeda dari `for` / `while` / `repeat` / `do`, `with` hanya mendukung satu nilai `break`. | ||
| 1677 | |||
| 1678 | Atau… | ||
| 1679 | |||
| 1680 | ```yuescript | ||
| 1681 | create_person = (name, relatives) -> | ||
| 1682 | with Person! | ||
| 1683 | .name = name | ||
| 1684 | \add_relative relative for relative in *relatives | ||
| 1685 | |||
| 1686 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1687 | ``` | ||
| 1688 | |||
| 1689 | <YueDisplay> | ||
| 1690 | |||
| 1691 | ```yue | ||
| 1692 | create_person = (name, relatives) -> | ||
| 1693 | with Person! | ||
| 1694 | .name = name | ||
| 1695 | \add_relative relative for relative in *relatives | ||
| 1696 | |||
| 1697 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1698 | ``` | ||
| 1699 | |||
| 1700 | </YueDisplay> | ||
| 1701 | |||
| 1702 | Dalam penggunaan ini, `with` dapat dilihat sebagai bentuk khusus dari kombinator K. | ||
| 1703 | |||
| 1704 | Ekspresi pada pernyataan `with` juga bisa berupa assignment jika Anda ingin memberi nama pada ekspresi tersebut. | ||
| 1705 | |||
| 1706 | ```yuescript | ||
| 1707 | with str := "Hello" | ||
| 1708 | print "original:", str | ||
| 1709 | print "upper:", \upper! | ||
| 1710 | ``` | ||
| 1711 | |||
| 1712 | <YueDisplay> | ||
| 1713 | |||
| 1714 | ```yue | ||
| 1715 | with str := "Hello" | ||
| 1716 | print "original:", str | ||
| 1717 | print "upper:", \upper! | ||
| 1718 | ``` | ||
| 1719 | |||
| 1720 | </YueDisplay> | ||
| 1721 | |||
| 1722 | Anda bisa mengakses kunci khusus dengan `[]` di dalam pernyataan `with`. | ||
| 1723 | |||
| 1724 | ```yuescript | ||
| 1725 | with tb | ||
| 1726 | [1] = 1 | ||
| 1727 | print [2] | ||
| 1728 | with [abc] | ||
| 1729 | [3] = [2]\func! | ||
| 1730 | ["key-name"] = value | ||
| 1731 | [] = "abc" -- menambahkan ke "tb" | ||
| 1732 | ``` | ||
| 1733 | |||
| 1734 | <YueDisplay> | ||
| 1735 | |||
| 1736 | ```yue | ||
| 1737 | with tb | ||
| 1738 | [1] = 1 | ||
| 1739 | print [2] | ||
| 1740 | with [abc] | ||
| 1741 | [3] = [2]\func! | ||
| 1742 | ["key-name"] = value | ||
| 1743 | [] = "abc" -- menambahkan ke "tb" | ||
| 1744 | ``` | ||
| 1745 | |||
| 1746 | </YueDisplay> | ||
| 1747 | |||
| 1748 | `with?` adalah versi yang ditingkatkan dari sintaks `with`, yang memperkenalkan pengecekan keberadaan untuk mengakses objek yang mungkin nil secara aman tanpa pemeriksaan null eksplisit. | ||
| 1749 | |||
| 1750 | ```yuescript | ||
| 1751 | with? obj | ||
| 1752 | print obj.name | ||
| 1753 | ``` | ||
| 1754 | |||
| 1755 | <YueDisplay> | ||
| 1756 | |||
| 1757 | ```yue | ||
| 1758 | with? obj | ||
| 1759 | print obj.name | ||
| 1760 | ``` | ||
| 1761 | |||
| 1762 | </YueDisplay> | ||
| 1763 | |||
| 1764 | # Penugasan | ||
| 1765 | |||
| 1766 | Variabel bersifat bertipe dinamis dan secara default dideklarasikan sebagai local. Namun Anda dapat mengubah cakupan deklarasi dengan pernyataan **local** dan **global**. | ||
| 1767 | |||
| 1768 | ```yuescript | ||
| 1769 | hello = "world" | ||
| 1770 | a, b, c = 1, 2, 3 | ||
| 1771 | hello = 123 -- menggunakan variabel yang sudah ada | ||
| 1772 | ``` | ||
| 1773 | |||
| 1774 | <YueDisplay> | ||
| 1775 | |||
| 1776 | ```yue | ||
| 1777 | hello = "world" | ||
| 1778 | a, b, c = 1, 2, 3 | ||
| 1779 | hello = 123 -- menggunakan variabel yang sudah ada | ||
| 1780 | ``` | ||
| 1781 | |||
| 1782 | </YueDisplay> | ||
| 1783 | |||
| 1784 | ## Pembaruan Nilai | ||
| 1785 | |||
| 1786 | Anda dapat melakukan assignment pembaruan dengan banyak operator biner. | ||
| 1787 | |||
| 1788 | ```yuescript | ||
| 1789 | x = 1 | ||
| 1790 | x += 1 | ||
| 1791 | x -= 1 | ||
| 1792 | x *= 10 | ||
| 1793 | x /= 10 | ||
| 1794 | x %= 10 | ||
| 1795 | s ..= "world" -- akan menambah local baru jika variabel local belum ada | ||
| 1796 | arg or= "default value" | ||
| 1797 | ``` | ||
| 1798 | |||
| 1799 | <YueDisplay> | ||
| 1800 | |||
| 1801 | ```yue | ||
| 1802 | x = 1 | ||
| 1803 | x += 1 | ||
| 1804 | x -= 1 | ||
| 1805 | x *= 10 | ||
| 1806 | x /= 10 | ||
| 1807 | x %= 10 | ||
| 1808 | s ..= "world" -- akan menambah local baru jika variabel local belum ada | ||
| 1809 | arg or= "default value" | ||
| 1810 | ``` | ||
| 1811 | |||
| 1812 | </YueDisplay> | ||
| 1813 | |||
| 1814 | ## Assignment Berantai | ||
| 1815 | |||
| 1816 | Anda bisa melakukan assignment berantai untuk menetapkan beberapa item ke nilai yang sama. | ||
| 1817 | |||
| 1818 | ```yuescript | ||
| 1819 | a = b = c = d = e = 0 | ||
| 1820 | x = y = z = f! | ||
| 1821 | ``` | ||
| 1822 | |||
| 1823 | <YueDisplay> | ||
| 1824 | |||
| 1825 | ```yue | ||
| 1826 | a = b = c = d = e = 0 | ||
| 1827 | x = y = z = f! | ||
| 1828 | ``` | ||
| 1829 | |||
| 1830 | </YueDisplay> | ||
| 1831 | |||
| 1832 | ## Local Eksplisit | ||
| 1833 | |||
| 1834 | ```yuescript | ||
| 1835 | do | ||
| 1836 | local a = 1 | ||
| 1837 | local * | ||
| 1838 | print "deklarasikan semua variabel sebagai local di awal" | ||
| 1839 | x = -> 1 + y + z | ||
| 1840 | y, z = 2, 3 | ||
| 1841 | global instance = Item\new! | ||
| 1842 | |||
| 1843 | do | ||
| 1844 | local X = 1 | ||
| 1845 | local ^ | ||
| 1846 | print "hanya deklarasikan variabel huruf besar sebagai local di awal" | ||
| 1847 | a = 1 | ||
| 1848 | B = 2 | ||
| 1849 | ``` | ||
| 1850 | |||
| 1851 | <YueDisplay> | ||
| 1852 | |||
| 1853 | ```yue | ||
| 1854 | do | ||
| 1855 | local a = 1 | ||
| 1856 | local * | ||
| 1857 | print "deklarasikan semua variabel sebagai local di awal" | ||
| 1858 | x = -> 1 + y + z | ||
| 1859 | y, z = 2, 3 | ||
| 1860 | global instance = Item\new! | ||
| 1861 | |||
| 1862 | do | ||
| 1863 | local X = 1 | ||
| 1864 | local ^ | ||
| 1865 | print "hanya deklarasikan variabel huruf besar sebagai local di awal" | ||
| 1866 | a = 1 | ||
| 1867 | B = 2 | ||
| 1868 | ``` | ||
| 1869 | |||
| 1870 | </YueDisplay> | ||
| 1871 | |||
| 1872 | ## Global Eksplisit | ||
| 1873 | |||
| 1874 | ```yuescript | ||
| 1875 | do | ||
| 1876 | global a = 1 | ||
| 1877 | global * | ||
| 1878 | print "deklarasikan semua variabel sebagai global" | ||
| 1879 | x = -> 1 + y + z | ||
| 1880 | y, z = 2, 3 | ||
| 1881 | |||
| 1882 | do | ||
| 1883 | global X = 1 | ||
| 1884 | global ^ | ||
| 1885 | print "hanya deklarasikan variabel huruf besar sebagai global" | ||
| 1886 | a = 1 | ||
| 1887 | B = 2 | ||
| 1888 | local Temp = "a local value" | ||
| 1889 | ``` | ||
| 1890 | |||
| 1891 | <YueDisplay> | ||
| 1892 | |||
| 1893 | ```yue | ||
| 1894 | do | ||
| 1895 | global a = 1 | ||
| 1896 | global * | ||
| 1897 | print "deklarasikan semua variabel sebagai global" | ||
| 1898 | x = -> 1 + y + z | ||
| 1899 | y, z = 2, 3 | ||
| 1900 | |||
| 1901 | do | ||
| 1902 | global X = 1 | ||
| 1903 | global ^ | ||
| 1904 | print "hanya deklarasikan variabel huruf besar sebagai global" | ||
| 1905 | a = 1 | ||
| 1906 | B = 2 | ||
| 1907 | local Temp = "a local value" | ||
| 1908 | ``` | ||
| 1909 | |||
| 1910 | </YueDisplay> | ||
| 1911 | |||
| 1912 | # Penugasan Varargs | ||
| 1913 | |||
| 1914 | Anda dapat meng-assign hasil yang dikembalikan dari sebuah fungsi ke simbol varargs `...`. Lalu akses isinya menggunakan cara Lua. | ||
| 1915 | |||
| 1916 | ```yuescript | ||
| 1917 | list = [1, 2, 3, 4, 5] | ||
| 1918 | fn = (ok) -> ok, table.unpack list | ||
| 1919 | ok, ... = fn true | ||
| 1920 | count = select '#', ... | ||
| 1921 | first = select 1, ... | ||
| 1922 | print ok, count, first | ||
| 1923 | ``` | ||
| 1924 | |||
| 1925 | <YueDisplay> | ||
| 1926 | |||
| 1927 | ```yue | ||
| 1928 | list = [1, 2, 3, 4, 5] | ||
| 1929 | fn = (ok) -> ok, table.unpack list | ||
| 1930 | ok, ... = fn true | ||
| 1931 | count = select '#', ... | ||
| 1932 | first = select 1, ... | ||
| 1933 | print ok, count, first | ||
| 1934 | ``` | ||
| 1935 | |||
| 1936 | </YueDisplay> | ||
| 1937 | |||
| 1938 | # Penugasan pada If | ||
| 1939 | |||
| 1940 | Blok `if` dan `elseif` dapat menerima assignment sebagai ganti ekspresi kondisional. Saat kondisi dievaluasi, assignment akan dilakukan dan nilai yang di-assign akan digunakan sebagai ekspresi kondisional. Variabel yang di-assign hanya berada dalam scope badan kondisional, artinya tidak pernah tersedia jika nilai tidak truthy. Dan Anda harus menggunakan "walrus operator" `:=` sebagai ganti `=` untuk melakukan assignment. | ||
| 1941 | |||
| 1942 | ```yuescript | ||
| 1943 | if user := database.find_user "moon" | ||
| 1944 | print user.name | ||
| 1945 | ``` | ||
| 1946 | |||
| 1947 | <YueDisplay> | ||
| 1948 | |||
| 1949 | ```yue | ||
| 1950 | if user := database.find_user "moon" | ||
| 1951 | print user.name | ||
| 1952 | ``` | ||
| 1953 | |||
| 1954 | </YueDisplay> | ||
| 1955 | |||
| 1956 | ```yuescript | ||
| 1957 | if hello := os.getenv "hello" | ||
| 1958 | print "You have hello", hello | ||
| 1959 | elseif world := os.getenv "world" | ||
| 1960 | print "you have world", world | ||
| 1961 | else | ||
| 1962 | print "nothing :(" | ||
| 1963 | ``` | ||
| 1964 | |||
| 1965 | <YueDisplay> | ||
| 1966 | |||
| 1967 | ```yue | ||
| 1968 | if hello := os.getenv "hello" | ||
| 1969 | print "You have hello", hello | ||
| 1970 | elseif world := os.getenv "world" | ||
| 1971 | print "you have world", world | ||
| 1972 | else | ||
| 1973 | print "nothing :(" | ||
| 1974 | ``` | ||
| 1975 | |||
| 1976 | </YueDisplay> | ||
| 1977 | |||
| 1978 | Assignment if dengan beberapa nilai return. Hanya nilai pertama yang dicek, nilai lainnya tetap berada dalam scope. | ||
| 1979 | |||
| 1980 | ```yuescript | ||
| 1981 | if success, result := pcall -> "get result without problems" | ||
| 1982 | print result -- variabel result berada dalam scope | ||
| 1983 | print "OK" | ||
| 1984 | ``` | ||
| 1985 | |||
| 1986 | <YueDisplay> | ||
| 1987 | |||
| 1988 | ```yue | ||
| 1989 | if success, result := pcall -> "get result without problems" | ||
| 1990 | print result -- variabel result berada dalam scope | ||
| 1991 | print "OK" | ||
| 1992 | ``` | ||
| 1993 | |||
| 1994 | </YueDisplay> | ||
| 1995 | |||
| 1996 | ## Assignment pada While | ||
| 1997 | |||
| 1998 | Anda juga bisa menggunakan assignment if di loop while untuk mendapatkan nilai sebagai kondisi loop. | ||
| 1999 | |||
| 2000 | ```yuescript | ||
| 2001 | while byte := stream\read_one! | ||
| 2002 | -- lakukan sesuatu dengan byte | ||
| 2003 | print byte | ||
| 2004 | ``` | ||
| 2005 | |||
| 2006 | <YueDisplay> | ||
| 2007 | |||
| 2008 | ```yue | ||
| 2009 | while byte := stream\read_one! | ||
| 2010 | -- lakukan sesuatu dengan byte | ||
| 2011 | print byte | ||
| 2012 | ``` | ||
| 2013 | |||
| 2014 | </YueDisplay> | ||
| 2015 | |||
| 2016 | # Penugasan Destrukturisasi | ||
| 2017 | |||
| 2018 | Assignment destrukturisasi adalah cara cepat untuk mengekstrak nilai dari sebuah tabel berdasarkan nama kunci atau posisinya pada tabel berbasis array. | ||
| 2019 | |||
| 2020 | Biasanya ketika Anda melihat literal tabel, `{1,2,3}`, ia berada di sisi kanan assignment karena merupakan nilai. Assignment destrukturisasi menukar peran literal tabel dan menaruhnya di sisi kiri pernyataan assignment. | ||
| 2021 | |||
| 2022 | Ini paling mudah dijelaskan dengan contoh. Berikut cara membongkar dua nilai pertama dari sebuah tabel: | ||
| 2023 | |||
| 2024 | ```yuescript | ||
| 2025 | thing = [1, 2] | ||
| 2026 | |||
| 2027 | [a, b] = thing | ||
| 2028 | print a, b | ||
| 2029 | ``` | ||
| 2030 | |||
| 2031 | <YueDisplay> | ||
| 2032 | |||
| 2033 | ```yue | ||
| 2034 | thing = [1, 2] | ||
| 2035 | |||
| 2036 | [a, b] = thing | ||
| 2037 | print a, b | ||
| 2038 | ``` | ||
| 2039 | |||
| 2040 | </YueDisplay> | ||
| 2041 | |||
| 2042 | Di literal tabel destrukturisasi, kunci mewakili kunci yang dibaca dari sisi kanan, dan nilai mewakili nama yang akan menerima nilai tersebut. | ||
| 2043 | |||
| 2044 | ```yuescript | ||
| 2045 | obj = { | ||
| 2046 | hello: "world" | ||
| 2047 | day: "tuesday" | ||
| 2048 | length: 20 | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | {hello: hello, day: the_day} = obj | ||
| 2052 | print hello, the_day | ||
| 2053 | |||
| 2054 | :day = obj -- OK untuk destrukturisasi sederhana tanpa kurung | ||
| 2055 | ``` | ||
| 2056 | |||
| 2057 | <YueDisplay> | ||
| 2058 | |||
| 2059 | ```yue | ||
| 2060 | obj = { | ||
| 2061 | hello: "world" | ||
| 2062 | day: "tuesday" | ||
| 2063 | length: 20 | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | {hello: hello, day: the_day} = obj | ||
| 2067 | print hello, the_day | ||
| 2068 | |||
| 2069 | :day = obj -- OK untuk destrukturisasi sederhana tanpa kurung | ||
| 2070 | ``` | ||
| 2071 | |||
| 2072 | </YueDisplay> | ||
| 2073 | |||
| 2074 | Ini juga bekerja pada struktur data bertingkat: | ||
| 2075 | |||
| 2076 | ```yuescript | ||
| 2077 | obj2 = { | ||
| 2078 | numbers: [1, 2, 3, 4] | ||
| 2079 | properties: { | ||
| 2080 | color: "green" | ||
| 2081 | height: 13.5 | ||
| 2082 | } | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2086 | print first, second, color | ||
| 2087 | ``` | ||
| 2088 | |||
| 2089 | <YueDisplay> | ||
| 2090 | |||
| 2091 | ```yue | ||
| 2092 | obj2 = { | ||
| 2093 | numbers: [1, 2, 3, 4] | ||
| 2094 | properties: { | ||
| 2095 | color: "green" | ||
| 2096 | height: 13.5 | ||
| 2097 | } | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2101 | print first, second, color | ||
| 2102 | ``` | ||
| 2103 | |||
| 2104 | </YueDisplay> | ||
| 2105 | |||
| 2106 | Jika pernyataan destrukturisasi kompleks, Anda bisa memecahnya ke beberapa baris. Contoh yang sedikit lebih rumit: | ||
| 2107 | |||
| 2108 | ```yuescript | ||
| 2109 | { | ||
| 2110 | numbers: [first, second] | ||
| 2111 | properties: { | ||
| 2112 | color: color | ||
| 2113 | } | ||
| 2114 | } = obj2 | ||
| 2115 | ``` | ||
| 2116 | |||
| 2117 | <YueDisplay> | ||
| 2118 | |||
| 2119 | ```yue | ||
| 2120 | { | ||
| 2121 | numbers: [first, second] | ||
| 2122 | properties: { | ||
| 2123 | color: color | ||
| 2124 | } | ||
| 2125 | } = obj2 | ||
| 2126 | ``` | ||
| 2127 | |||
| 2128 | </YueDisplay> | ||
| 2129 | |||
| 2130 | Umumnya mengekstrak nilai dari tabel lalu menugaskannya ke variabel local dengan nama yang sama dengan kuncinya. Untuk menghindari pengulangan, kita bisa menggunakan operator prefiks **:**: | ||
| 2131 | |||
| 2132 | ```yuescript | ||
| 2133 | {:concat, :insert} = table | ||
| 2134 | ``` | ||
| 2135 | |||
| 2136 | <YueDisplay> | ||
| 2137 | |||
| 2138 | ```yue | ||
| 2139 | {:concat, :insert} = table | ||
| 2140 | ``` | ||
| 2141 | |||
| 2142 | </YueDisplay> | ||
| 2143 | |||
| 2144 | Ini secara efektif sama seperti import, tetapi kita dapat mengganti nama field yang ingin diekstrak dengan menggabungkan sintaks: | ||
| 2145 | |||
| 2146 | ```yuescript | ||
| 2147 | {:mix, :max, random: rand} = math | ||
| 2148 | ``` | ||
| 2149 | |||
| 2150 | <YueDisplay> | ||
| 2151 | |||
| 2152 | ```yue | ||
| 2153 | {:mix, :max, random: rand} = math | ||
| 2154 | ``` | ||
| 2155 | |||
| 2156 | </YueDisplay> | ||
| 2157 | |||
| 2158 | Anda bisa menulis nilai default saat destrukturisasi seperti: | ||
| 2159 | |||
| 2160 | ```yuescript | ||
| 2161 | {:name = "nameless", :job = "jobless"} = person | ||
| 2162 | ``` | ||
| 2163 | |||
| 2164 | <YueDisplay> | ||
| 2165 | |||
| 2166 | ```yue | ||
| 2167 | {:name = "nameless", :job = "jobless"} = person | ||
| 2168 | ``` | ||
| 2169 | |||
| 2170 | </YueDisplay> | ||
| 2171 | |||
| 2172 | Anda dapat menggunakan `_` sebagai placeholder saat destrukturisasi list: | ||
| 2173 | |||
| 2174 | ```yuescript | ||
| 2175 | [_, two, _, four] = items | ||
| 2176 | ``` | ||
| 2177 | |||
| 2178 | <YueDisplay> | ||
| 2179 | |||
| 2180 | ```yue | ||
| 2181 | [_, two, _, four] = items | ||
| 2182 | ``` | ||
| 2183 | |||
| 2184 | </YueDisplay> | ||
| 2185 | |||
| 2186 | ## Destrukturisasi Rentang | ||
| 2187 | |||
| 2188 | Anda dapat menggunakan operator spread `...` pada destrukturisasi list untuk menangkap rentang nilai. Ini berguna ketika Anda ingin mengekstrak elemen tertentu dari awal dan akhir list sambil mengumpulkan sisanya di tengah. | ||
| 2189 | |||
| 2190 | ```yuescript | ||
| 2191 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2192 | [first, ...bulk, last] = orders | ||
| 2193 | print first -- prints: first | ||
| 2194 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 2195 | print last -- prints: last | ||
| 2196 | ``` | ||
| 2197 | |||
| 2198 | <YueDisplay> | ||
| 2199 | |||
| 2200 | ```yue | ||
| 2201 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2202 | [first, ...bulk, last] = orders | ||
| 2203 | print first -- prints: first | ||
| 2204 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 2205 | print last -- prints: last | ||
| 2206 | ``` | ||
| 2207 | |||
| 2208 | </YueDisplay> | ||
| 2209 | |||
| 2210 | Operator spread dapat digunakan pada posisi berbeda untuk menangkap rentang yang berbeda, dan Anda bisa memakai `_` sebagai placeholder untuk nilai yang tidak ingin ditangkap: | ||
| 2211 | |||
| 2212 | ```yuescript | ||
| 2213 | -- Tangkap semuanya setelah elemen pertama | ||
| 2214 | [first, ...rest] = orders | ||
| 2215 | |||
| 2216 | -- Tangkap semuanya sebelum elemen terakhir | ||
| 2217 | [...start, last] = orders | ||
| 2218 | |||
| 2219 | -- Tangkap semuanya kecuali elemen tengah | ||
| 2220 | [first, ..._, last] = orders | ||
| 2221 | ``` | ||
| 2222 | |||
| 2223 | <YueDisplay> | ||
| 2224 | |||
| 2225 | ```yue | ||
| 2226 | -- Tangkap semuanya setelah elemen pertama | ||
| 2227 | [first, ...rest] = orders | ||
| 2228 | |||
| 2229 | -- Tangkap semuanya sebelum elemen terakhir | ||
| 2230 | [...start, last] = orders | ||
| 2231 | |||
| 2232 | -- Tangkap semuanya kecuali elemen tengah | ||
| 2233 | [first, ..._, last] = orders | ||
| 2234 | ``` | ||
| 2235 | |||
| 2236 | </YueDisplay> | ||
| 2237 | |||
| 2238 | ## Destrukturisasi di Tempat Lain | ||
| 2239 | |||
| 2240 | Destrukturisasi juga dapat muncul di tempat-tempat di mana assignment terjadi secara implisit. Contohnya adalah perulangan for: | ||
| 2241 | |||
| 2242 | ```yuescript | ||
| 2243 | tuples = [ | ||
| 2244 | ["hello", "world"] | ||
| 2245 | ["egg", "head"] | ||
| 2246 | ] | ||
| 2247 | |||
| 2248 | for [left, right] in *tuples | ||
| 2249 | print left, right | ||
| 2250 | ``` | ||
| 2251 | |||
| 2252 | <YueDisplay> | ||
| 2253 | |||
| 2254 | ```yue | ||
| 2255 | tuples = [ | ||
| 2256 | ["hello", "world"] | ||
| 2257 | ["egg", "head"] | ||
| 2258 | ] | ||
| 2259 | |||
| 2260 | for [left, right] in *tuples | ||
| 2261 | print left, right | ||
| 2262 | ``` | ||
| 2263 | |||
| 2264 | </YueDisplay> | ||
| 2265 | |||
| 2266 | Kita tahu setiap elemen pada tabel array adalah tuple dua item, sehingga kita dapat membongkarnya langsung di klausa nama pada pernyataan for menggunakan destrukturisasi. | ||
| 2267 | |||
| 2268 | # Klausa Using; Mengendalikan Penugasan Destruktif | ||
| 2269 | |||
| 2270 | Meskipun scope leksikal sangat membantu mengurangi kompleksitas kode yang kita tulis, hal ini bisa menjadi sulit ketika ukuran kode membesar. Pertimbangkan cuplikan berikut: | ||
| 2271 | |||
| 2272 | ```yuescript | ||
| 2273 | i = 100 | ||
| 2274 | |||
| 2275 | -- banyak baris kode... | ||
| 2276 | |||
| 2277 | my_func = -> | ||
| 2278 | i = 10 | ||
| 2279 | while i > 0 | ||
| 2280 | print i | ||
| 2281 | i -= 1 | ||
| 2282 | |||
| 2283 | my_func! | ||
| 2284 | |||
| 2285 | print i -- akan mencetak 0 | ||
| 2286 | ``` | ||
| 2287 | |||
| 2288 | <YueDisplay> | ||
| 2289 | |||
| 2290 | ```yue | ||
| 2291 | i = 100 | ||
| 2292 | |||
| 2293 | -- banyak baris kode... | ||
| 2294 | |||
| 2295 | my_func = -> | ||
| 2296 | i = 10 | ||
| 2297 | while i > 0 | ||
| 2298 | print i | ||
| 2299 | i -= 1 | ||
| 2300 | |||
| 2301 | my_func! | ||
| 2302 | |||
| 2303 | print i -- akan mencetak 0 | ||
| 2304 | ``` | ||
| 2305 | |||
| 2306 | </YueDisplay> | ||
| 2307 | |||
| 2308 | Di `my_func`, kita tanpa sengaja menimpa nilai `i`. Dalam contoh ini halnya cukup jelas, tetapi bayangkan kode besar atau basis kode asing di mana tidak jelas nama apa saja yang sudah dideklarasikan. | ||
| 2309 | |||
| 2310 | Akan sangat membantu jika kita dapat menyatakan variabel mana dari scope luar yang memang ingin kita ubah, agar mencegah mengubah yang lain secara tidak sengaja. | ||
| 2311 | |||
| 2312 | Kata kunci `using` memungkinkan kita melakukan itu. `using nil` memastikan bahwa tidak ada variabel tertutup yang ditimpa dalam assignment. Klausa `using` ditempatkan setelah daftar argumen pada fungsi, atau menggantikannya jika tidak ada argumen. | ||
| 2313 | |||
| 2314 | ```yuescript | ||
| 2315 | i = 100 | ||
| 2316 | |||
| 2317 | my_func = (using nil) -> | ||
| 2318 | i = "hello" -- variabel local baru dibuat di sini | ||
| 2319 | |||
| 2320 | my_func! | ||
| 2321 | print i -- mencetak 100, i tidak terpengaruh | ||
| 2322 | ``` | ||
| 2323 | |||
| 2324 | <YueDisplay> | ||
| 2325 | |||
| 2326 | ```yue | ||
| 2327 | i = 100 | ||
| 2328 | |||
| 2329 | my_func = (using nil) -> | ||
| 2330 | i = "hello" -- variabel local baru dibuat di sini | ||
| 2331 | |||
| 2332 | my_func! | ||
| 2333 | print i -- mencetak 100, i tidak terpengaruh | ||
| 2334 | ``` | ||
| 2335 | |||
| 2336 | </YueDisplay> | ||
| 2337 | |||
| 2338 | Beberapa nama dapat dipisahkan dengan koma. Nilai closure tetap bisa diakses, hanya saja tidak dapat dimodifikasi: | ||
| 2339 | |||
| 2340 | ```yuescript | ||
| 2341 | tmp = 1213 | ||
| 2342 | i, k = 100, 50 | ||
| 2343 | |||
| 2344 | my_func = (add using k, i) -> | ||
| 2345 | tmp = tmp + add -- tmp local baru dibuat | ||
| 2346 | i += tmp | ||
| 2347 | k += tmp | ||
| 2348 | |||
| 2349 | my_func(22) | ||
| 2350 | print i, k -- ini telah diperbarui | ||
| 2351 | ``` | ||
| 2352 | |||
| 2353 | <YueDisplay> | ||
| 2354 | |||
| 2355 | ```yue | ||
| 2356 | tmp = 1213 | ||
| 2357 | i, k = 100, 50 | ||
| 2358 | |||
| 2359 | my_func = (add using k, i) -> | ||
| 2360 | tmp = tmp + add -- tmp local baru dibuat | ||
| 2361 | i += tmp | ||
| 2362 | k += tmp | ||
| 2363 | |||
| 2364 | my_func(22) | ||
| 2365 | print i, k -- ini telah diperbarui | ||
| 2366 | ``` | ||
| 2367 | |||
| 2368 | </YueDisplay> | ||
| 2369 | |||
| 2370 | # Penggunaan | ||
| 2371 | |||
| 2372 | ## Modul Lua | ||
| 2373 | |||
| 2374 | Gunakan modul YueScript di Lua: | ||
| 2375 | |||
| 2376 | - **Kasus 1** | ||
| 2377 | |||
| 2378 | Require "your_yuescript_entry.yue" di Lua. | ||
| 2379 | |||
| 2380 | ```Lua | ||
| 2381 | require("yue")("your_yuescript_entry") | ||
| 2382 | ``` | ||
| 2383 | |||
| 2384 | Dan kode ini tetap bekerja ketika Anda mengompilasi "your_yuescript_entry.yue" menjadi "your_yuescript_entry.lua" di path yang sama. Pada file YueScript lainnya cukup gunakan **require** atau **import** biasa. Nomor baris pada pesan error juga akan ditangani dengan benar. | ||
| 2385 | |||
| 2386 | - **Kasus 2** | ||
| 2387 | |||
| 2388 | Require modul YueScript dan tulis ulang pesan secara manual. | ||
| 2389 | |||
| 2390 | ```lua | ||
| 2391 | local yue = require("yue") | ||
| 2392 | yue.insert_loader() | ||
| 2393 | local success, result = xpcall(function() | ||
| 2394 | return require("yuescript_module_name") | ||
| 2395 | end, function(err) | ||
| 2396 | return yue.traceback(err) | ||
| 2397 | end) | ||
| 2398 | ``` | ||
| 2399 | |||
| 2400 | - **Kasus 3** | ||
| 2401 | |||
| 2402 | Gunakan fungsi kompiler YueScript di Lua. | ||
| 2403 | |||
| 2404 | ```lua | ||
| 2405 | local yue = require("yue") | ||
| 2406 | local codes, err, globals = yue.to_lua([[ | ||
| 2407 | f = -> | ||
| 2408 | print "hello world" | ||
| 2409 | f! | ||
| 2410 | ]],{ | ||
| 2411 | implicit_return_root = true, | ||
| 2412 | reserve_line_number = true, | ||
| 2413 | lint_global = true, | ||
| 2414 | space_over_tab = false, | ||
| 2415 | options = { | ||
| 2416 | target = "5.4", | ||
| 2417 | path = "/script" | ||
| 2418 | } | ||
| 2419 | }) | ||
| 2420 | ``` | ||
| 2421 | |||
| 2422 | ## Tool YueScript | ||
| 2423 | |||
| 2424 | Gunakan tool YueScript dengan: | ||
| 2425 | |||
| 2426 | ```shell | ||
| 2427 | > yue -h | ||
| 2428 | Penggunaan: yue | ||
| 2429 | [opsi] [<file/direktori>] ... | ||
| 2430 | yue -e <kode_atau_file> [argumen...] | ||
| 2431 | yue -w [<direktori>] [opsi] | ||
| 2432 | yue - | ||
| 2433 | |||
| 2434 | Catatan: | ||
| 2435 | - '-' / '--' harus menjadi argumen pertama dan satu-satunya. | ||
| 2436 | - '-o/--output' tidak dapat digunakan dengan beberapa file input. | ||
| 2437 | - '-w/--watch' tidak dapat digunakan dengan file input (khusus direktori). | ||
| 2438 | - dengan '-e/--execute', token sisanya dianggap sebagai argumen skrip. | ||
| 2439 | |||
| 2440 | Opsi: | ||
| 2441 | -h, --help Tampilkan pesan bantuan ini dan keluar. | ||
| 2442 | -e <str>, --execute <str> Eksekusi file atau kode mentah | ||
| 2443 | -m, --minify Menghasilkan kode yang sudah diminimasi | ||
| 2444 | -r, --rewrite Tulis ulang output agar sesuai dengan nomor baris asal | ||
| 2445 | -t <output_to>, --output-to <output_to> | ||
| 2446 | Tentukan lokasi untuk menaruh file hasil kompilasi | ||
| 2447 | -o <file>, --output <file> Tulis output ke file | ||
| 2448 | -p, --print Tulis output ke standar output | ||
| 2449 | -b, --benchmark Tampilkan waktu kompilasi (tanpa menulis output) | ||
| 2450 | -g, --globals Tampilkan variabel global yang digunakan dalam FORMAT NAMA BARIS KOLOM | ||
| 2451 | -s, --spaces Pakai spasi di kode hasil kompilasi (bukan tab) | ||
| 2452 | -l, --line-numbers Tulis nomor baris dari kode sumber | ||
| 2453 | -j, --no-implicit-return Nonaktifkan return implisit di akhir file | ||
| 2454 | -c, --reserve-comments Pertahankan komentar sebelum pernyataan dari kode sumber | ||
| 2455 | -w [<dir>], --watch [<dir>] | ||
| 2456 | Pantau perubahan dan kompilasi setiap file di bawah direktori | ||
| 2457 | -v, --version Tampilkan versi | ||
| 2458 | - Baca dari standar input, tulis ke standar output | ||
| 2459 | (harus menjadi argumen pertama dan satu-satunya) | ||
| 2460 | -- Sama dengan '-', dipertahankan untuk kompatibilitas lama | ||
| 2461 | |||
| 2462 | --target <versi> Tentukan versi Lua yang akan dihasilkan kodenya | ||
| 2463 | (versi hanya bisa dari 5.1 sampai 5.5) | ||
| 2464 | --path <path_str> Tambahkan path pencarian Lua tambahan ke package.path | ||
| 2465 | --<key>=<value> Kirim opsi kompilasi dalam bentuk key=value (perilaku standar) | ||
| 2466 | |||
| 2467 | Jalankan tanpa opsi untuk masuk ke REPL, ketik simbol '$' | ||
| 2468 | dalam satu baris untuk memulai/mengakhiri mode multi-baris | ||
| 2469 | ``` | ||
| 2470 | |||
| 2471 | Gunakan kasus: | ||
| 2472 | |||
| 2473 | Kompilasi semua file YueScript dengan ekstensi **.yue** secara rekursif di bawah path saat ini: **yue .** | ||
| 2474 | |||
| 2475 | Kompilasi dan simpan hasil ke path target: **yue -t /target/path/ .** | ||
| 2476 | |||
| 2477 | Kompilasi dan pertahankan info debug: **yue -l .** | ||
| 2478 | |||
| 2479 | Kompilasi dan hasilkan kode yang diminisasi: **yue -m .** | ||
| 2480 | |||
| 2481 | Eksekusi kode mentah: **yue -e 'print 123'** | ||
| 2482 | |||
| 2483 | Eksekusi file YueScript: **yue -e main.yue** | ||
| 2484 | |||
| 2485 | # Pendahuluan | ||
| 2486 | |||
| 2487 | YueScript adalah bahasa dinamis yang dikompilasi ke Lua, dan merupakan dialek [MoonScript](https://github.com/leafo/moonscript). Kode yang ditulis dengan YueScript ekspresif dan sangat ringkas. YueScript cocok untuk menulis logika aplikasi yang sering berubah dengan kode yang lebih mudah dipelihara, serta berjalan di lingkungan embed Lua seperti game atau server situs web. | ||
| 2488 | |||
| 2489 | Yue (月) adalah kata untuk bulan dalam bahasa Tionghoa dan diucapkan sebagai [jyɛ]. | ||
| 2490 | |||
| 2491 | ## Ikhtisar YueScript | ||
| 2492 | |||
| 2493 | ```yuescript | ||
| 2494 | -- import syntax | ||
| 2495 | import p, to_lua from "yue" | ||
| 2496 | |||
| 2497 | -- object literals | ||
| 2498 | inventory = | ||
| 2499 | equipment: | ||
| 2500 | - "sword" | ||
| 2501 | - "shield" | ||
| 2502 | items: | ||
| 2503 | - name: "potion" | ||
| 2504 | count: 10 | ||
| 2505 | - name: "bread" | ||
| 2506 | count: 3 | ||
| 2507 | |||
| 2508 | -- list comprehension | ||
| 2509 | map = (arr, action) -> | ||
| 2510 | [action item for item in *arr] | ||
| 2511 | |||
| 2512 | filter = (arr, cond) -> | ||
| 2513 | [item for item in *arr when cond item] | ||
| 2514 | |||
| 2515 | reduce = (arr, init, action): init -> | ||
| 2516 | init = action init, item for item in *arr | ||
| 2517 | |||
| 2518 | -- pipe operator | ||
| 2519 | [1, 2, 3] | ||
| 2520 | |> map (x) -> x * 2 | ||
| 2521 | |> filter (x) -> x > 4 | ||
| 2522 | |> reduce 0, (a, b) -> a + b | ||
| 2523 | |||
| 2524 | |||
| 2525 | -- metatable manipulation | ||
| 2526 | apple = | ||
| 2527 | size: 15 | ||
| 2528 | <index>: | ||
| 2529 | color: 0x00ffff | ||
| 2530 | |||
| 2531 | with apple | ||
| 2532 | p .size, .color, .<index> if .<>? | ||
| 2533 | |||
| 2534 | -- js-like export syntax | ||
| 2535 | export 🌛 = "Skrip Bulan" | ||
| 2536 | ``` | ||
| 2537 | |||
| 2538 | <YueDisplay> | ||
| 2539 | |||
| 2540 | ```yue | ||
| 2541 | -- import syntax | ||
| 2542 | import p, to_lua from "yue" | ||
| 2543 | |||
| 2544 | -- object literals | ||
| 2545 | inventory = | ||
| 2546 | equipment: | ||
| 2547 | - "sword" | ||
| 2548 | - "shield" | ||
| 2549 | items: | ||
| 2550 | - name: "potion" | ||
| 2551 | count: 10 | ||
| 2552 | - name: "bread" | ||
| 2553 | count: 3 | ||
| 2554 | |||
| 2555 | -- list comprehension | ||
| 2556 | map = (arr, action) -> | ||
| 2557 | [action item for item in *arr] | ||
| 2558 | |||
| 2559 | filter = (arr, cond) -> | ||
| 2560 | [item for item in *arr when cond item] | ||
| 2561 | |||
| 2562 | reduce = (arr, init, action): init -> | ||
| 2563 | init = action init, item for item in *arr | ||
| 2564 | |||
| 2565 | -- pipe operator | ||
| 2566 | [1, 2, 3] | ||
| 2567 | |> map (x) -> x * 2 | ||
| 2568 | |> filter (x) -> x > 4 | ||
| 2569 | |> reduce 0, (a, b) -> a + b | ||
| 2570 | |||
| 2571 | |||
| 2572 | -- metatable manipulation | ||
| 2573 | apple = | ||
| 2574 | size: 15 | ||
| 2575 | <index>: | ||
| 2576 | color: 0x00ffff | ||
| 2577 | |||
| 2578 | with apple | ||
| 2579 | p .size, .color, .<index> if .<>? | ||
| 2580 | |||
| 2581 | -- js-like export syntax | ||
| 2582 | export 🌛 = "Skrip Bulan" | ||
| 2583 | ``` | ||
| 2584 | |||
| 2585 | </YueDisplay> | ||
| 2586 | |||
| 2587 | ## Tentang Dora SSR | ||
| 2588 | |||
| 2589 | YueScript dikembangkan dan dipelihara bersama mesin game open-source [Dora SSR](https://github.com/Dora-SSR/Dora-SSR). YueScript telah digunakan untuk membuat alat mesin, demo game, dan prototipe, membuktikan kemampuannya dalam skenario dunia nyata sekaligus meningkatkan pengalaman pengembangan Dora SSR. | ||
| 2590 | |||
| 2591 | # Instalasi | ||
| 2592 | |||
| 2593 | ## Modul Lua | ||
| 2594 | |||
| 2595 | Instal [luarocks](https://luarocks.org), manajer paket untuk modul Lua. Lalu instal sebagai modul Lua dan executable dengan: | ||
| 2596 | |||
| 2597 | ```shell | ||
| 2598 | luarocks install yuescript | ||
| 2599 | ``` | ||
| 2600 | |||
| 2601 | Atau Anda dapat membangun file `yue.so` dengan: | ||
| 2602 | |||
| 2603 | ```shell | ||
| 2604 | make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua | ||
| 2605 | ``` | ||
| 2606 | |||
| 2607 | Lalu ambil file biner dari path **bin/shared/yue.so**. | ||
| 2608 | |||
| 2609 | ## Membangun Tool Biner | ||
| 2610 | |||
| 2611 | Klon repo ini, lalu bangun dan instal executable dengan: | ||
| 2612 | |||
| 2613 | ```shell | ||
| 2614 | make install | ||
| 2615 | ``` | ||
| 2616 | |||
| 2617 | Bangun tool YueScript tanpa fitur macro: | ||
| 2618 | |||
| 2619 | ```shell | ||
| 2620 | make install NO_MACRO=true | ||
| 2621 | ``` | ||
| 2622 | |||
| 2623 | Bangun tool YueScript tanpa biner Lua bawaan: | ||
| 2624 | |||
| 2625 | ```shell | ||
| 2626 | make install NO_LUA=true | ||
| 2627 | ``` | ||
| 2628 | |||
| 2629 | ## Unduh Biner Pra-kompilasi | ||
| 2630 | |||
| 2631 | Anda dapat mengunduh file biner pra-kompilasi, termasuk file executable biner yang kompatibel dengan berbagai versi Lua dan file library. | ||
| 2632 | |||
| 2633 | Unduh file biner pra-kompilasi dari [sini](https://github.com/IppClub/YueScript/releases). | ||
| 2634 | |||
| 2635 | # Kondisional | ||
| 2636 | |||
| 2637 | ```yuescript | ||
| 2638 | have_coins = false | ||
| 2639 | if have_coins | ||
| 2640 | print "Dapat koin" | ||
| 2641 | else | ||
| 2642 | print "Tidak ada koin" | ||
| 2643 | ``` | ||
| 2644 | |||
| 2645 | <YueDisplay> | ||
| 2646 | |||
| 2647 | ```yue | ||
| 2648 | have_coins = false | ||
| 2649 | if have_coins | ||
| 2650 | print "Dapat koin" | ||
| 2651 | else | ||
| 2652 | print "Tidak ada koin" | ||
| 2653 | ``` | ||
| 2654 | |||
| 2655 | </YueDisplay> | ||
| 2656 | |||
| 2657 | Sintaks pendek untuk pernyataan tunggal juga bisa digunakan: | ||
| 2658 | |||
| 2659 | ```yuescript | ||
| 2660 | have_coins = false | ||
| 2661 | if have_coins then print "Dapat koin" else print "Tidak ada koin" | ||
| 2662 | ``` | ||
| 2663 | |||
| 2664 | <YueDisplay> | ||
| 2665 | |||
| 2666 | ```yue | ||
| 2667 | have_coins = false | ||
| 2668 | if have_coins then print "Dapat koin" else print "Tidak ada koin" | ||
| 2669 | ``` | ||
| 2670 | |||
| 2671 | </YueDisplay> | ||
| 2672 | |||
| 2673 | Karena pernyataan if dapat digunakan sebagai ekspresi, ini juga bisa ditulis sebagai: | ||
| 2674 | |||
| 2675 | ```yuescript | ||
| 2676 | have_coins = false | ||
| 2677 | print if have_coins then "Dapat koin" else "Tidak ada koin" | ||
| 2678 | ``` | ||
| 2679 | |||
| 2680 | <YueDisplay> | ||
| 2681 | |||
| 2682 | ```yue | ||
| 2683 | have_coins = false | ||
| 2684 | print if have_coins then "Dapat koin" else "Tidak ada koin" | ||
| 2685 | ``` | ||
| 2686 | |||
| 2687 | </YueDisplay> | ||
| 2688 | |||
| 2689 | Kondisional juga bisa digunakan di pernyataan return dan assignment: | ||
| 2690 | |||
| 2691 | ```yuescript | ||
| 2692 | is_tall = (name) -> | ||
| 2693 | if name == "Rob" | ||
| 2694 | true | ||
| 2695 | else | ||
| 2696 | false | ||
| 2697 | |||
| 2698 | message = if is_tall "Rob" | ||
| 2699 | "Saya sangat tinggi" | ||
| 2700 | else | ||
| 2701 | "Saya tidak terlalu tinggi" | ||
| 2702 | |||
| 2703 | print message -- prints: Saya sangat tinggi | ||
| 2704 | ``` | ||
| 2705 | |||
| 2706 | <YueDisplay> | ||
| 2707 | |||
| 2708 | ```yue | ||
| 2709 | is_tall = (name) -> | ||
| 2710 | if name == "Rob" | ||
| 2711 | true | ||
| 2712 | else | ||
| 2713 | false | ||
| 2714 | |||
| 2715 | message = if is_tall "Rob" | ||
| 2716 | "Saya sangat tinggi" | ||
| 2717 | else | ||
| 2718 | "Saya tidak terlalu tinggi" | ||
| 2719 | |||
| 2720 | print message -- prints: Saya sangat tinggi | ||
| 2721 | ``` | ||
| 2722 | |||
| 2723 | </YueDisplay> | ||
| 2724 | |||
| 2725 | Kebalikan dari if adalah unless: | ||
| 2726 | |||
| 2727 | ```yuescript | ||
| 2728 | unless os.date("%A") == "Monday" | ||
| 2729 | print "hari ini bukan Senin!" | ||
| 2730 | ``` | ||
| 2731 | |||
| 2732 | <YueDisplay> | ||
| 2733 | |||
| 2734 | ```yue | ||
| 2735 | unless os.date("%A") == "Monday" | ||
| 2736 | print "hari ini bukan Senin!" | ||
| 2737 | ``` | ||
| 2738 | |||
| 2739 | </YueDisplay> | ||
| 2740 | |||
| 2741 | ```yuescript | ||
| 2742 | print "Kamu beruntung!" unless math.random! > 0.1 | ||
| 2743 | ``` | ||
| 2744 | |||
| 2745 | <YueDisplay> | ||
| 2746 | |||
| 2747 | ```yue | ||
| 2748 | print "Kamu beruntung!" unless math.random! > 0.1 | ||
| 2749 | ``` | ||
| 2750 | |||
| 2751 | </YueDisplay> | ||
| 2752 | |||
| 2753 | ## Ekspresi In | ||
| 2754 | |||
| 2755 | Anda dapat menulis kode pengecekan rentang dengan `ekspresi in`. | ||
| 2756 | |||
| 2757 | ```yuescript | ||
| 2758 | a = 5 | ||
| 2759 | |||
| 2760 | if a in [1, 3, 5, 7] | ||
| 2761 | print "memeriksa kesamaan dengan nilai-nilai diskrit" | ||
| 2762 | |||
| 2763 | if a in list | ||
| 2764 | print "memeriksa apakah `a` ada di dalam daftar" | ||
| 2765 | ``` | ||
| 2766 | |||
| 2767 | <YueDisplay> | ||
| 2768 | |||
| 2769 | ```yue | ||
| 2770 | a = 5 | ||
| 2771 | |||
| 2772 | if a in [1, 3, 5, 7] | ||
| 2773 | print "memeriksa kesamaan dengan nilai-nilai diskrit" | ||
| 2774 | |||
| 2775 | if a in list | ||
| 2776 | print "memeriksa apakah `a` ada di dalam daftar" | ||
| 2777 | ``` | ||
| 2778 | |||
| 2779 | </YueDisplay> | ||
| 2780 | |||
| 2781 | # Perulangan For | ||
| 2782 | |||
| 2783 | Ada dua bentuk perulangan for, seperti di Lua. Satu numerik dan satu generik: | ||
| 2784 | |||
| 2785 | ```yuescript | ||
| 2786 | for i = 10, 20 | ||
| 2787 | print i | ||
| 2788 | |||
| 2789 | for k = 1, 15, 2 -- an optional step provided | ||
| 2790 | print k | ||
| 2791 | |||
| 2792 | for key, value in pairs object | ||
| 2793 | print key, value | ||
| 2794 | ``` | ||
| 2795 | |||
| 2796 | <YueDisplay> | ||
| 2797 | |||
| 2798 | ```yue | ||
| 2799 | for i = 10, 20 | ||
| 2800 | print i | ||
| 2801 | |||
| 2802 | for k = 1, 15, 2 -- an optional step provided | ||
| 2803 | print k | ||
| 2804 | |||
| 2805 | for key, value in pairs object | ||
| 2806 | print key, value | ||
| 2807 | ``` | ||
| 2808 | |||
| 2809 | </YueDisplay> | ||
| 2810 | |||
| 2811 | Operator slicing dan **\*** dapat digunakan, seperti pada comprehension: | ||
| 2812 | |||
| 2813 | ```yuescript | ||
| 2814 | for item in *items[2, 4] | ||
| 2815 | print item | ||
| 2816 | ``` | ||
| 2817 | |||
| 2818 | <YueDisplay> | ||
| 2819 | |||
| 2820 | ```yue | ||
| 2821 | for item in *items[2, 4] | ||
| 2822 | print item | ||
| 2823 | ``` | ||
| 2824 | |||
| 2825 | </YueDisplay> | ||
| 2826 | |||
| 2827 | Sintaks yang lebih singkat juga tersedia untuk semua variasi ketika badan hanya satu baris: | ||
| 2828 | |||
| 2829 | ```yuescript | ||
| 2830 | for item in *items do print item | ||
| 2831 | |||
| 2832 | for j = 1, 10, 3 do print j | ||
| 2833 | ``` | ||
| 2834 | |||
| 2835 | <YueDisplay> | ||
| 2836 | |||
| 2837 | ```yue | ||
| 2838 | for item in *items do print item | ||
| 2839 | |||
| 2840 | for j = 1, 10, 3 do print j | ||
| 2841 | ``` | ||
| 2842 | |||
| 2843 | </YueDisplay> | ||
| 2844 | |||
| 2845 | Perulangan for juga bisa digunakan sebagai ekspresi. Pernyataan terakhir di badan for dipaksa menjadi ekspresi dan ditambahkan ke tabel array yang terakumulasi. | ||
| 2846 | |||
| 2847 | Menggandakan setiap bilangan genap: | ||
| 2848 | |||
| 2849 | ```yuescript | ||
| 2850 | doubled_evens = for i = 1, 20 | ||
| 2851 | if i % 2 == 0 | ||
| 2852 | i * 2 | ||
| 2853 | else | ||
| 2854 | i | ||
| 2855 | ``` | ||
| 2856 | |||
| 2857 | <YueDisplay> | ||
| 2858 | |||
| 2859 | ```yue | ||
| 2860 | doubled_evens = for i = 1, 20 | ||
| 2861 | if i % 2 == 0 | ||
| 2862 | i * 2 | ||
| 2863 | else | ||
| 2864 | i | ||
| 2865 | ``` | ||
| 2866 | |||
| 2867 | </YueDisplay> | ||
| 2868 | |||
| 2869 | Selain itu, loop for mendukung break dengan nilai kembalian, sehingga loop itu sendiri bisa dipakai sebagai ekspresi yang keluar lebih awal dengan hasil bermakna. Ekspresi `for` mendukung `break` dengan banyak nilai. | ||
| 2870 | |||
| 2871 | Contohnya, untuk menemukan angka pertama yang lebih besar dari 10: | ||
| 2872 | |||
| 2873 | ```yuescript | ||
| 2874 | first_large = for n in *numbers | ||
| 2875 | break n if n > 10 | ||
| 2876 | ``` | ||
| 2877 | |||
| 2878 | <YueDisplay> | ||
| 2879 | |||
| 2880 | ```yue | ||
| 2881 | first_large = for n in *numbers | ||
| 2882 | break n if n > 10 | ||
| 2883 | ``` | ||
| 2884 | |||
| 2885 | </YueDisplay> | ||
| 2886 | |||
| 2887 | Sintaks break-dengan-nilai ini memungkinkan pola pencarian atau keluar-lebih-awal yang ringkas langsung di dalam ekspresi loop. | ||
| 2888 | |||
| 2889 | ```yuescript | ||
| 2890 | key, score = for k, v in pairs data | ||
| 2891 | break k, v * 10 if k == "target" | ||
| 2892 | ``` | ||
| 2893 | |||
| 2894 | <YueDisplay> | ||
| 2895 | |||
| 2896 | ```yue | ||
| 2897 | key, score = for k, v in pairs data | ||
| 2898 | break k, v * 10 if k == "target" | ||
| 2899 | ``` | ||
| 2900 | |||
| 2901 | </YueDisplay> | ||
| 2902 | |||
| 2903 | Anda juga bisa memfilter nilai dengan menggabungkan ekspresi for dengan pernyataan continue. | ||
| 2904 | |||
| 2905 | Loop for di akhir badan fungsi tidak diakumulasikan menjadi tabel untuk nilai kembalian (sebaliknya fungsi akan mengembalikan nil). Gunakan pernyataan return eksplisit, atau ubah loop menjadi list comprehension. | ||
| 2906 | |||
| 2907 | ```yuescript | ||
| 2908 | func_a = -> for i = 1, 10 do print i | ||
| 2909 | func_b = -> return for i = 1, 10 do i | ||
| 2910 | |||
| 2911 | print func_a! -- prints nil | ||
| 2912 | print func_b! -- prints table object | ||
| 2913 | ``` | ||
| 2914 | |||
| 2915 | <YueDisplay> | ||
| 2916 | |||
| 2917 | ```yue | ||
| 2918 | func_a = -> for i = 1, 10 do print i | ||
| 2919 | func_b = -> return for i = 1, 10 do i | ||
| 2920 | |||
| 2921 | print func_a! -- prints nil | ||
| 2922 | print func_b! -- prints table object | ||
| 2923 | ``` | ||
| 2924 | |||
| 2925 | </YueDisplay> | ||
| 2926 | |||
| 2927 | # Pernyataan Continue | ||
| 2928 | |||
| 2929 | Pernyataan continue dapat digunakan untuk melewati iterasi saat ini di dalam loop. | ||
| 2930 | |||
| 2931 | ```yuescript | ||
| 2932 | i = 0 | ||
| 2933 | while i < 10 | ||
| 2934 | i += 1 | ||
| 2935 | continue if i % 2 == 0 | ||
| 2936 | print i | ||
| 2937 | ``` | ||
| 2938 | |||
| 2939 | <YueDisplay> | ||
| 2940 | |||
| 2941 | ```yue | ||
| 2942 | i = 0 | ||
| 2943 | while i < 10 | ||
| 2944 | i += 1 | ||
| 2945 | continue if i % 2 == 0 | ||
| 2946 | print i | ||
| 2947 | ``` | ||
| 2948 | |||
| 2949 | </YueDisplay> | ||
| 2950 | |||
| 2951 | continue juga bisa digunakan bersama ekspresi loop untuk mencegah iterasi tersebut diakumulasikan ke hasil. Contoh ini memfilter tabel array menjadi hanya angka genap: | ||
| 2952 | |||
| 2953 | ```yuescript | ||
| 2954 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2955 | odds = for x in *my_numbers | ||
| 2956 | continue if x % 2 == 1 | ||
| 2957 | x | ||
| 2958 | ``` | ||
| 2959 | |||
| 2960 | <YueDisplay> | ||
| 2961 | |||
| 2962 | ```yue | ||
| 2963 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2964 | odds = for x in *my_numbers | ||
| 2965 | continue if x % 2 == 1 | ||
| 2966 | x | ||
| 2967 | ``` | ||
| 2968 | |||
| 2969 | </YueDisplay> | ||
| 2970 | |||
| 2971 | # Pernyataan Switch | ||
| 2972 | |||
| 2973 | Pernyataan switch adalah bentuk singkat untuk menulis serangkaian if yang membandingkan nilai yang sama. Perhatikan bahwa nilainya hanya dievaluasi sekali. Seperti if, switch bisa memiliki blok else untuk menangani tidak ada yang cocok. Perbandingan dilakukan dengan operator `==`. Di dalam switch, Anda juga bisa memakai ekspresi assignment untuk menyimpan nilai variabel sementara. | ||
| 2974 | |||
| 2975 | ```yuescript | ||
| 2976 | switch name := "Dan" | ||
| 2977 | when "Robert" | ||
| 2978 | print "You are Robert" | ||
| 2979 | when "Dan", "Daniel" | ||
| 2980 | print "Your name, it's Dan" | ||
| 2981 | else | ||
| 2982 | print "I don't know about you with name #{name}" | ||
| 2983 | ``` | ||
| 2984 | |||
| 2985 | <YueDisplay> | ||
| 2986 | |||
| 2987 | ```yue | ||
| 2988 | switch name := "Dan" | ||
| 2989 | when "Robert" | ||
| 2990 | print "You are Robert" | ||
| 2991 | when "Dan", "Daniel" | ||
| 2992 | print "Your name, it's Dan" | ||
| 2993 | else | ||
| 2994 | print "I don't know about you with name #{name}" | ||
| 2995 | ``` | ||
| 2996 | |||
| 2997 | </YueDisplay> | ||
| 2998 | |||
| 2999 | Klausa when pada switch bisa mencocokkan beberapa nilai dengan menuliskannya dipisah koma. | ||
| 3000 | |||
| 3001 | Switch juga bisa dipakai sebagai ekspresi; di sini kita dapat menetapkan hasil switch ke sebuah variabel: | ||
| 3002 | |||
| 3003 | ```yuescript | ||
| 3004 | b = 1 | ||
| 3005 | next_number = switch b | ||
| 3006 | when 1 | ||
| 3007 | 2 | ||
| 3008 | when 2 | ||
| 3009 | 3 | ||
| 3010 | else | ||
| 3011 | error "can't count that high!" | ||
| 3012 | ``` | ||
| 3013 | |||
| 3014 | <YueDisplay> | ||
| 3015 | |||
| 3016 | ```yue | ||
| 3017 | b = 1 | ||
| 3018 | next_number = switch b | ||
| 3019 | when 1 | ||
| 3020 | 2 | ||
| 3021 | when 2 | ||
| 3022 | 3 | ||
| 3023 | else | ||
| 3024 | error "can't count that high!" | ||
| 3025 | ``` | ||
| 3026 | |||
| 3027 | </YueDisplay> | ||
| 3028 | |||
| 3029 | Kita bisa memakai kata kunci `then` untuk menulis blok when switch pada satu baris. Tidak ada kata kunci tambahan yang dibutuhkan untuk menulis blok else pada satu baris. | ||
| 3030 | |||
| 3031 | ```yuescript | ||
| 3032 | msg = switch math.random(1, 5) | ||
| 3033 | when 1 then "you are lucky" | ||
| 3034 | when 2 then "you are almost lucky" | ||
| 3035 | else "not so lucky" | ||
| 3036 | ``` | ||
| 3037 | |||
| 3038 | <YueDisplay> | ||
| 3039 | |||
| 3040 | ```yue | ||
| 3041 | msg = switch math.random(1, 5) | ||
| 3042 | when 1 then "you are lucky" | ||
| 3043 | when 2 then "you are almost lucky" | ||
| 3044 | else "not so lucky" | ||
| 3045 | ``` | ||
| 3046 | |||
| 3047 | </YueDisplay> | ||
| 3048 | |||
| 3049 | Jika Anda ingin menulis kode dengan satu indentasi lebih sedikit saat menulis switch, Anda bisa menaruh klausa when pertama pada baris awal pernyataan, lalu semua klausa lain dapat ditulis dengan satu indentasi lebih sedikit. | ||
| 3050 | |||
| 3051 | ```yuescript | ||
| 3052 | switch math.random(1, 5) | ||
| 3053 | when 1 | ||
| 3054 | print "you are lucky" -- two indents | ||
| 3055 | else | ||
| 3056 | print "not so lucky" | ||
| 3057 | |||
| 3058 | switch math.random(1, 5) when 1 | ||
| 3059 | print "you are lucky" -- one indent | ||
| 3060 | else | ||
| 3061 | print "not so lucky" | ||
| 3062 | ``` | ||
| 3063 | |||
| 3064 | <YueDisplay> | ||
| 3065 | |||
| 3066 | ```yue | ||
| 3067 | switch math.random(1, 5) | ||
| 3068 | when 1 | ||
| 3069 | print "you are lucky" -- two indents | ||
| 3070 | else | ||
| 3071 | print "not so lucky" | ||
| 3072 | |||
| 3073 | switch math.random(1, 5) when 1 | ||
| 3074 | print "you are lucky" -- one indent | ||
| 3075 | else | ||
| 3076 | print "not so lucky" | ||
| 3077 | ``` | ||
| 3078 | |||
| 3079 | </YueDisplay> | ||
| 3080 | |||
| 3081 | Perlu dicatat urutan ekspresi perbandingan kasus. Ekspresi kasus berada di sisi kiri. Ini bisa berguna jika ekspresi kasus ingin mengganti cara perbandingan dengan mendefinisikan metamethod `eq`. | ||
| 3082 | |||
| 3083 | ## Pencocokan Tabel | ||
| 3084 | |||
| 3085 | Anda bisa melakukan pencocokan tabel dalam klausa when switch, jika tabel dapat didestrukturisasi oleh struktur tertentu dan mendapatkan nilai non-nil. | ||
| 3086 | |||
| 3087 | ```yuescript | ||
| 3088 | items = | ||
| 3089 | * x: 100 | ||
| 3090 | y: 200 | ||
| 3091 | * width: 300 | ||
| 3092 | height: 400 | ||
| 3093 | |||
| 3094 | for item in *items | ||
| 3095 | switch item | ||
| 3096 | when :x, :y | ||
| 3097 | print "Vec2 #{x}, #{y}" | ||
| 3098 | when :width, :height | ||
| 3099 | print "size #{width}, #{height}" | ||
| 3100 | ``` | ||
| 3101 | |||
| 3102 | <YueDisplay> | ||
| 3103 | |||
| 3104 | ```yue | ||
| 3105 | items = | ||
| 3106 | * x: 100 | ||
| 3107 | y: 200 | ||
| 3108 | * width: 300 | ||
| 3109 | height: 400 | ||
| 3110 | |||
| 3111 | for item in *items | ||
| 3112 | switch item | ||
| 3113 | when :x, :y | ||
| 3114 | print "Vec2 #{x}, #{y}" | ||
| 3115 | when :width, :height | ||
| 3116 | print "size #{width}, #{height}" | ||
| 3117 | ``` | ||
| 3118 | |||
| 3119 | </YueDisplay> | ||
| 3120 | |||
| 3121 | Anda dapat menggunakan nilai default untuk mendestrukturisasi tabel secara opsional pada beberapa field. | ||
| 3122 | |||
| 3123 | ```yuescript | ||
| 3124 | item = {} | ||
| 3125 | |||
| 3126 | {pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos') | ||
| 3127 | |||
| 3128 | switch item | ||
| 3129 | when {pos: {:x = 50, :y = 200}} | ||
| 3130 | print "Vec2 #{x}, #{y}" -- table destructuring will still pass | ||
| 3131 | ``` | ||
| 3132 | |||
| 3133 | <YueDisplay> | ||
| 3134 | |||
| 3135 | ```yue | ||
| 3136 | item = {} | ||
| 3137 | |||
| 3138 | {pos: {:x = 50, :y = 200}} = item -- get error: attempt to index a nil value (field 'pos') | ||
| 3139 | |||
| 3140 | switch item | ||
| 3141 | when {pos: {:x = 50, :y = 200}} | ||
| 3142 | print "Vec2 #{x}, #{y}" -- table destructuring will still pass | ||
| 3143 | ``` | ||
| 3144 | |||
| 3145 | </YueDisplay> | ||
| 3146 | |||
| 3147 | Anda juga bisa mencocokkan elemen array, field tabel, dan bahkan struktur bertingkat dengan literal array atau tabel. | ||
| 3148 | |||
| 3149 | Cocokkan terhadap elemen array. | ||
| 3150 | |||
| 3151 | ```yuescript | ||
| 3152 | switch tb | ||
| 3153 | when [1, 2, 3] | ||
| 3154 | print "1, 2, 3" | ||
| 3155 | when [1, b, 3] | ||
| 3156 | print "1, #{b}, 3" | ||
| 3157 | when [1, 2, b = 3] -- b has a default value | ||
| 3158 | print "1, 2, #{b}" | ||
| 3159 | ``` | ||
| 3160 | |||
| 3161 | <YueDisplay> | ||
| 3162 | |||
| 3163 | ```yue | ||
| 3164 | switch tb | ||
| 3165 | when [1, 2, 3] | ||
| 3166 | print "1, 2, 3" | ||
| 3167 | when [1, b, 3] | ||
| 3168 | print "1, #{b}, 3" | ||
| 3169 | when [1, 2, b = 3] -- b has a default value | ||
| 3170 | print "1, 2, #{b}" | ||
| 3171 | ``` | ||
| 3172 | |||
| 3173 | </YueDisplay> | ||
| 3174 | |||
| 3175 | Cocokkan terhadap field tabel dengan destrukturisasi. | ||
| 3176 | |||
| 3177 | ```yuescript | ||
| 3178 | switch tb | ||
| 3179 | when success: true, :result | ||
| 3180 | print "success", result | ||
| 3181 | when success: false | ||
| 3182 | print "failed", result | ||
| 3183 | else | ||
| 3184 | print "invalid" | ||
| 3185 | ``` | ||
| 3186 | |||
| 3187 | <YueDisplay> | ||
| 3188 | |||
| 3189 | ```yue | ||
| 3190 | switch tb | ||
| 3191 | when success: true, :result | ||
| 3192 | print "success", result | ||
| 3193 | when success: false | ||
| 3194 | print "failed", result | ||
| 3195 | else | ||
| 3196 | print "invalid" | ||
| 3197 | ``` | ||
| 3198 | |||
| 3199 | </YueDisplay> | ||
| 3200 | |||
| 3201 | Cocokkan terhadap struktur tabel bertingkat. | ||
| 3202 | |||
| 3203 | ```yuescript | ||
| 3204 | switch tb | ||
| 3205 | when data: {type: "success", :content} | ||
| 3206 | print "success", content | ||
| 3207 | when data: {type: "error", :content} | ||
| 3208 | print "failed", content | ||
| 3209 | else | ||
| 3210 | print "invalid" | ||
| 3211 | ``` | ||
| 3212 | |||
| 3213 | <YueDisplay> | ||
| 3214 | |||
| 3215 | ```yue | ||
| 3216 | switch tb | ||
| 3217 | when data: {type: "success", :content} | ||
| 3218 | print "success", content | ||
| 3219 | when data: {type: "error", :content} | ||
| 3220 | print "failed", content | ||
| 3221 | else | ||
| 3222 | print "invalid" | ||
| 3223 | ``` | ||
| 3224 | |||
| 3225 | </YueDisplay> | ||
| 3226 | |||
| 3227 | Cocokkan terhadap array dari tabel. | ||
| 3228 | |||
| 3229 | ```yuescript | ||
| 3230 | switch tb | ||
| 3231 | when [ | ||
| 3232 | {a: 1, b: 2} | ||
| 3233 | {a: 3, b: 4} | ||
| 3234 | {a: 5, b: 6} | ||
| 3235 | fourth | ||
| 3236 | ] | ||
| 3237 | print "matched", fourth | ||
| 3238 | ``` | ||
| 3239 | |||
| 3240 | <YueDisplay> | ||
| 3241 | |||
| 3242 | ```yue | ||
| 3243 | switch tb | ||
| 3244 | when [ | ||
| 3245 | {a: 1, b: 2} | ||
| 3246 | {a: 3, b: 4} | ||
| 3247 | {a: 5, b: 6} | ||
| 3248 | fourth | ||
| 3249 | ] | ||
| 3250 | print "matched", fourth | ||
| 3251 | ``` | ||
| 3252 | |||
| 3253 | </YueDisplay> | ||
| 3254 | |||
| 3255 | Cocokkan terhadap daftar dan tangkap rentang elemen. | ||
| 3256 | |||
| 3257 | ```yuescript | ||
| 3258 | segments = ["admin", "users", "logs", "view"] | ||
| 3259 | switch segments | ||
| 3260 | when [...groups, resource, action] | ||
| 3261 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3262 | print "Resource:", resource -- prints: "logs" | ||
| 3263 | print "Action:", action -- prints: "view" | ||
| 3264 | ``` | ||
| 3265 | |||
| 3266 | <YueDisplay> | ||
| 3267 | |||
| 3268 | ```yue | ||
| 3269 | segments = ["admin", "users", "logs", "view"] | ||
| 3270 | switch segments | ||
| 3271 | when [...groups, resource, action] | ||
| 3272 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3273 | print "Resource:", resource -- prints: "logs" | ||
| 3274 | print "Action:", action -- prints: "view" | ||
| 3275 | ``` | ||
| 3276 | |||
| 3277 | </YueDisplay> | ||
| 3278 | |||
| 3279 | # Perulangan While | ||
| 3280 | |||
| 3281 | Perulangan while juga memiliki empat variasi: | ||
| 3282 | |||
| 3283 | ```yuescript | ||
| 3284 | i = 10 | ||
| 3285 | while i > 0 | ||
| 3286 | print i | ||
| 3287 | i -= 1 | ||
| 3288 | |||
| 3289 | while running == true do my_function! | ||
| 3290 | ``` | ||
| 3291 | |||
| 3292 | <YueDisplay> | ||
| 3293 | |||
| 3294 | ```yue | ||
| 3295 | i = 10 | ||
| 3296 | while i > 0 | ||
| 3297 | print i | ||
| 3298 | i -= 1 | ||
| 3299 | |||
| 3300 | while running == true do my_function! | ||
| 3301 | ``` | ||
| 3302 | |||
| 3303 | </YueDisplay> | ||
| 3304 | |||
| 3305 | ```yuescript | ||
| 3306 | i = 10 | ||
| 3307 | until i == 0 | ||
| 3308 | print i | ||
| 3309 | i -= 1 | ||
| 3310 | |||
| 3311 | until running == false do my_function! | ||
| 3312 | ``` | ||
| 3313 | |||
| 3314 | <YueDisplay> | ||
| 3315 | |||
| 3316 | ```yue | ||
| 3317 | i = 10 | ||
| 3318 | until i == 0 | ||
| 3319 | print i | ||
| 3320 | i -= 1 | ||
| 3321 | until running == false do my_function! | ||
| 3322 | ``` | ||
| 3323 | |||
| 3324 | </YueDisplay> | ||
| 3325 | |||
| 3326 | Seperti loop for, loop while juga bisa digunakan sebagai ekspresi. Ekspresi `while` dan `until` mendukung `break` dengan banyak nilai. | ||
| 3327 | |||
| 3328 | ```yuescript | ||
| 3329 | value, doubled = while true | ||
| 3330 | n = get_next! | ||
| 3331 | break n, n * 2 if n > 10 | ||
| 3332 | ``` | ||
| 3333 | |||
| 3334 | <YueDisplay> | ||
| 3335 | |||
| 3336 | ```yue | ||
| 3337 | value, doubled = while true | ||
| 3338 | n = get_next! | ||
| 3339 | break n, n * 2 if n > 10 | ||
| 3340 | ``` | ||
| 3341 | |||
| 3342 | </YueDisplay> | ||
| 3343 | |||
| 3344 | Selain itu, agar sebuah fungsi mengembalikan nilai akumulasi dari loop while, pernyataannya harus di-return secara eksplisit. | ||
| 3345 | |||
| 3346 | ## Repeat Loop | ||
| 3347 | |||
| 3348 | Loop repeat berasal dari Lua: | ||
| 3349 | |||
| 3350 | ```yuescript | ||
| 3351 | i = 10 | ||
| 3352 | repeat | ||
| 3353 | print i | ||
| 3354 | i -= 1 | ||
| 3355 | until i == 0 | ||
| 3356 | ``` | ||
| 3357 | |||
| 3358 | <YueDisplay> | ||
| 3359 | |||
| 3360 | ```yue | ||
| 3361 | i = 10 | ||
| 3362 | repeat | ||
| 3363 | print i | ||
| 3364 | i -= 1 | ||
| 3365 | until i == 0 | ||
| 3366 | ``` | ||
| 3367 | |||
| 3368 | </YueDisplay> | ||
| 3369 | |||
| 3370 | Ekspresi `repeat` juga mendukung `break` dengan banyak nilai: | ||
| 3371 | |||
| 3372 | ```yuescript | ||
| 3373 | i = 1 | ||
| 3374 | value, scaled = repeat | ||
| 3375 | break i, i * 100 if i > 3 | ||
| 3376 | i += 1 | ||
| 3377 | until false | ||
| 3378 | ``` | ||
| 3379 | |||
| 3380 | <YueDisplay> | ||
| 3381 | |||
| 3382 | ```yue | ||
| 3383 | i = 1 | ||
| 3384 | value, scaled = repeat | ||
| 3385 | break i, i * 100 if i > 3 | ||
| 3386 | i += 1 | ||
| 3387 | until false | ||
| 3388 | ``` | ||
| 3389 | |||
| 3390 | </YueDisplay> | ||
| 3391 | |||
| 3392 | # Stub Fungsi | ||
| 3393 | |||
| 3394 | Sering kali fungsi dari sebuah objek diteruskan sebagai nilai, misalnya meneruskan method instance ke fungsi lain sebagai callback. Jika fungsi mengharapkan objek yang dioperasikan sebagai argumen pertama, maka Anda harus menggabungkan objek tersebut dengan fungsi agar dapat dipanggil dengan benar. | ||
| 3395 | |||
| 3396 | Sintaks stub fungsi adalah singkatan untuk membuat fungsi closure baru yang menggabungkan objek dan fungsi. Fungsi baru ini memanggil fungsi yang dibungkus dalam konteks objek yang benar. | ||
| 3397 | |||
| 3398 | Sintaksnya sama seperti memanggil method instance dengan operator `\`, tetapi tanpa menyediakan daftar argumen. | ||
| 3399 | |||
| 3400 | ```yuescript | ||
| 3401 | my_object = { | ||
| 3402 | value: 1000 | ||
| 3403 | write: => print "the value:", @value | ||
| 3404 | } | ||
| 3405 | |||
| 3406 | run_callback = (func) -> | ||
| 3407 | print "running callback..." | ||
| 3408 | func! | ||
| 3409 | |||
| 3410 | -- ini tidak akan berfungsi: | ||
| 3411 | -- fungsi tidak memiliki referensi ke my_object | ||
| 3412 | run_callback my_object.write | ||
| 3413 | |||
| 3414 | -- sintaks stub fungsi | ||
| 3415 | -- memungkinkan kita membundel objek ke fungsi baru | ||
| 3416 | run_callback my_object\write | ||
| 3417 | ``` | ||
| 3418 | |||
| 3419 | <YueDisplay> | ||
| 3420 | |||
| 3421 | ```yue | ||
| 3422 | my_object = { | ||
| 3423 | value: 1000 | ||
| 3424 | write: => print "the value:", @value | ||
| 3425 | } | ||
| 3426 | |||
| 3427 | run_callback = (func) -> | ||
| 3428 | print "running callback..." | ||
| 3429 | func! | ||
| 3430 | |||
| 3431 | -- ini tidak akan berfungsi: | ||
| 3432 | -- fungsi tidak memiliki referensi ke my_object | ||
| 3433 | run_callback my_object.write | ||
| 3434 | |||
| 3435 | -- sintaks stub fungsi | ||
| 3436 | -- memungkinkan kita membundel objek ke fungsi baru | ||
| 3437 | run_callback my_object\write | ||
| 3438 | ``` | ||
| 3439 | |||
| 3440 | </YueDisplay> | ||
| 3441 | |||
| 3442 | # Backcall | ||
| 3443 | |||
| 3444 | Backcall digunakan untuk meratakan callback yang bersarang. Backcall didefinisikan menggunakan panah yang mengarah ke kiri sebagai parameter terakhir secara default yang akan mengisi pemanggilan fungsi. Semua sintaks pada dasarnya sama seperti fungsi panah biasa, kecuali arahnya berlawanan dan badan fungsi tidak memerlukan indentasi. | ||
| 3445 | |||
| 3446 | ```yuescript | ||
| 3447 | x <- f | ||
| 3448 | print "hello" .. x | ||
| 3449 | ``` | ||
| 3450 | |||
| 3451 | <YueDisplay> | ||
| 3452 | |||
| 3453 | ```yue | ||
| 3454 | x <- f | ||
| 3455 | print "hello" .. x | ||
| 3456 | ``` | ||
| 3457 | |||
| 3458 | </YueDisplay> | ||
| 3459 | |||
| 3460 | Fungsi panah tebal juga tersedia. | ||
| 3461 | |||
| 3462 | ```yuescript | ||
| 3463 | <= f | ||
| 3464 | print @value | ||
| 3465 | ``` | ||
| 3466 | |||
| 3467 | <YueDisplay> | ||
| 3468 | |||
| 3469 | ```yue | ||
| 3470 | <= f | ||
| 3471 | print @value | ||
| 3472 | ``` | ||
| 3473 | |||
| 3474 | </YueDisplay> | ||
| 3475 | |||
| 3476 | Anda dapat menentukan placeholder untuk posisi fungsi backcall sebagai parameter. | ||
| 3477 | |||
| 3478 | ```yuescript | ||
| 3479 | (x) <- map _, [1, 2, 3] | ||
| 3480 | x * 2 | ||
| 3481 | ``` | ||
| 3482 | |||
| 3483 | <YueDisplay> | ||
| 3484 | |||
| 3485 | ```yue | ||
| 3486 | (x) <- map _, [1, 2, 3] | ||
| 3487 | x * 2 | ||
| 3488 | ``` | ||
| 3489 | |||
| 3490 | </YueDisplay> | ||
| 3491 | |||
| 3492 | Jika Anda ingin menulis kode lanjutan setelah backcall, Anda dapat memisahkannya dengan pernyataan `do`. Tanda kurung dapat dihilangkan untuk fungsi panah non-tebal. | ||
| 3493 | |||
| 3494 | ```yuescript | ||
| 3495 | result, msg = do | ||
| 3496 | data <- readAsync "filename.txt" | ||
| 3497 | print data | ||
| 3498 | info <- processAsync data | ||
| 3499 | check info | ||
| 3500 | print result, msg | ||
| 3501 | ``` | ||
| 3502 | |||
| 3503 | <YueDisplay> | ||
| 3504 | |||
| 3505 | ```yue | ||
| 3506 | result, msg = do | ||
| 3507 | data <- readAsync "filename.txt" | ||
| 3508 | print data | ||
| 3509 | info <- processAsync data | ||
| 3510 | check info | ||
| 3511 | print result, msg | ||
| 3512 | ``` | ||
| 3513 | |||
| 3514 | </YueDisplay> | ||
| 3515 | |||
| 3516 | # Literal Fungsi | ||
| 3517 | |||
| 3518 | Semua fungsi dibuat menggunakan ekspresi fungsi. Fungsi sederhana ditandai dengan panah: **->**. | ||
| 3519 | |||
| 3520 | ```yuescript | ||
| 3521 | my_function = -> | ||
| 3522 | my_function() -- memanggil fungsi kosong | ||
| 3523 | ``` | ||
| 3524 | |||
| 3525 | <YueDisplay> | ||
| 3526 | |||
| 3527 | ```yue | ||
| 3528 | my_function = -> | ||
| 3529 | my_function() -- memanggil fungsi kosong | ||
| 3530 | ``` | ||
| 3531 | |||
| 3532 | </YueDisplay> | ||
| 3533 | |||
| 3534 | Badan fungsi bisa berupa satu pernyataan yang ditulis langsung setelah panah, atau berupa serangkaian pernyataan yang diindentasi di baris berikutnya: | ||
| 3535 | |||
| 3536 | ```yuescript | ||
| 3537 | func_a = -> print "hello world" | ||
| 3538 | |||
| 3539 | func_b = -> | ||
| 3540 | value = 100 | ||
| 3541 | print "The value:", value | ||
| 3542 | ``` | ||
| 3543 | |||
| 3544 | <YueDisplay> | ||
| 3545 | |||
| 3546 | ```yue | ||
| 3547 | func_a = -> print "hello world" | ||
| 3548 | |||
| 3549 | func_b = -> | ||
| 3550 | value = 100 | ||
| 3551 | print "The value:", value | ||
| 3552 | ``` | ||
| 3553 | |||
| 3554 | </YueDisplay> | ||
| 3555 | |||
| 3556 | Jika fungsi tidak memiliki argumen, ia dapat dipanggil menggunakan operator `!`, sebagai ganti tanda kurung kosong. Pemanggilan `!` adalah cara yang disarankan untuk memanggil fungsi tanpa argumen. | ||
| 3557 | |||
| 3558 | ```yuescript | ||
| 3559 | func_a! | ||
| 3560 | func_b() | ||
| 3561 | ``` | ||
| 3562 | |||
| 3563 | <YueDisplay> | ||
| 3564 | |||
| 3565 | ```yue | ||
| 3566 | func_a! | ||
| 3567 | func_b() | ||
| 3568 | ``` | ||
| 3569 | |||
| 3570 | </YueDisplay> | ||
| 3571 | |||
| 3572 | Fungsi dengan argumen dapat dibuat dengan menaruh daftar nama argumen dalam tanda kurung sebelum panah: | ||
| 3573 | |||
| 3574 | ```yuescript | ||
| 3575 | sum = (x, y) -> print "sum", x + y | ||
| 3576 | ``` | ||
| 3577 | |||
| 3578 | <YueDisplay> | ||
| 3579 | |||
| 3580 | ```yue | ||
| 3581 | sum = (x, y) -> print "sum", x + y | ||
| 3582 | ``` | ||
| 3583 | |||
| 3584 | </YueDisplay> | ||
| 3585 | |||
| 3586 | Fungsi dapat dipanggil dengan menuliskan argumen setelah nama ekspresi yang mengevaluasi ke fungsi. Saat merangkai pemanggilan fungsi, argumen diterapkan ke fungsi terdekat di sebelah kiri. | ||
| 3587 | |||
| 3588 | ```yuescript | ||
| 3589 | sum 10, 20 | ||
| 3590 | print sum 10, 20 | ||
| 3591 | |||
| 3592 | a b c "a", "b", "c" | ||
| 3593 | ``` | ||
| 3594 | |||
| 3595 | <YueDisplay> | ||
| 3596 | |||
| 3597 | ```yue | ||
| 3598 | sum 10, 20 | ||
| 3599 | print sum 10, 20 | ||
| 3600 | |||
| 3601 | a b c "a", "b", "c" | ||
| 3602 | ``` | ||
| 3603 | |||
| 3604 | </YueDisplay> | ||
| 3605 | |||
| 3606 | Untuk menghindari ambiguitas saat memanggil fungsi, tanda kurung juga bisa digunakan untuk mengelilingi argumen. Ini diperlukan di sini agar argumen yang tepat dikirim ke fungsi yang tepat. | ||
| 3607 | |||
| 3608 | ```yuescript | ||
| 3609 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3610 | ``` | ||
| 3611 | |||
| 3612 | <YueDisplay> | ||
| 3613 | |||
| 3614 | ```yue | ||
| 3615 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3616 | ``` | ||
| 3617 | |||
| 3618 | </YueDisplay> | ||
| 3619 | |||
| 3620 | Tidak boleh ada spasi antara tanda kurung buka dan nama fungsi. | ||
| 3621 | |||
| 3622 | Fungsi akan memaksa pernyataan terakhir di badannya menjadi pernyataan return, ini disebut return implisit: | ||
| 3623 | |||
| 3624 | ```yuescript | ||
| 3625 | sum = (x, y) -> x + y | ||
| 3626 | print "The sum is ", sum 10, 20 | ||
| 3627 | ``` | ||
| 3628 | |||
| 3629 | <YueDisplay> | ||
| 3630 | |||
| 3631 | ```yue | ||
| 3632 | sum = (x, y) -> x + y | ||
| 3633 | print "The sum is ", sum 10, 20 | ||
| 3634 | ``` | ||
| 3635 | |||
| 3636 | </YueDisplay> | ||
| 3637 | |||
| 3638 | Dan jika Anda perlu return secara eksplisit, Anda bisa menggunakan kata kunci `return`: | ||
| 3639 | |||
| 3640 | ```yuescript | ||
| 3641 | sum = (x, y) -> return x + y | ||
| 3642 | ``` | ||
| 3643 | |||
| 3644 | <YueDisplay> | ||
| 3645 | |||
| 3646 | ```yue | ||
| 3647 | sum = (x, y) -> return x + y | ||
| 3648 | ``` | ||
| 3649 | |||
| 3650 | </YueDisplay> | ||
| 3651 | |||
| 3652 | Seperti di Lua, fungsi dapat mengembalikan beberapa nilai. Pernyataan terakhir harus berupa daftar nilai yang dipisahkan koma: | ||
| 3653 | |||
| 3654 | ```yuescript | ||
| 3655 | mystery = (x, y) -> x + y, x - y | ||
| 3656 | a, b = mystery 10, 20 | ||
| 3657 | ``` | ||
| 3658 | |||
| 3659 | <YueDisplay> | ||
| 3660 | |||
| 3661 | ```yue | ||
| 3662 | mystery = (x, y) -> x + y, x - y | ||
| 3663 | a, b = mystery 10, 20 | ||
| 3664 | ``` | ||
| 3665 | |||
| 3666 | </YueDisplay> | ||
| 3667 | |||
| 3668 | ## Panah Tebal | ||
| 3669 | |||
| 3670 | Karena sudah menjadi idiom di Lua untuk mengirim objek sebagai argumen pertama saat memanggil method, disediakan sintaks khusus untuk membuat fungsi yang otomatis menyertakan argumen `self`. | ||
| 3671 | |||
| 3672 | ```yuescript | ||
| 3673 | func = (num) => @value + num | ||
| 3674 | ``` | ||
| 3675 | |||
| 3676 | <YueDisplay> | ||
| 3677 | |||
| 3678 | ```yue | ||
| 3679 | func = (num) => @value + num | ||
| 3680 | ``` | ||
| 3681 | |||
| 3682 | </YueDisplay> | ||
| 3683 | |||
| 3684 | ## Nilai Default Argumen | ||
| 3685 | |||
| 3686 | Dimungkinkan untuk menyediakan nilai default bagi argumen fungsi. Argumen dianggap kosong jika nilainya nil. Argumen nil yang memiliki nilai default akan diganti sebelum badan fungsi dijalankan. | ||
| 3687 | |||
| 3688 | ```yuescript | ||
| 3689 | my_function = (name = "something", height = 100) -> | ||
| 3690 | print "Hello I am", name | ||
| 3691 | print "My height is", height | ||
| 3692 | ``` | ||
| 3693 | |||
| 3694 | <YueDisplay> | ||
| 3695 | |||
| 3696 | ```yue | ||
| 3697 | my_function = (name = "something", height = 100) -> | ||
| 3698 | print "Hello I am", name | ||
| 3699 | print "My height is", height | ||
| 3700 | ``` | ||
| 3701 | |||
| 3702 | </YueDisplay> | ||
| 3703 | |||
| 3704 | Ekspresi nilai default argumen dievaluasi di dalam badan fungsi sesuai urutan deklarasi argumen. Karena itu, nilai default dapat mengakses argumen yang dideklarasikan sebelumnya. | ||
| 3705 | |||
| 3706 | ```yuescript | ||
| 3707 | some_args = (x = 100, y = x + 1000) -> | ||
| 3708 | print x + y | ||
| 3709 | ``` | ||
| 3710 | |||
| 3711 | <YueDisplay> | ||
| 3712 | |||
| 3713 | ```yue | ||
| 3714 | some_args = (x = 100, y = x + 1000) -> | ||
| 3715 | print x + y | ||
| 3716 | ``` | ||
| 3717 | |||
| 3718 | </YueDisplay> | ||
| 3719 | |||
| 3720 | ## Pertimbangan | ||
| 3721 | |||
| 3722 | Karena cara pemanggilan fungsi tanpa tanda kurung yang ekspresif, beberapa pembatasan harus diterapkan untuk menghindari ambiguitas parsing yang melibatkan spasi. | ||
| 3723 | |||
| 3724 | Tanda minus memiliki dua peran, operator negasi unari dan operator pengurangan biner. Perhatikan bagaimana contoh berikut dikompilasi: | ||
| 3725 | |||
| 3726 | ```yuescript | ||
| 3727 | a = x - 10 | ||
| 3728 | b = x-10 | ||
| 3729 | c = x -y | ||
| 3730 | d = x- z | ||
| 3731 | ``` | ||
| 3732 | |||
| 3733 | <YueDisplay> | ||
| 3734 | |||
| 3735 | ```yue | ||
| 3736 | a = x - 10 | ||
| 3737 | b = x-10 | ||
| 3738 | c = x -y | ||
| 3739 | d = x- z | ||
| 3740 | ``` | ||
| 3741 | |||
| 3742 | </YueDisplay> | ||
| 3743 | |||
| 3744 | Prioritas argumen pertama pada pemanggilan fungsi dapat dikendalikan menggunakan spasi jika argumennya adalah literal string. Di Lua, sudah umum untuk menghilangkan tanda kurung saat memanggil fungsi dengan satu literal string atau tabel. | ||
| 3745 | |||
| 3746 | Ketika tidak ada spasi antara variabel dan literal string, pemanggilan fungsi akan memiliki prioritas atas ekspresi yang mengikuti. Tidak ada argumen lain yang dapat diberikan pada fungsi ketika dipanggil dengan cara ini. | ||
| 3747 | |||
| 3748 | Ketika ada spasi setelah variabel dan literal string, pemanggilan fungsi bertindak seperti yang dijelaskan di atas. Literal string menjadi milik ekspresi berikutnya (jika ada), yang berfungsi sebagai daftar argumen. | ||
| 3749 | |||
| 3750 | ```yuescript | ||
| 3751 | x = func"hello" + 100 | ||
| 3752 | y = func "hello" + 100 | ||
| 3753 | ``` | ||
| 3754 | |||
| 3755 | <YueDisplay> | ||
| 3756 | |||
| 3757 | ```yue | ||
| 3758 | x = func"hello" + 100 | ||
| 3759 | y = func "hello" + 100 | ||
| 3760 | ``` | ||
| 3761 | |||
| 3762 | </YueDisplay> | ||
| 3763 | |||
| 3764 | ## Argumen Multi-baris | ||
| 3765 | |||
| 3766 | Saat memanggil fungsi yang menerima banyak argumen, akan lebih nyaman untuk memecah daftar argumen menjadi beberapa baris. Karena sifat bahasa yang peka terhadap spasi, perlu hati-hati saat memecah daftar argumen. | ||
| 3767 | |||
| 3768 | Jika daftar argumen akan dilanjutkan ke baris berikutnya, baris saat ini harus diakhiri dengan koma. Dan baris berikutnya harus lebih terindentasi daripada indentasi saat ini. Setelah diindentasi, semua baris argumen lainnya harus berada pada tingkat indentasi yang sama agar menjadi bagian dari daftar argumen. | ||
| 3769 | |||
| 3770 | ```yuescript | ||
| 3771 | my_func 5, 4, 3, | ||
| 3772 | 8, 9, 10 | ||
| 3773 | |||
| 3774 | cool_func 1, 2, | ||
| 3775 | 3, 4, | ||
| 3776 | 5, 6, | ||
| 3777 | 7, 8 | ||
| 3778 | ``` | ||
| 3779 | |||
| 3780 | <YueDisplay> | ||
| 3781 | |||
| 3782 | ```yue | ||
| 3783 | my_func 5, 4, 3, | ||
| 3784 | 8, 9, 10 | ||
| 3785 | |||
| 3786 | cool_func 1, 2, | ||
| 3787 | 3, 4, | ||
| 3788 | 5, 6, | ||
| 3789 | 7, 8 | ||
| 3790 | ``` | ||
| 3791 | |||
| 3792 | </YueDisplay> | ||
| 3793 | |||
| 3794 | Jenis pemanggilan ini dapat dinest. Tingkat indentasi digunakan untuk menentukan argumen milik fungsi yang mana. | ||
| 3795 | |||
| 3796 | ```yuescript | ||
| 3797 | my_func 5, 6, 7, | ||
| 3798 | 6, another_func 6, 7, 8, | ||
| 3799 | 9, 1, 2, | ||
| 3800 | 5, 4 | ||
| 3801 | ``` | ||
| 3802 | |||
| 3803 | <YueDisplay> | ||
| 3804 | |||
| 3805 | ```yue | ||
| 3806 | my_func 5, 6, 7, | ||
| 3807 | 6, another_func 6, 7, 8, | ||
| 3808 | 9, 1, 2, | ||
| 3809 | 5, 4 | ||
| 3810 | ``` | ||
| 3811 | |||
| 3812 | </YueDisplay> | ||
| 3813 | |||
| 3814 | Karena tabel juga menggunakan koma sebagai pemisah, sintaks indentasi ini membantu agar nilai menjadi bagian dari daftar argumen, bukan bagian dari tabel. | ||
| 3815 | |||
| 3816 | ```yuescript | ||
| 3817 | x = [ | ||
| 3818 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3819 | 5, 6, | ||
| 3820 | 8, 9, 10 | ||
| 3821 | ] | ||
| 3822 | ``` | ||
| 3823 | |||
| 3824 | <YueDisplay> | ||
| 3825 | |||
| 3826 | ```yue | ||
| 3827 | x = [ | ||
| 3828 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3829 | 5, 6, | ||
| 3830 | 8, 9, 10 | ||
| 3831 | ] | ||
| 3832 | ``` | ||
| 3833 | |||
| 3834 | </YueDisplay> | ||
| 3835 | |||
| 3836 | Meskipun jarang, perhatikan bahwa kita bisa memberikan indentasi yang lebih dalam untuk argumen fungsi jika kita tahu akan menggunakan indentasi yang lebih dangkal di bagian selanjutnya. | ||
| 3837 | |||
| 3838 | ```yuescript | ||
| 3839 | y = [ my_func 1, 2, 3, | ||
| 3840 | 4, 5, | ||
| 3841 | 5, 6, 7 | ||
| 3842 | ] | ||
| 3843 | ``` | ||
| 3844 | |||
| 3845 | <YueDisplay> | ||
| 3846 | |||
| 3847 | ```yue | ||
| 3848 | y = [ my_func 1, 2, 3, | ||
| 3849 | 4, 5, | ||
| 3850 | 5, 6, 7 | ||
| 3851 | ] | ||
| 3852 | ``` | ||
| 3853 | |||
| 3854 | </YueDisplay> | ||
| 3855 | |||
| 3856 | Hal yang sama juga dapat dilakukan pada pernyataan tingkat blok lainnya seperti kondisional. Kita bisa menggunakan tingkat indentasi untuk menentukan nilai milik pernyataan apa: | ||
| 3857 | |||
| 3858 | ```yuescript | ||
| 3859 | if func 1, 2, 3, | ||
| 3860 | "hello", | ||
| 3861 | "world" | ||
| 3862 | print "hello" | ||
| 3863 | print "I am inside if" | ||
| 3864 | |||
| 3865 | if func 1, 2, 3, | ||
| 3866 | "hello", | ||
| 3867 | "world" | ||
| 3868 | print "hello" | ||
| 3869 | print "I am inside if" | ||
| 3870 | ``` | ||
| 3871 | |||
| 3872 | <YueDisplay> | ||
| 3873 | |||
| 3874 | ```yue | ||
| 3875 | if func 1, 2, 3, | ||
| 3876 | "hello", | ||
| 3877 | "world" | ||
| 3878 | print "hello" | ||
| 3879 | print "I am inside if" | ||
| 3880 | |||
| 3881 | if func 1, 2, 3, | ||
| 3882 | "hello", | ||
| 3883 | "world" | ||
| 3884 | print "hello" | ||
| 3885 | print "I am inside if" | ||
| 3886 | ``` | ||
| 3887 | |||
| 3888 | </YueDisplay> | ||
| 3889 | |||
| 3890 | ## Destrukturisasi Parameter | ||
| 3891 | |||
| 3892 | YueScript kini mendukung destrukturisasi parameter fungsi ketika argumen berupa objek. Dua bentuk destrukturisasi literal tabel tersedia: | ||
| 3893 | |||
| 3894 | - **Literal berkurung kurawal/parameter objek**, memungkinkan nilai default opsional ketika field hilang (misalnya, `{:a, :b}`, `{a: a1 = 123}`). | ||
| 3895 | |||
| 3896 | - **Sintaks tabel sederhana tanpa pembungkus**, dimulai dengan urutan key-value atau binding singkat dan berlanjut sampai ekspresi lain menghentikannya (misalnya, `:a, b: b1, :c`). Bentuk ini mengekstrak beberapa field dari objek yang sama. | ||
| 3897 | |||
| 3898 | ```yuescript | ||
| 3899 | f1 = (:a, :b, :c) -> | ||
| 3900 | print a, b, c | ||
| 3901 | |||
| 3902 | f1 a: 1, b: "2", c: {} | ||
| 3903 | |||
| 3904 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3905 | print a1, b, c | ||
| 3906 | |||
| 3907 | arg1 = {a: 0} | ||
| 3908 | f2 arg1, arg2 | ||
| 3909 | ``` | ||
| 3910 | |||
| 3911 | <YueDisplay> | ||
| 3912 | |||
| 3913 | ```yue | ||
| 3914 | f1 = (:a, :b, :c) -> | ||
| 3915 | print a, b, c | ||
| 3916 | |||
| 3917 | f1 a: 1, b: "2", c: {} | ||
| 3918 | |||
| 3919 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3920 | print a1, b, c | ||
| 3921 | |||
| 3922 | arg1 = {a: 0} | ||
| 3923 | f2 arg1, arg2 | ||
| 3924 | ``` | ||
| 3925 | |||
| 3926 | </YueDisplay> | ||
| 3927 | |||
| 3928 | ## Ekspresi Return Berawalan | ||
| 3929 | |||
| 3930 | Saat bekerja dengan badan fungsi yang sangat bertingkat, menjaga keterbacaan dan konsistensi nilai return bisa terasa melelahkan. Untuk mengatasinya, YueScript memperkenalkan sintaks **Ekspresi Return Berawalan**. Bentuknya sebagai berikut: | ||
| 3931 | |||
| 3932 | ```yuescript | ||
| 3933 | findFirstEven = (list): nil -> | ||
| 3934 | for item in *list | ||
| 3935 | if type(item) == "table" | ||
| 3936 | for sub in *item | ||
| 3937 | if sub % 2 == 0 | ||
| 3938 | return sub | ||
| 3939 | ``` | ||
| 3940 | |||
| 3941 | <YueDisplay> | ||
| 3942 | |||
| 3943 | ```yue | ||
| 3944 | findFirstEven = (list): nil -> | ||
| 3945 | for item in *list | ||
| 3946 | if type(item) == "table" | ||
| 3947 | for sub in *item | ||
| 3948 | if sub % 2 == 0 | ||
| 3949 | return sub | ||
| 3950 | ``` | ||
| 3951 | |||
| 3952 | </YueDisplay> | ||
| 3953 | |||
| 3954 | Ini setara dengan: | ||
| 3955 | |||
| 3956 | ```yuescript | ||
| 3957 | findFirstEven = (list) -> | ||
| 3958 | for item in *list | ||
| 3959 | if type(item) == "table" | ||
| 3960 | for sub in *item | ||
| 3961 | if sub % 2 == 0 | ||
| 3962 | return sub | ||
| 3963 | nil | ||
| 3964 | ``` | ||
| 3965 | |||
| 3966 | <YueDisplay> | ||
| 3967 | |||
| 3968 | ```yue | ||
| 3969 | findFirstEven = (list) -> | ||
| 3970 | for item in *list | ||
| 3971 | if type(item) == "table" | ||
| 3972 | for sub in *item | ||
| 3973 | if sub % 2 == 0 | ||
| 3974 | return sub | ||
| 3975 | nil | ||
| 3976 | ``` | ||
| 3977 | |||
| 3978 | </YueDisplay> | ||
| 3979 | |||
| 3980 | Satu-satunya perbedaan adalah Anda dapat memindahkan ekspresi return terakhir sebelum token `->` atau `=>` untuk menunjukkan nilai return implisit fungsi sebagai pernyataan terakhir. Dengan cara ini, bahkan pada fungsi dengan banyak loop bertingkat atau cabang kondisional, Anda tidak lagi perlu menulis ekspresi return di akhir badan fungsi, sehingga struktur logika menjadi lebih lurus dan mudah diikuti. | ||
| 3981 | |||
| 3982 | ## Varargs Bernama | ||
| 3983 | |||
| 3984 | Anda dapat menggunakan sintaks `(...t) ->` untuk otomatis menyimpan varargs ke tabel bernama. Tabel ini berisi semua argumen yang diteruskan (termasuk nilai `nil`), dan field `n` pada tabel menyimpan jumlah argumen yang benar-benar diteruskan (termasuk nilai `nil`). | ||
| 3985 | |||
| 3986 | ```yuescript | ||
| 3987 | f = (...t) -> | ||
| 3988 | print "argument count:", t.n | ||
| 3989 | print "table length:", #t | ||
| 3990 | for i = 1, t.n | ||
| 3991 | print t[i] | ||
| 3992 | |||
| 3993 | f 1, 2, 3 | ||
| 3994 | f "a", "b", "c", "d" | ||
| 3995 | f! | ||
| 3996 | |||
| 3997 | -- Menangani kasus dengan nilai nil | ||
| 3998 | process = (...args) -> | ||
| 3999 | sum = 0 | ||
| 4000 | for i = 1, args.n | ||
| 4001 | if args[i] != nil and type(args[i]) == "number" | ||
| 4002 | sum += args[i] | ||
| 4003 | sum | ||
| 4004 | |||
| 4005 | process 1, nil, 3, nil, 5 | ||
| 4006 | ``` | ||
| 4007 | |||
| 4008 | <YueDisplay> | ||
| 4009 | |||
| 4010 | ```yue | ||
| 4011 | f = (...t) -> | ||
| 4012 | print "argument count:", t.n | ||
| 4013 | print "table length:", #t | ||
| 4014 | for i = 1, t.n | ||
| 4015 | print t[i] | ||
| 4016 | |||
| 4017 | f 1, 2, 3 | ||
| 4018 | f "a", "b", "c", "d" | ||
| 4019 | f! | ||
| 4020 | |||
| 4021 | -- Menangani kasus dengan nilai nil | ||
| 4022 | process = (...args) -> | ||
| 4023 | sum = 0 | ||
| 4024 | for i = 1, args.n | ||
| 4025 | if args[i] != nil and type(args[i]) == "number" | ||
| 4026 | sum += args[i] | ||
| 4027 | sum | ||
| 4028 | |||
| 4029 | process 1, nil, 3, nil, 5 | ||
| 4030 | ``` | ||
| 4031 | |||
| 4032 | </YueDisplay> | ||
| 4033 | |||
| 4034 | # Spasi Kosong | ||
| 4035 | |||
| 4036 | YueScript adalah bahasa yang peka terhadap spasi. Anda harus menulis beberapa blok kode dengan indentasi yang sama menggunakan spasi **' '** atau tab **'\t'** seperti badan fungsi, daftar nilai, dan beberapa blok kontrol. Ekspresi yang mengandung spasi berbeda dapat bermakna berbeda. Tab diperlakukan seperti 4 spasi, tetapi sebaiknya jangan mencampur penggunaan spasi dan tab. | ||
| 4037 | |||
| 4038 | ## Pemisah Pernyataan | ||
| 4039 | |||
| 4040 | Sebuah pernyataan biasanya berakhir pada pergantian baris. Anda juga bisa memakai titik koma `;` untuk mengakhiri pernyataan secara eksplisit, yang memungkinkan menulis beberapa pernyataan pada satu baris: | ||
| 4041 | |||
| 4042 | ```yuescript | ||
| 4043 | a = 1; b = 2; print a + b | ||
| 4044 | ``` | ||
| 4045 | |||
| 4046 | <YueDisplay> | ||
| 4047 | |||
| 4048 | ```yue | ||
| 4049 | a = 1; b = 2; print a + b | ||
| 4050 | ``` | ||
| 4051 | |||
| 4052 | </YueDisplay> | ||
| 4053 | |||
| 4054 | ## Rantai Multibaris | ||
| 4055 | |||
| 4056 | Anda bisa menulis pemanggilan fungsi berantai multi-baris dengan indentasi yang sama. | ||
| 4057 | |||
| 4058 | ```yuescript | ||
| 4059 | Rx.Observable | ||
| 4060 | .fromRange 1, 8 | ||
| 4061 | \filter (x) -> x % 2 == 0 | ||
| 4062 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4063 | \map (value) -> value .. '!' | ||
| 4064 | \subscribe print | ||
| 4065 | ``` | ||
| 4066 | |||
| 4067 | <YueDisplay> | ||
| 4068 | |||
| 4069 | ```yue | ||
| 4070 | Rx.Observable | ||
| 4071 | .fromRange 1, 8 | ||
| 4072 | \filter (x) -> x % 2 == 0 | ||
| 4073 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4074 | \map (value) -> value .. '!' | ||
| 4075 | \subscribe print | ||
| 4076 | ``` | ||
| 4077 | |||
| 4078 | </YueDisplay> | ||
| 4079 | |||
| 4080 | # Komentar | ||
| 4081 | |||
| 4082 | ```yuescript | ||
| 4083 | -- Saya adalah komentar | ||
| 4084 | |||
| 4085 | str = --[[ | ||
| 4086 | Ini komentar multi-baris. | ||
| 4087 | Tidak masalah. | ||
| 4088 | ]] strA \ -- komentar 1 | ||
| 4089 | .. strB \ -- komentar 2 | ||
| 4090 | .. strC | ||
| 4091 | |||
| 4092 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4093 | ``` | ||
| 4094 | |||
| 4095 | <YueDisplay> | ||
| 4096 | |||
| 4097 | ```yue | ||
| 4098 | -- Saya adalah komentar | ||
| 4099 | |||
| 4100 | str = --[[ | ||
| 4101 | Ini komentar multi-baris. | ||
| 4102 | Tidak masalah. | ||
| 4103 | ]] strA \ -- komentar 1 | ||
| 4104 | .. strB \ -- komentar 2 | ||
| 4105 | .. strC | ||
| 4106 | |||
| 4107 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4108 | ``` | ||
| 4109 | |||
| 4110 | </YueDisplay> | ||
| 4111 | |||
| 4112 | # Atribut | ||
| 4113 | |||
| 4114 | Dukungan sintaks untuk atribut Lua 5.4. Anda juga masih bisa menggunakan deklarasi `const` dan `close` dan mendapatkan pemeriksaan konstanta serta callback berbatas-scope ketika menargetkan versi Lua di bawah 5.4. | ||
| 4115 | |||
| 4116 | ```yuescript | ||
| 4117 | const a = 123 | ||
| 4118 | close _ = <close>: -> print "Out of scope." | ||
| 4119 | ``` | ||
| 4120 | |||
| 4121 | <YueDisplay> | ||
| 4122 | |||
| 4123 | ```yue | ||
| 4124 | const a = 123 | ||
| 4125 | close _ = <close>: -> print "Out of scope." | ||
| 4126 | ``` | ||
| 4127 | |||
| 4128 | </YueDisplay> | ||
| 4129 | |||
| 4130 | Anda dapat melakukan destrukturisasi dengan variabel yang diberi atribut sebagai konstanta. | ||
| 4131 | |||
| 4132 | ```yuescript | ||
| 4133 | const {:a, :b, c, d} = tb | ||
| 4134 | -- a = 1 | ||
| 4135 | ``` | ||
| 4136 | |||
| 4137 | <YueDisplay> | ||
| 4138 | |||
| 4139 | ```yue | ||
| 4140 | const {:a, :b, c, d} = tb | ||
| 4141 | -- a = 1 | ||
| 4142 | ``` | ||
| 4143 | |||
| 4144 | </YueDisplay> | ||
| 4145 | |||
| 4146 | Anda juga bisa mendeklarasikan variabel global sebagai `const`. | ||
| 4147 | |||
| 4148 | ```yuescript | ||
| 4149 | global const Constant = 123 | ||
| 4150 | -- Constant = 1 | ||
| 4151 | ``` | ||
| 4152 | |||
| 4153 | <YueDisplay> | ||
| 4154 | |||
| 4155 | ```yue | ||
| 4156 | global const Constant = 123 | ||
| 4157 | -- Constant = 1 | ||
| 4158 | ``` | ||
| 4159 | |||
| 4160 | </YueDisplay> | ||
| 4161 | |||
| 4162 | # Operator | ||
| 4163 | |||
| 4164 | Semua operator biner dan unari Lua tersedia. Selain itu **!=** adalah alias untuk **~=**, dan **\\** atau **::** bisa digunakan untuk menulis pemanggilan fungsi berantai seperti `tb\func!` atau `tb::func!`. YueScript juga menawarkan beberapa operator khusus lain untuk menulis kode yang lebih ekspresif. | ||
| 4165 | |||
| 4166 | ```yuescript | ||
| 4167 | tb\func! if tb ~= nil | ||
| 4168 | tb::func! if tb != nil | ||
| 4169 | ``` | ||
| 4170 | |||
| 4171 | <YueDisplay> | ||
| 4172 | |||
| 4173 | ```yue | ||
| 4174 | tb\func! if tb ~= nil | ||
| 4175 | tb::func! if tb != nil | ||
| 4176 | ``` | ||
| 4177 | |||
| 4178 | </YueDisplay> | ||
| 4179 | |||
| 4180 | ## Perbandingan Berantai | ||
| 4181 | |||
| 4182 | Perbandingan bisa dirantai secara bebas: | ||
| 4183 | |||
| 4184 | ```yuescript | ||
| 4185 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4186 | -- output: true | ||
| 4187 | |||
| 4188 | a = 5 | ||
| 4189 | print 1 <= a <= 10 | ||
| 4190 | -- output: true | ||
| 4191 | ``` | ||
| 4192 | |||
| 4193 | <YueDisplay> | ||
| 4194 | |||
| 4195 | ```yue | ||
| 4196 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4197 | -- output: true | ||
| 4198 | |||
| 4199 | a = 5 | ||
| 4200 | print 1 <= a <= 10 | ||
| 4201 | -- output: true | ||
| 4202 | ``` | ||
| 4203 | |||
| 4204 | </YueDisplay> | ||
| 4205 | |||
| 4206 | Perhatikan perilaku evaluasi perbandingan berantai: | ||
| 4207 | |||
| 4208 | ```yuescript | ||
| 4209 | v = (x) -> | ||
| 4210 | print x | ||
| 4211 | x | ||
| 4212 | |||
| 4213 | print v(1) < v(2) <= v(3) | ||
| 4214 | --[[ | ||
| 4215 | output: | ||
| 4216 | 2 | ||
| 4217 | 1 | ||
| 4218 | 3 | ||
| 4219 | true | ||
| 4220 | ]] | ||
| 4221 | |||
| 4222 | print v(1) > v(2) <= v(3) | ||
| 4223 | --[[ | ||
| 4224 | output: | ||
| 4225 | 2 | ||
| 4226 | 1 | ||
| 4227 | false | ||
| 4228 | ]] | ||
| 4229 | ``` | ||
| 4230 | |||
| 4231 | <YueDisplay> | ||
| 4232 | |||
| 4233 | ```yue | ||
| 4234 | v = (x) -> | ||
| 4235 | print x | ||
| 4236 | x | ||
| 4237 | |||
| 4238 | print v(1) < v(2) <= v(3) | ||
| 4239 | --[[ | ||
| 4240 | output: | ||
| 4241 | 2 | ||
| 4242 | 1 | ||
| 4243 | 3 | ||
| 4244 | true | ||
| 4245 | ]] | ||
| 4246 | |||
| 4247 | print v(1) > v(2) <= v(3) | ||
| 4248 | --[[ | ||
| 4249 | output: | ||
| 4250 | 2 | ||
| 4251 | 1 | ||
| 4252 | false | ||
| 4253 | ]] | ||
| 4254 | ``` | ||
| 4255 | |||
| 4256 | </YueDisplay> | ||
| 4257 | |||
| 4258 | Ekspresi tengah hanya dievaluasi sekali, bukan dua kali seperti jika ekspresi ditulis sebagai `v(1) < v(2) and v(2) <= v(3)`. Namun, urutan evaluasi pada perbandingan berantai tidak didefinisikan. Sangat disarankan untuk tidak menggunakan ekspresi dengan efek samping (seperti `print`) di perbandingan berantai. Jika efek samping diperlukan, operator short-circuit `and` sebaiknya digunakan secara eksplisit. | ||
| 4259 | |||
| 4260 | ## Menambahkan ke Tabel | ||
| 4261 | |||
| 4262 | Operator **[] =** digunakan untuk menambahkan nilai ke tabel. | ||
| 4263 | |||
| 4264 | ```yuescript | ||
| 4265 | tab = [] | ||
| 4266 | tab[] = "Value" | ||
| 4267 | ``` | ||
| 4268 | |||
| 4269 | <YueDisplay> | ||
| 4270 | |||
| 4271 | ```yue | ||
| 4272 | tab = [] | ||
| 4273 | tab[] = "Value" | ||
| 4274 | ``` | ||
| 4275 | |||
| 4276 | </YueDisplay> | ||
| 4277 | |||
| 4278 | Anda juga bisa memakai operator spread `...` untuk menambahkan semua elemen dari satu list ke list lain: | ||
| 4279 | |||
| 4280 | ```yuescript | ||
| 4281 | tbA = [1, 2, 3] | ||
| 4282 | tbB = [4, 5, 6] | ||
| 4283 | tbA[] = ...tbB | ||
| 4284 | -- tbA sekarang [1, 2, 3, 4, 5, 6] | ||
| 4285 | ``` | ||
| 4286 | |||
| 4287 | <YueDisplay> | ||
| 4288 | |||
| 4289 | ```yue | ||
| 4290 | tbA = [1, 2, 3] | ||
| 4291 | tbB = [4, 5, 6] | ||
| 4292 | tbA[] = ...tbB | ||
| 4293 | -- tbA sekarang [1, 2, 3, 4, 5, 6] | ||
| 4294 | ``` | ||
| 4295 | |||
| 4296 | </YueDisplay> | ||
| 4297 | |||
| 4298 | ## Penyebaran Tabel | ||
| 4299 | |||
| 4300 | Anda bisa menggabungkan tabel array atau tabel hash menggunakan operator spread `...` sebelum ekspresi di literal tabel. | ||
| 4301 | |||
| 4302 | ```yuescript | ||
| 4303 | parts = | ||
| 4304 | * "shoulders" | ||
| 4305 | * "knees" | ||
| 4306 | lyrics = | ||
| 4307 | * "head" | ||
| 4308 | * ...parts | ||
| 4309 | * "and" | ||
| 4310 | * "toes" | ||
| 4311 | |||
| 4312 | copy = {...other} | ||
| 4313 | |||
| 4314 | a = {1, 2, 3, x: 1} | ||
| 4315 | b = {4, 5, y: 1} | ||
| 4316 | merge = {...a, ...b} | ||
| 4317 | ``` | ||
| 4318 | |||
| 4319 | <YueDisplay> | ||
| 4320 | |||
| 4321 | ```yue | ||
| 4322 | parts = | ||
| 4323 | * "shoulders" | ||
| 4324 | * "knees" | ||
| 4325 | lyrics = | ||
| 4326 | * "head" | ||
| 4327 | * ...parts | ||
| 4328 | * "and" | ||
| 4329 | * "toes" | ||
| 4330 | |||
| 4331 | copy = {...other} | ||
| 4332 | |||
| 4333 | a = {1, 2, 3, x: 1} | ||
| 4334 | b = {4, 5, y: 1} | ||
| 4335 | merge = {...a, ...b} | ||
| 4336 | ``` | ||
| 4337 | |||
| 4338 | </YueDisplay> | ||
| 4339 | |||
| 4340 | ## Indeks Balik Tabel | ||
| 4341 | |||
| 4342 | Anda dapat menggunakan operator **#** untuk mendapatkan elemen terakhir dari tabel. | ||
| 4343 | |||
| 4344 | ```yuescript | ||
| 4345 | last = data.items[#] | ||
| 4346 | second_last = data.items[#-1] | ||
| 4347 | data.items[#] = 1 | ||
| 4348 | ``` | ||
| 4349 | |||
| 4350 | <YueDisplay> | ||
| 4351 | |||
| 4352 | ```yue | ||
| 4353 | last = data.items[#] | ||
| 4354 | second_last = data.items[#-1] | ||
| 4355 | data.items[#] = 1 | ||
| 4356 | ``` | ||
| 4357 | |||
| 4358 | </YueDisplay> | ||
| 4359 | |||
| 4360 | ## Metatable | ||
| 4361 | |||
| 4362 | Operator **<>** dapat digunakan sebagai pintasan untuk manipulasi metatable. | ||
| 4363 | |||
| 4364 | ### Pembuatan Metatable | ||
| 4365 | |||
| 4366 | Buat tabel normal dengan tanda kurung siku kosong **<>** atau kunci metamethod yang dikelilingi oleh **<>**. | ||
| 4367 | |||
| 4368 | ```yuescript | ||
| 4369 | mt = {} | ||
| 4370 | add = (right) => <>: mt, value: @value + right.value | ||
| 4371 | mt.__add = add | ||
| 4372 | |||
| 4373 | a = <>: mt, value: 1 | ||
| 4374 | -- set field dengan variabel bernama sama | ||
| 4375 | b = :<add>, value: 2 | ||
| 4376 | c = <add>: mt.__add, value: 3 | ||
| 4377 | |||
| 4378 | d = a + b + c | ||
| 4379 | print d.value | ||
| 4380 | |||
| 4381 | close _ = <close>: -> print "out of scope" | ||
| 4382 | ``` | ||
| 4383 | |||
| 4384 | <YueDisplay> | ||
| 4385 | |||
| 4386 | ```yue | ||
| 4387 | mt = {} | ||
| 4388 | add = (right) => <>: mt, value: @value + right.value | ||
| 4389 | mt.__add = add | ||
| 4390 | |||
| 4391 | a = <>: mt, value: 1 | ||
| 4392 | -- set field dengan variabel bernama sama | ||
| 4393 | b = :<add>, value: 2 | ||
| 4394 | c = <add>: mt.__add, value: 3 | ||
| 4395 | |||
| 4396 | d = a + b + c | ||
| 4397 | print d.value | ||
| 4398 | |||
| 4399 | close _ = <close>: -> print "out of scope" | ||
| 4400 | ``` | ||
| 4401 | |||
| 4402 | </YueDisplay> | ||
| 4403 | |||
| 4404 | ### Mengakses Metatable | ||
| 4405 | |||
| 4406 | Akses metatable dengan **<>**, nama metamethod yang dikelilingi **<>**, atau menulis ekspresi di dalam **<>**. | ||
| 4407 | |||
| 4408 | ```yuescript | ||
| 4409 | -- dibuat dengan metatable yang berisi field "value" | ||
| 4410 | tb = <"value">: 123 | ||
| 4411 | tb.<index> = tb.<> | ||
| 4412 | print tb.value | ||
| 4413 | |||
| 4414 | tb.<> = __index: {item: "hello"} | ||
| 4415 | print tb.item | ||
| 4416 | ``` | ||
| 4417 | |||
| 4418 | <YueDisplay> | ||
| 4419 | |||
| 4420 | ```yue | ||
| 4421 | -- dibuat dengan metatable yang berisi field "value" | ||
| 4422 | tb = <"value">: 123 | ||
| 4423 | tb.<index> = tb.<> | ||
| 4424 | print tb.value | ||
| 4425 | tb.<> = __index: {item: "hello"} | ||
| 4426 | print tb.item | ||
| 4427 | ``` | ||
| 4428 | |||
| 4429 | </YueDisplay> | ||
| 4430 | |||
| 4431 | ### Destrukturisasi Metatable | ||
| 4432 | |||
| 4433 | Destrukturisasi metatable dengan kunci metamethod yang dikelilingi **<>**. | ||
| 4434 | |||
| 4435 | ```yuescript | ||
| 4436 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4437 | print item, new, close, getter | ||
| 4438 | ``` | ||
| 4439 | |||
| 4440 | <YueDisplay> | ||
| 4441 | |||
| 4442 | ```yue | ||
| 4443 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4444 | print item, new, close, getter | ||
| 4445 | ``` | ||
| 4446 | |||
| 4447 | </YueDisplay> | ||
| 4448 | |||
| 4449 | ## Keberadaan | ||
| 4450 | |||
| 4451 | Operator **?** dapat digunakan dalam berbagai konteks untuk memeriksa keberadaan. | ||
| 4452 | |||
| 4453 | ```yuescript | ||
| 4454 | func?! | ||
| 4455 | print abc?["hello world"]?.xyz | ||
| 4456 | |||
| 4457 | x = tab?.value | ||
| 4458 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4459 | |||
| 4460 | if print and x? | ||
| 4461 | print x | ||
| 4462 | |||
| 4463 | with? io.open "test.txt", "w" | ||
| 4464 | \write "hello" | ||
| 4465 | \close! | ||
| 4466 | ``` | ||
| 4467 | |||
| 4468 | <YueDisplay> | ||
| 4469 | |||
| 4470 | ```yue | ||
| 4471 | func?! | ||
| 4472 | print abc?["hello world"]?.xyz | ||
| 4473 | |||
| 4474 | x = tab?.value | ||
| 4475 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4476 | |||
| 4477 | if print and x? | ||
| 4478 | print x | ||
| 4479 | |||
| 4480 | with? io.open "test.txt", "w" | ||
| 4481 | \write "hello" | ||
| 4482 | \close! | ||
| 4483 | ``` | ||
| 4484 | |||
| 4485 | </YueDisplay> | ||
| 4486 | |||
| 4487 | ## Piping | ||
| 4488 | |||
| 4489 | Sebagai ganti serangkaian pemanggilan fungsi bersarang, Anda bisa mengalirkan nilai dengan operator **|>**. | ||
| 4490 | |||
| 4491 | ```yuescript | ||
| 4492 | "hello" |> print | ||
| 4493 | 1 |> print 2 -- sisipkan nilai pipe sebagai argumen pertama | ||
| 4494 | 2 |> print 1, _, 3 -- pipe dengan placeholder | ||
| 4495 | |||
| 4496 | -- ekspresi pipe multi-baris | ||
| 4497 | readFile "example.txt" | ||
| 4498 | |> extract language, {} | ||
| 4499 | |> parse language | ||
| 4500 | |> emit | ||
| 4501 | |> render | ||
| 4502 | |||
| 4503 | ``` | ||
| 4504 | |||
| 4505 | <YueDisplay> | ||
| 4506 | |||
| 4507 | ```yue | ||
| 4508 | "hello" |> print | ||
| 4509 | 1 |> print 2 -- sisipkan nilai pipe sebagai argumen pertama | ||
| 4510 | 2 |> print 1, _, 3 -- pipe dengan placeholder | ||
| 4511 | -- ekspresi pipe multi-baris | ||
| 4512 | readFile "example.txt" | ||
| 4513 | |> extract language, {} | ||
| 4514 | |> parse language | ||
| 4515 | |> emit | ||
| 4516 | |> render | ||
| 4517 | |||
| 4518 | ``` | ||
| 4519 | |||
| 4520 | </YueDisplay> | ||
| 4521 | |||
| 4522 | ## Nil Coalescing | ||
| 4523 | |||
| 4524 | Operator nil-coalescing **??** mengembalikan nilai dari operan kiri jika bukan **nil**; jika tidak, operator mengevaluasi operan kanan dan mengembalikan hasilnya. Operator **??** tidak mengevaluasi operan kanan jika operan kiri bernilai non-nil. | ||
| 4525 | |||
| 4526 | ```yuescript | ||
| 4527 | local a, b, c, d | ||
| 4528 | a = b ?? c ?? d | ||
| 4529 | func a ?? {} | ||
| 4530 | |||
| 4531 | a ??= false | ||
| 4532 | ``` | ||
| 4533 | |||
| 4534 | <YueDisplay> | ||
| 4535 | |||
| 4536 | ```yue | ||
| 4537 | local a, b, c, d | ||
| 4538 | a = b ?? c ?? d | ||
| 4539 | func a ?? {} | ||
| 4540 | a ??= false | ||
| 4541 | ``` | ||
| 4542 | |||
| 4543 | </YueDisplay> | ||
| 4544 | |||
| 4545 | ## Objek Implisit | ||
| 4546 | |||
| 4547 | Anda dapat menulis daftar struktur implisit yang diawali simbol **\*** atau **-** di dalam blok tabel. Jika Anda membuat objek implisit, field objek harus berada pada indentasi yang sama. | ||
| 4548 | |||
| 4549 | ```yuescript | ||
| 4550 | -- assignment dengan objek implisit | ||
| 4551 | list = | ||
| 4552 | * 1 | ||
| 4553 | * 2 | ||
| 4554 | * 3 | ||
| 4555 | |||
| 4556 | -- pemanggilan fungsi dengan objek implisit | ||
| 4557 | func | ||
| 4558 | * 1 | ||
| 4559 | * 2 | ||
| 4560 | * 3 | ||
| 4561 | |||
| 4562 | -- return dengan objek implisit | ||
| 4563 | f = -> | ||
| 4564 | return | ||
| 4565 | * 1 | ||
| 4566 | * 2 | ||
| 4567 | * 3 | ||
| 4568 | |||
| 4569 | -- tabel dengan objek implisit | ||
| 4570 | tb = | ||
| 4571 | name: "abc" | ||
| 4572 | |||
| 4573 | values: | ||
| 4574 | - "a" | ||
| 4575 | - "b" | ||
| 4576 | - "c" | ||
| 4577 | |||
| 4578 | objects: | ||
| 4579 | - name: "a" | ||
| 4580 | value: 1 | ||
| 4581 | func: => @value + 1 | ||
| 4582 | tb: | ||
| 4583 | fieldA: 1 | ||
| 4584 | |||
| 4585 | - name: "b" | ||
| 4586 | value: 2 | ||
| 4587 | func: => @value + 2 | ||
| 4588 | tb: { } | ||
| 4589 | |||
| 4590 | ``` | ||
| 4591 | |||
| 4592 | <YueDisplay> | ||
| 4593 | |||
| 4594 | ```yue | ||
| 4595 | -- assignment dengan objek implisit | ||
| 4596 | list = | ||
| 4597 | * 1 | ||
| 4598 | * 2 | ||
| 4599 | * 3 | ||
| 4600 | |||
| 4601 | -- pemanggilan fungsi dengan objek implisit | ||
| 4602 | func | ||
| 4603 | * 1 | ||
| 4604 | * 2 | ||
| 4605 | * 3 | ||
| 4606 | |||
| 4607 | -- return dengan objek implisit | ||
| 4608 | f = -> | ||
| 4609 | return | ||
| 4610 | * 1 | ||
| 4611 | * 2 | ||
| 4612 | * 3 | ||
| 4613 | |||
| 4614 | -- tabel dengan objek implisit | ||
| 4615 | tb = | ||
| 4616 | name: "abc" | ||
| 4617 | |||
| 4618 | values: | ||
| 4619 | - "a" | ||
| 4620 | - "b" | ||
| 4621 | - "c" | ||
| 4622 | |||
| 4623 | objects: | ||
| 4624 | - name: "a" | ||
| 4625 | value: 1 | ||
| 4626 | func: => @value + 1 | ||
| 4627 | tb: | ||
| 4628 | fieldA: 1 | ||
| 4629 | |||
| 4630 | - name: "b" | ||
| 4631 | value: 2 | ||
| 4632 | func: => @value + 2 | ||
| 4633 | tb: { } | ||
| 4634 | ``` | ||
| 4635 | |||
| 4636 | </YueDisplay> | ||
| 4637 | |||
| 4638 | # Literal | ||
| 4639 | |||
| 4640 | Semua literal primitif di Lua dapat digunakan. Ini berlaku untuk angka, string, boolean, dan **nil**. | ||
| 4641 | |||
| 4642 | Berbeda dengan Lua, pemisah baris diizinkan di dalam string bertanda kutip tunggal maupun ganda tanpa urutan escape: | ||
| 4643 | |||
| 4644 | ```yuescript | ||
| 4645 | some_string = "Here is a string | ||
| 4646 | that has a line break in it." | ||
| 4647 | |||
| 4648 | -- Anda dapat mencampur ekspresi ke dalam literal string dengan sintaks #{}. | ||
| 4649 | -- Interpolasi string hanya tersedia pada string dengan tanda kutip ganda. | ||
| 4650 | print "I am #{math.random! * 100}% sure." | ||
| 4651 | ``` | ||
| 4652 | |||
| 4653 | <YueDisplay> | ||
| 4654 | |||
| 4655 | ```yue | ||
| 4656 | some_string = "Here is a string | ||
| 4657 | that has a line break in it." | ||
| 4658 | |||
| 4659 | -- Anda dapat mencampur ekspresi ke dalam literal string dengan sintaks #{}. | ||
| 4660 | -- Interpolasi string hanya tersedia pada string dengan tanda kutip ganda. | ||
| 4661 | print "I am #{math.random! * 100}% sure." | ||
| 4662 | ``` | ||
| 4663 | |||
| 4664 | </YueDisplay> | ||
| 4665 | |||
| 4666 | ## Literal Angka | ||
| 4667 | |||
| 4668 | Anda bisa menggunakan garis bawah pada literal angka untuk meningkatkan keterbacaan. | ||
| 4669 | |||
| 4670 | ```yuescript | ||
| 4671 | integer = 1_000_000 | ||
| 4672 | hex = 0xEF_BB_BF | ||
| 4673 | binary = 0B10011 | ||
| 4674 | ``` | ||
| 4675 | |||
| 4676 | <YueDisplay> | ||
| 4677 | |||
| 4678 | ```yue | ||
| 4679 | integer = 1_000_000 | ||
| 4680 | hex = 0xEF_BB_BF | ||
| 4681 | binary = 0B10011 | ||
| 4682 | ``` | ||
| 4683 | |||
| 4684 | </YueDisplay> | ||
| 4685 | |||
| 4686 | ## String Multibaris YAML | ||
| 4687 | |||
| 4688 | Prefiks `|` memperkenalkan literal string multibaris bergaya YAML: | ||
| 4689 | |||
| 4690 | ```yuescript | ||
| 4691 | str = | | ||
| 4692 | key: value | ||
| 4693 | list: | ||
| 4694 | - item1 | ||
| 4695 | - #{expr} | ||
| 4696 | ``` | ||
| 4697 | |||
| 4698 | <YueDisplay> | ||
| 4699 | |||
| 4700 | ```yue | ||
| 4701 | str = | | ||
| 4702 | key: value | ||
| 4703 | list: | ||
| 4704 | - item1 | ||
| 4705 | - #{expr} | ||
| 4706 | ``` | ||
| 4707 | |||
| 4708 | </YueDisplay> | ||
| 4709 | |||
| 4710 | Ini memungkinkan penulisan teks multibaris terstruktur dengan mudah. Semua pemisah baris dan indentasi dipertahankan relatif terhadap baris non-kosong pertama, dan ekspresi di dalam `#{...}` diinterpolasi otomatis sebagai `tostring(expr)`. | ||
| 4711 | |||
| 4712 | String Multibaris YAML secara otomatis mendeteksi prefiks spasi awal yang sama (indentasi minimum di seluruh baris non-kosong) dan menghapusnya dari semua baris. Ini memudahkan untuk mengindentasi kode secara visual tanpa memengaruhi isi string yang dihasilkan. | ||
| 4713 | |||
| 4714 | ```yuescript | ||
| 4715 | fn = -> | ||
| 4716 | str = | | ||
| 4717 | foo: | ||
| 4718 | bar: baz | ||
| 4719 | return str | ||
| 4720 | ``` | ||
| 4721 | |||
| 4722 | <YueDisplay> | ||
| 4723 | |||
| 4724 | ```yue | ||
| 4725 | fn = -> | ||
| 4726 | str = | | ||
| 4727 | foo: | ||
| 4728 | bar: baz | ||
| 4729 | return str | ||
| 4730 | ``` | ||
| 4731 | |||
| 4732 | </YueDisplay> | ||
| 4733 | |||
| 4734 | Indentasi internal dipertahankan relatif terhadap prefiks umum yang dihapus, sehingga struktur bertingkat tetap rapi. | ||
| 4735 | |||
| 4736 | Semua karakter khusus seperti tanda kutip (`"`) dan backslash (`\`) di dalam blok YAMLMultiline di-escape secara otomatis agar string Lua yang dihasilkan valid secara sintaks dan berperilaku sebagaimana mestinya. | ||
| 4737 | |||
| 4738 | ```yuescript | ||
| 4739 | str = | | ||
| 4740 | path: "C:\Program Files\App" | ||
| 4741 | note: 'He said: "#{Hello}!"' | ||
| 4742 | ``` | ||
| 4743 | |||
| 4744 | <YueDisplay> | ||
| 4745 | |||
| 4746 | ```yue | ||
| 4747 | str = | | ||
| 4748 | path: "C:\Program Files\App" | ||
| 4749 | note: 'He said: "#{Hello}!"' | ||
| 4750 | ``` | ||
| 4751 | |||
| 4752 | </YueDisplay> | ||
| 4753 | |||
| 4754 | # Modul | ||
| 4755 | |||
| 4756 | ## Import | ||
| 4757 | |||
| 4758 | Pernyataan `import` adalah sintaks sugar untuk me-require modul atau membantu mengekstrak item dari modul yang diimpor. Item yang diimpor bersifat `const` secara default. | ||
| 4759 | |||
| 4760 | ```yuescript | ||
| 4761 | -- digunakan sebagai destrukturisasi tabel | ||
| 4762 | do | ||
| 4763 | import insert, concat from table | ||
| 4764 | -- akan error saat meng-assign ke insert, concat | ||
| 4765 | import C, Ct, Cmt from require "lpeg" | ||
| 4766 | -- shortcut untuk require implisit | ||
| 4767 | import x, y, z from 'mymodule' | ||
| 4768 | -- import gaya Python | ||
| 4769 | from 'module' import a, b, c | ||
| 4770 | |||
| 4771 | -- shortcut untuk require modul | ||
| 4772 | do | ||
| 4773 | import 'module' | ||
| 4774 | import 'module_x' | ||
| 4775 | import "d-a-s-h-e-s" | ||
| 4776 | import "module.part" | ||
| 4777 | |||
| 4778 | -- require modul dengan aliasing atau destrukturisasi tabel | ||
| 4779 | do | ||
| 4780 | import "player" as PlayerModule | ||
| 4781 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4782 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4783 | ``` | ||
| 4784 | |||
| 4785 | <YueDisplay> | ||
| 4786 | |||
| 4787 | ```yue | ||
| 4788 | -- digunakan sebagai destrukturisasi tabel | ||
| 4789 | do | ||
| 4790 | import insert, concat from table | ||
| 4791 | -- akan error saat meng-assign ke insert, concat | ||
| 4792 | import C, Ct, Cmt from require "lpeg" | ||
| 4793 | -- shortcut untuk require implisit | ||
| 4794 | import x, y, z from 'mymodule' | ||
| 4795 | -- import gaya Python | ||
| 4796 | from 'module' import a, b, c | ||
| 4797 | |||
| 4798 | -- shortcut untuk require modul | ||
| 4799 | do | ||
| 4800 | import 'module' | ||
| 4801 | import 'module_x' | ||
| 4802 | import "d-a-s-h-e-s" | ||
| 4803 | import "module.part" | ||
| 4804 | |||
| 4805 | -- require modul dengan aliasing atau destrukturisasi tabel | ||
| 4806 | do | ||
| 4807 | import "player" as PlayerModule | ||
| 4808 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4809 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4810 | ``` | ||
| 4811 | |||
| 4812 | </YueDisplay> | ||
| 4813 | |||
| 4814 | ## Import Global | ||
| 4815 | |||
| 4816 | Anda dapat mengimpor global tertentu ke variabel local dengan `import`. Saat mengimpor rangkaian akses variabel global, field terakhir akan di-assign ke variabel local. | ||
| 4817 | |||
| 4818 | ```yuescript | ||
| 4819 | do | ||
| 4820 | import tostring | ||
| 4821 | import table.concat | ||
| 4822 | print concat ["a", tostring 1] | ||
| 4823 | ``` | ||
| 4824 | |||
| 4825 | <YueDisplay> | ||
| 4826 | |||
| 4827 | ```yue | ||
| 4828 | do | ||
| 4829 | import tostring | ||
| 4830 | import table.concat | ||
| 4831 | print concat ["a", tostring 1] | ||
| 4832 | ``` | ||
| 4833 | |||
| 4834 | </YueDisplay> | ||
| 4835 | |||
| 4836 | ### Import Variabel Global Otomatis | ||
| 4837 | |||
| 4838 | Anda dapat menempatkan `import global` di awal blok untuk mengimpor secara otomatis semua nama yang belum dideklarasikan atau di-assign secara eksplisit di scope saat ini sebagai global. Import implisit ini diperlakukan sebagai local const yang mereferensikan global terkait pada posisi pernyataan tersebut. | ||
| 4839 | |||
| 4840 | Nama yang secara eksplisit dideklarasikan sebagai global di scope yang sama tidak akan diimpor, sehingga Anda masih bisa meng-assign ke mereka. | ||
| 4841 | |||
| 4842 | ```yuescript | ||
| 4843 | do | ||
| 4844 | import global | ||
| 4845 | print "hello" | ||
| 4846 | math.random 3 | ||
| 4847 | -- print = nil -- error: imported globals are const | ||
| 4848 | |||
| 4849 | do | ||
| 4850 | -- variabel global eksplisit tidak akan diimpor | ||
| 4851 | import global | ||
| 4852 | global FLAG | ||
| 4853 | print FLAG | ||
| 4854 | FLAG = 123 | ||
| 4855 | ``` | ||
| 4856 | |||
| 4857 | <YueDisplay> | ||
| 4858 | |||
| 4859 | ```yue | ||
| 4860 | do | ||
| 4861 | import global | ||
| 4862 | print "hello" | ||
| 4863 | math.random 3 | ||
| 4864 | -- print = nil -- error: imported globals are const | ||
| 4865 | |||
| 4866 | do | ||
| 4867 | -- variabel global eksplisit tidak akan diimpor | ||
| 4868 | import global | ||
| 4869 | global FLAG | ||
| 4870 | print FLAG | ||
| 4871 | FLAG = 123 | ||
| 4872 | ``` | ||
| 4873 | |||
| 4874 | </YueDisplay> | ||
| 4875 | |||
| 4876 | ## Export | ||
| 4877 | |||
| 4878 | Pernyataan `export` menawarkan cara ringkas untuk mendefinisikan modul. | ||
| 4879 | |||
| 4880 | ### Export Bernama | ||
| 4881 | |||
| 4882 | Export bernama akan mendefinisikan variabel local sekaligus menambahkan field di tabel export. | ||
| 4883 | |||
| 4884 | ```yuescript | ||
| 4885 | export a, b, c = 1, 2, 3 | ||
| 4886 | export cool = "cat" | ||
| 4887 | |||
| 4888 | export What = if this | ||
| 4889 | "abc" | ||
| 4890 | else | ||
| 4891 | "def" | ||
| 4892 | |||
| 4893 | export y = -> | ||
| 4894 | hallo = 3434 | ||
| 4895 | |||
| 4896 | export class Something | ||
| 4897 | umm: "cool" | ||
| 4898 | ``` | ||
| 4899 | |||
| 4900 | <YueDisplay> | ||
| 4901 | |||
| 4902 | ```yue | ||
| 4903 | export a, b, c = 1, 2, 3 | ||
| 4904 | export cool = "cat" | ||
| 4905 | |||
| 4906 | export What = if this | ||
| 4907 | "abc" | ||
| 4908 | else | ||
| 4909 | "def" | ||
| 4910 | |||
| 4911 | export y = -> | ||
| 4912 | hallo = 3434 | ||
| 4913 | |||
| 4914 | export class Something | ||
| 4915 | umm: "cool" | ||
| 4916 | ``` | ||
| 4917 | |||
| 4918 | </YueDisplay> | ||
| 4919 | |||
| 4920 | Melakukan export bernama dengan destrukturisasi. | ||
| 4921 | |||
| 4922 | ```yuescript | ||
| 4923 | export :loadstring, to_lua: tolua = yue | ||
| 4924 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4925 | ``` | ||
| 4926 | |||
| 4927 | <YueDisplay> | ||
| 4928 | |||
| 4929 | ```yue | ||
| 4930 | export :loadstring, to_lua: tolua = yue | ||
| 4931 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4932 | ``` | ||
| 4933 | |||
| 4934 | </YueDisplay> | ||
| 4935 | |||
| 4936 | Export item bernama dari modul tanpa membuat variabel local. | ||
| 4937 | |||
| 4938 | ```yuescript | ||
| 4939 | export.itemA = tb | ||
| 4940 | export.<index> = items | ||
| 4941 | export["a-b-c"] = 123 | ||
| 4942 | ``` | ||
| 4943 | |||
| 4944 | <YueDisplay> | ||
| 4945 | |||
| 4946 | ```yue | ||
| 4947 | export.itemA = tb | ||
| 4948 | export.<index> = items | ||
| 4949 | export["a-b-c"] = 123 | ||
| 4950 | ``` | ||
| 4951 | |||
| 4952 | </YueDisplay> | ||
| 4953 | |||
| 4954 | ### Export Tanpa Nama | ||
| 4955 | |||
| 4956 | Export tanpa nama akan menambahkan item target ke bagian array dari tabel export. | ||
| 4957 | |||
| 4958 | ```yuescript | ||
| 4959 | d, e, f = 3, 2, 1 | ||
| 4960 | export d, e, f | ||
| 4961 | |||
| 4962 | export if this | ||
| 4963 | 123 | ||
| 4964 | else | ||
| 4965 | 456 | ||
| 4966 | |||
| 4967 | export with tmp | ||
| 4968 | j = 2000 | ||
| 4969 | ``` | ||
| 4970 | |||
| 4971 | <YueDisplay> | ||
| 4972 | |||
| 4973 | ```yue | ||
| 4974 | d, e, f = 3, 2, 1 | ||
| 4975 | export d, e, f | ||
| 4976 | |||
| 4977 | export if this | ||
| 4978 | 123 | ||
| 4979 | else | ||
| 4980 | 456 | ||
| 4981 | |||
| 4982 | export with tmp | ||
| 4983 | j = 2000 | ||
| 4984 | ``` | ||
| 4985 | |||
| 4986 | </YueDisplay> | ||
| 4987 | |||
| 4988 | ### Export Default | ||
| 4989 | |||
| 4990 | Gunakan kata kunci **default** dalam pernyataan export untuk mengganti tabel export dengan apa pun. | ||
| 4991 | |||
| 4992 | ```yuescript | ||
| 4993 | export default -> | ||
| 4994 | print "hello" | ||
| 4995 | 123 | ||
| 4996 | ``` | ||
| 4997 | |||
| 4998 | <YueDisplay> | ||
| 4999 | |||
| 5000 | ```yue | ||
| 5001 | export default -> | ||
| 5002 | print "hello" | ||
| 5003 | 123 | ||
| 5004 | ``` | ||
| 5005 | |||
| 5006 | </YueDisplay> | ||
| 5007 | |||
| 5008 | # Lisensi: MIT | ||
| 5009 | |||
| 5010 | Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> | ||
| 5011 | |||
| 5012 | Izin dengan ini diberikan, tanpa biaya, kepada siapa pun yang memperoleh salinan | ||
| 5013 | perangkat lunak ini beserta file dokumentasi terkait ("Perangkat Lunak"), untuk | ||
| 5014 | berurusan dengan Perangkat Lunak tanpa pembatasan, termasuk tanpa batasan hak | ||
| 5015 | untuk menggunakan, menyalin, memodifikasi, menggabungkan, menerbitkan, | ||
| 5016 | mendistribusikan, mensublisensikan, dan/atau menjual salinan Perangkat Lunak, | ||
| 5017 | dan untuk mengizinkan orang yang menerima Perangkat Lunak untuk melakukannya, | ||
| 5018 | dengan syarat-syarat berikut: | ||
| 5019 | |||
| 5020 | Pemberitahuan hak cipta di atas dan pemberitahuan izin ini harus disertakan dalam | ||
| 5021 | semua salinan atau bagian substansial dari Perangkat Lunak. | ||
| 5022 | |||
| 5023 | PERANGKAT LUNAK DISEDIAKAN "APA ADANYA", TANPA JAMINAN APA PUN, BAIK TERSURAT | ||
| 5024 | MAUPUN TERSIRAT, TERMASUK NAMUN TIDAK TERBATAS PADA JAMINAN KELAYAKAN | ||
| 5025 | DIPERDAGANGKAN, KESESUAIAN UNTUK TUJUAN TERTENTU, DAN TIDAK MELANGGAR HAK. | ||
| 5026 | DALAM KEADAAN APA PUN, PENULIS ATAU PEMEGANG HAK CIPTA TIDAK BERTANGGUNG JAWAB | ||
| 5027 | ATAS KLAIM, KERUSAKAN, ATAU KEWAJIBAN LAINNYA, BAIK DALAM TINDAKAN KONTRAK, | ||
| 5028 | PERBUATAN MELAWAN HUKUM, ATAU LAINNYA, YANG TIMBUL DARI, DI LUAR, ATAU TERKAIT | ||
| 5029 | DENGAN PERANGKAT LUNAK ATAU PENGGUNAAN ATAU URUSAN LAIN DALAM PERANGKAT LUNAK. | ||
| 5030 | |||
| 5031 | # Pustaka YueScript | ||
| 5032 | |||
| 5033 | Akses dengan `local yue = require("yue")` di Lua. | ||
| 5034 | |||
| 5035 | ## yue | ||
| 5036 | |||
| 5037 | **Deskripsi:** | ||
| 5038 | |||
| 5039 | Pustaka bahasa YueScript. | ||
| 5040 | |||
| 5041 | ### version | ||
| 5042 | |||
| 5043 | **Tipe:** Field. | ||
| 5044 | |||
| 5045 | **Deskripsi:** | ||
| 5046 | |||
| 5047 | Versi YueScript. | ||
| 5048 | |||
| 5049 | **Signature:** | ||
| 5050 | |||
| 5051 | ```lua | ||
| 5052 | version: string | ||
| 5053 | ``` | ||
| 5054 | |||
| 5055 | ### dirsep | ||
| 5056 | |||
| 5057 | **Tipe:** Field. | ||
| 5058 | |||
| 5059 | **Deskripsi:** | ||
| 5060 | |||
| 5061 | Pemisah file untuk platform saat ini. | ||
| 5062 | |||
| 5063 | **Signature:** | ||
| 5064 | |||
| 5065 | ```lua | ||
| 5066 | dirsep: string | ||
| 5067 | ``` | ||
| 5068 | |||
| 5069 | ### yue_compiled | ||
| 5070 | |||
| 5071 | **Tipe:** Field. | ||
| 5072 | |||
| 5073 | **Deskripsi:** | ||
| 5074 | |||
| 5075 | Cache kode modul yang telah dikompilasi. | ||
| 5076 | |||
| 5077 | **Signature:** | ||
| 5078 | |||
| 5079 | ```lua | ||
| 5080 | yue_compiled: {string: string} | ||
| 5081 | ``` | ||
| 5082 | |||
| 5083 | ### to_lua | ||
| 5084 | |||
| 5085 | **Tipe:** Function. | ||
| 5086 | |||
| 5087 | **Deskripsi:** | ||
| 5088 | |||
| 5089 | Fungsi kompilasi YueScript. Mengompilasi kode YueScript menjadi kode Lua. | ||
| 5090 | |||
| 5091 | **Signature:** | ||
| 5092 | |||
| 5093 | ```lua | ||
| 5094 | to_lua: function(code: string, config?: Config): | ||
| 5095 | --[[codes]] string | nil, | ||
| 5096 | --[[error]] string | nil, | ||
| 5097 | --[[globals]] {{string, integer, integer}} | nil | ||
| 5098 | ``` | ||
| 5099 | |||
| 5100 | **Parameter:** | ||
| 5101 | |||
| 5102 | | Parameter | Tipe | Deskripsi | | ||
| 5103 | | --------- | ------ | ------------------------- | | ||
| 5104 | | code | string | Kode YueScript. | | ||
| 5105 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5106 | |||
| 5107 | **Return:** | ||
| 5108 | |||
| 5109 | | Tipe Return | Deskripsi | | ||
| 5110 | | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5111 | | string \| nil | Kode Lua hasil kompilasi, atau nil jika kompilasi gagal. | | ||
| 5112 | | string \| nil | Pesan error, atau nil jika kompilasi berhasil. | | ||
| 5113 | | {{string, integer, integer}} \| nil | Variabel global yang muncul dalam kode (dengan nama, baris, dan kolom), atau nil jika opsi kompiler `lint_global` bernilai false. | | ||
| 5114 | |||
| 5115 | ### file_exist | ||
| 5116 | |||
| 5117 | **Tipe:** Function. | ||
| 5118 | |||
| 5119 | **Deskripsi:** | ||
| 5120 | |||
| 5121 | Fungsi untuk memeriksa keberadaan file sumber. Dapat ditimpa untuk menyesuaikan perilaku. | ||
| 5122 | |||
| 5123 | **Signature:** | ||
| 5124 | |||
| 5125 | ```lua | ||
| 5126 | file_exist: function(filename: string): boolean | ||
| 5127 | ``` | ||
| 5128 | |||
| 5129 | **Parameter:** | ||
| 5130 | |||
| 5131 | | Parameter | Tipe | Deskripsi | | ||
| 5132 | | --------- | ------ | ---------- | | ||
| 5133 | | filename | string | Nama file. | | ||
| 5134 | |||
| 5135 | **Return:** | ||
| 5136 | |||
| 5137 | | Tipe Return | Deskripsi | | ||
| 5138 | | ----------- | ---------------- | | ||
| 5139 | | boolean | Apakah file ada. | | ||
| 5140 | |||
| 5141 | ### read_file | ||
| 5142 | |||
| 5143 | **Tipe:** Function. | ||
| 5144 | |||
| 5145 | **Deskripsi:** | ||
| 5146 | |||
| 5147 | Fungsi untuk membaca file sumber. Dapat ditimpa untuk menyesuaikan perilaku. | ||
| 5148 | |||
| 5149 | **Signature:** | ||
| 5150 | |||
| 5151 | ```lua | ||
| 5152 | read_file: function(filename: string): string | ||
| 5153 | ``` | ||
| 5154 | |||
| 5155 | **Parameter:** | ||
| 5156 | |||
| 5157 | | Parameter | Tipe | Deskripsi | | ||
| 5158 | | --------- | ------ | ---------- | | ||
| 5159 | | filename | string | Nama file. | | ||
| 5160 | |||
| 5161 | **Return:** | ||
| 5162 | |||
| 5163 | | Tipe Return | Deskripsi | | ||
| 5164 | | ----------- | --------- | | ||
| 5165 | | string | Isi file. | | ||
| 5166 | |||
| 5167 | ### insert_loader | ||
| 5168 | |||
| 5169 | **Tipe:** Function. | ||
| 5170 | |||
| 5171 | **Deskripsi:** | ||
| 5172 | |||
| 5173 | Menyisipkan loader YueScript ke package loaders (searchers). | ||
| 5174 | |||
| 5175 | **Signature:** | ||
| 5176 | |||
| 5177 | ```lua | ||
| 5178 | insert_loader: function(pos?: integer): boolean | ||
| 5179 | ``` | ||
| 5180 | |||
| 5181 | **Parameter:** | ||
| 5182 | |||
| 5183 | | Parameter | Tipe | Deskripsi | | ||
| 5184 | | --------- | ------- | ------------------------------------------------------------- | | ||
| 5185 | | pos | integer | [Opsional] Posisi untuk menyisipkan loader. Default adalah 3. | | ||
| 5186 | |||
| 5187 | **Return:** | ||
| 5188 | |||
| 5189 | | Tipe Return | Deskripsi | | ||
| 5190 | | ----------- | --------------------------------------------------------------------------- | | ||
| 5191 | | boolean | Apakah loader berhasil disisipkan. Akan gagal jika loader sudah disisipkan. | | ||
| 5192 | |||
| 5193 | ### remove_loader | ||
| 5194 | |||
| 5195 | **Tipe:** Function. | ||
| 5196 | |||
| 5197 | **Deskripsi:** | ||
| 5198 | |||
| 5199 | Menghapus loader YueScript dari package loaders (searchers). | ||
| 5200 | |||
| 5201 | **Signature:** | ||
| 5202 | |||
| 5203 | ```lua | ||
| 5204 | remove_loader: function(): boolean | ||
| 5205 | ``` | ||
| 5206 | |||
| 5207 | **Return:** | ||
| 5208 | |||
| 5209 | | Tipe Return | Deskripsi | | ||
| 5210 | | ----------- | ------------------------------------------------------------------------ | | ||
| 5211 | | boolean | Apakah loader berhasil dihapus. Akan gagal jika loader belum disisipkan. | | ||
| 5212 | |||
| 5213 | ### loadstring | ||
| 5214 | |||
| 5215 | **Tipe:** Function. | ||
| 5216 | |||
| 5217 | **Deskripsi:** | ||
| 5218 | |||
| 5219 | Memuat kode YueScript dari string menjadi fungsi. | ||
| 5220 | |||
| 5221 | **Signature:** | ||
| 5222 | |||
| 5223 | ```lua | ||
| 5224 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | ||
| 5225 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5226 | --[[error]] string | nil | ||
| 5227 | ``` | ||
| 5228 | |||
| 5229 | **Parameter:** | ||
| 5230 | |||
| 5231 | | Parameter | Tipe | Deskripsi | | ||
| 5232 | | --------- | ------ | ------------------------- | | ||
| 5233 | | input | string | Kode YueScript. | | ||
| 5234 | | chunkname | string | Nama chunk kode. | | ||
| 5235 | | env | table | Tabel environment. | | ||
| 5236 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5237 | |||
| 5238 | **Return:** | ||
| 5239 | |||
| 5240 | | Tipe Return | Deskripsi | | ||
| 5241 | | --------------- | ------------------------------------------------- | | ||
| 5242 | | function \| nil | Fungsi yang dimuat, atau nil jika pemuatan gagal. | | ||
| 5243 | | string \| nil | Pesan error, atau nil jika pemuatan berhasil. | | ||
| 5244 | |||
| 5245 | ### loadstring | ||
| 5246 | |||
| 5247 | **Tipe:** Function. | ||
| 5248 | |||
| 5249 | **Deskripsi:** | ||
| 5250 | |||
| 5251 | Memuat kode YueScript dari string menjadi fungsi. | ||
| 5252 | |||
| 5253 | **Signature:** | ||
| 5254 | |||
| 5255 | ```lua | ||
| 5256 | loadstring: function(input: string, chunkname: string, config?: Config): | ||
| 5257 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5258 | --[[error]] string | nil | ||
| 5259 | ``` | ||
| 5260 | |||
| 5261 | **Parameter:** | ||
| 5262 | |||
| 5263 | | Parameter | Tipe | Deskripsi | | ||
| 5264 | | --------- | ------ | ------------------------- | | ||
| 5265 | | input | string | Kode YueScript. | | ||
| 5266 | | chunkname | string | Nama chunk kode. | | ||
| 5267 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5268 | |||
| 5269 | **Return:** | ||
| 5270 | |||
| 5271 | | Tipe Return | Deskripsi | | ||
| 5272 | | --------------- | ------------------------------------------------- | | ||
| 5273 | | function \| nil | Fungsi yang dimuat, atau nil jika pemuatan gagal. | | ||
| 5274 | | string \| nil | Pesan error, atau nil jika pemuatan berhasil. | | ||
| 5275 | |||
| 5276 | ### loadstring | ||
| 5277 | |||
| 5278 | **Tipe:** Function. | ||
| 5279 | |||
| 5280 | **Deskripsi:** | ||
| 5281 | |||
| 5282 | Memuat kode YueScript dari string menjadi fungsi. | ||
| 5283 | |||
| 5284 | **Signature:** | ||
| 5285 | |||
| 5286 | ```lua | ||
| 5287 | loadstring: function(input: string, config?: Config): | ||
| 5288 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5289 | --[[error]] string | nil | ||
| 5290 | ``` | ||
| 5291 | |||
| 5292 | **Parameter:** | ||
| 5293 | |||
| 5294 | | Parameter | Tipe | Deskripsi | | ||
| 5295 | | --------- | ------ | ------------------------- | | ||
| 5296 | | input | string | Kode YueScript. | | ||
| 5297 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5298 | |||
| 5299 | **Return:** | ||
| 5300 | |||
| 5301 | | Tipe Return | Deskripsi | | ||
| 5302 | | --------------- | ------------------------------------------------- | | ||
| 5303 | | function \| nil | Fungsi yang dimuat, atau nil jika pemuatan gagal. | | ||
| 5304 | | string \| nil | Pesan error, atau nil jika pemuatan berhasil. | | ||
| 5305 | |||
| 5306 | ### loadfile | ||
| 5307 | |||
| 5308 | **Tipe:** Function. | ||
| 5309 | |||
| 5310 | **Deskripsi:** | ||
| 5311 | |||
| 5312 | Memuat kode YueScript dari file menjadi fungsi. | ||
| 5313 | |||
| 5314 | **Signature:** | ||
| 5315 | |||
| 5316 | ```lua | ||
| 5317 | loadfile: function(filename: string, env: table, config?: Config): | ||
| 5318 | nil | function(...: any): (any...), | ||
| 5319 | string | nil | ||
| 5320 | ``` | ||
| 5321 | |||
| 5322 | **Parameter:** | ||
| 5323 | |||
| 5324 | | Parameter | Tipe | Deskripsi | | ||
| 5325 | | --------- | ------ | ------------------------- | | ||
| 5326 | | filename | string | Nama file. | | ||
| 5327 | | env | table | Tabel environment. | | ||
| 5328 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5329 | |||
| 5330 | **Return:** | ||
| 5331 | |||
| 5332 | | Tipe Return | Deskripsi | | ||
| 5333 | | --------------- | ------------------------------------------------- | | ||
| 5334 | | function \| nil | Fungsi yang dimuat, atau nil jika pemuatan gagal. | | ||
| 5335 | | string \| nil | Pesan error, atau nil jika pemuatan berhasil. | | ||
| 5336 | |||
| 5337 | ### loadfile | ||
| 5338 | |||
| 5339 | **Tipe:** Function. | ||
| 5340 | |||
| 5341 | **Deskripsi:** | ||
| 5342 | |||
| 5343 | Memuat kode YueScript dari file menjadi fungsi. | ||
| 5344 | |||
| 5345 | **Signature:** | ||
| 5346 | |||
| 5347 | ```lua | ||
| 5348 | loadfile: function(filename: string, config?: Config): | ||
| 5349 | nil | function(...: any): (any...), | ||
| 5350 | string | nil | ||
| 5351 | ``` | ||
| 5352 | |||
| 5353 | **Parameter:** | ||
| 5354 | |||
| 5355 | | Parameter | Tipe | Deskripsi | | ||
| 5356 | | --------- | ------ | ------------------------- | | ||
| 5357 | | filename | string | Nama file. | | ||
| 5358 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5359 | |||
| 5360 | **Return:** | ||
| 5361 | |||
| 5362 | | Tipe Return | Deskripsi | | ||
| 5363 | | --------------- | ------------------------------------------------- | | ||
| 5364 | | function \| nil | Fungsi yang dimuat, atau nil jika pemuatan gagal. | | ||
| 5365 | | string \| nil | Pesan error, atau nil jika pemuatan berhasil. | | ||
| 5366 | |||
| 5367 | ### dofile | ||
| 5368 | |||
| 5369 | **Tipe:** Function. | ||
| 5370 | |||
| 5371 | **Deskripsi:** | ||
| 5372 | |||
| 5373 | Memuat kode YueScript dari file menjadi fungsi dan mengeksekusinya. | ||
| 5374 | |||
| 5375 | **Signature:** | ||
| 5376 | |||
| 5377 | ```lua | ||
| 5378 | dofile: function(filename: string, env: table, config?: Config): any... | ||
| 5379 | ``` | ||
| 5380 | |||
| 5381 | **Parameter:** | ||
| 5382 | |||
| 5383 | | Parameter | Tipe | Deskripsi | | ||
| 5384 | | --------- | ------ | ------------------------- | | ||
| 5385 | | filename | string | Nama file. | | ||
| 5386 | | env | table | Tabel environment. | | ||
| 5387 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5388 | |||
| 5389 | **Return:** | ||
| 5390 | |||
| 5391 | | Tipe Return | Deskripsi | | ||
| 5392 | | ----------- | ------------------------------------- | | ||
| 5393 | | any... | Nilai return dari fungsi yang dimuat. | | ||
| 5394 | |||
| 5395 | ### dofile | ||
| 5396 | |||
| 5397 | **Tipe:** Function. | ||
| 5398 | |||
| 5399 | **Deskripsi:** | ||
| 5400 | |||
| 5401 | Memuat kode YueScript dari file menjadi fungsi dan mengeksekusinya. | ||
| 5402 | |||
| 5403 | **Signature:** | ||
| 5404 | |||
| 5405 | ```lua | ||
| 5406 | dofile: function(filename: string, config?: Config): any... | ||
| 5407 | ``` | ||
| 5408 | |||
| 5409 | **Parameter:** | ||
| 5410 | |||
| 5411 | | Parameter | Tipe | Deskripsi | | ||
| 5412 | | --------- | ------ | ------------------------- | | ||
| 5413 | | filename | string | Nama file. | | ||
| 5414 | | config | Config | [Opsional] Opsi kompiler. | | ||
| 5415 | |||
| 5416 | **Return:** | ||
| 5417 | |||
| 5418 | | Tipe Return | Deskripsi | | ||
| 5419 | | ----------- | ------------------------------------- | | ||
| 5420 | | any... | Nilai return dari fungsi yang dimuat. | | ||
| 5421 | |||
| 5422 | ### find_modulepath | ||
| 5423 | |||
| 5424 | **Tipe:** Function. | ||
| 5425 | |||
| 5426 | **Deskripsi:** | ||
| 5427 | |||
| 5428 | Menguraikan nama modul YueScript menjadi path file. | ||
| 5429 | |||
| 5430 | **Signature:** | ||
| 5431 | |||
| 5432 | ```lua | ||
| 5433 | find_modulepath: function(name: string): string | ||
| 5434 | ``` | ||
| 5435 | |||
| 5436 | **Parameter:** | ||
| 5437 | |||
| 5438 | | Parameter | Tipe | Deskripsi | | ||
| 5439 | | --------- | ------ | ----------- | | ||
| 5440 | | name | string | Nama modul. | | ||
| 5441 | |||
| 5442 | **Return:** | ||
| 5443 | |||
| 5444 | | Tipe Return | Deskripsi | | ||
| 5445 | | ----------- | ---------- | | ||
| 5446 | | string | Path file. | | ||
| 5447 | |||
| 5448 | ### pcall | ||
| 5449 | |||
| 5450 | **Tipe:** Function. | ||
| 5451 | |||
| 5452 | **Deskripsi:** | ||
| 5453 | |||
| 5454 | Memanggil fungsi dalam mode terlindungi. | ||
| 5455 | Menangkap error apa pun dan mengembalikan kode status beserta hasil atau objek error. | ||
| 5456 | Menulis ulang nomor baris error ke nomor baris asli di kode YueScript saat error terjadi. | ||
| 5457 | |||
| 5458 | **Signature:** | ||
| 5459 | |||
| 5460 | ```lua | ||
| 5461 | pcall: function(f: function, ...: any): boolean, any... | ||
| 5462 | ``` | ||
| 5463 | |||
| 5464 | **Parameter:** | ||
| 5465 | |||
| 5466 | | Parameter | Tipe | Deskripsi | | ||
| 5467 | | --------- | -------- | ---------------------------------- | | ||
| 5468 | | f | function | Fungsi yang akan dipanggil. | | ||
| 5469 | | ... | any | Argumen yang diteruskan ke fungsi. | | ||
| 5470 | |||
| 5471 | **Return:** | ||
| 5472 | |||
| 5473 | | Tipe Return | Deskripsi | | ||
| 5474 | | ------------ | ---------------------------------------------- | | ||
| 5475 | | boolean, ... | Kode status dan hasil fungsi atau objek error. | | ||
| 5476 | |||
| 5477 | ### require | ||
| 5478 | |||
| 5479 | **Tipe:** Function. | ||
| 5480 | |||
| 5481 | **Deskripsi:** | ||
| 5482 | |||
| 5483 | Memuat modul tertentu. Bisa berupa modul Lua atau modul YueScript. | ||
| 5484 | Menulis ulang nomor baris error ke nomor baris asli di kode YueScript jika modul adalah modul YueScript dan pemuatan gagal. | ||
| 5485 | |||
| 5486 | **Signature:** | ||
| 5487 | |||
| 5488 | ```lua | ||
| 5489 | require: function(name: string): any... | ||
| 5490 | ``` | ||
| 5491 | |||
| 5492 | **Parameter:** | ||
| 5493 | |||
| 5494 | | Parameter | Tipe | Deskripsi | | ||
| 5495 | | --------- | ------ | ---------------------------- | | ||
| 5496 | | modname | string | Nama modul yang akan dimuat. | | ||
| 5497 | |||
| 5498 | **Return:** | ||
| 5499 | |||
| 5500 | | Tipe Return | Deskripsi | | ||
| 5501 | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5502 | | any | Nilai yang disimpan di package.loaded[modname] jika modul sudah dimuat. Jika belum, mencoba mencari loader dan mengembalikan nilai akhir package.loaded[modname] serta data loader sebagai hasil kedua. | | ||
| 5503 | |||
| 5504 | ### p | ||
| 5505 | |||
| 5506 | **Tipe:** Function. | ||
| 5507 | |||
| 5508 | **Deskripsi:** | ||
| 5509 | |||
| 5510 | Memeriksa struktur nilai yang diteruskan dan mencetak representasi string. | ||
| 5511 | |||
| 5512 | **Signature:** | ||
| 5513 | |||
| 5514 | ```lua | ||
| 5515 | p: function(...: any) | ||
| 5516 | ``` | ||
| 5517 | |||
| 5518 | **Parameter:** | ||
| 5519 | |||
| 5520 | | Parameter | Tipe | Deskripsi | | ||
| 5521 | | --------- | ---- | -------------------------- | | ||
| 5522 | | ... | any | Nilai yang akan diperiksa. | | ||
| 5523 | |||
| 5524 | ### options | ||
| 5525 | |||
| 5526 | **Tipe:** Field. | ||
| 5527 | |||
| 5528 | **Deskripsi:** | ||
| 5529 | |||
| 5530 | Opsi kompiler saat ini. | ||
| 5531 | |||
| 5532 | **Signature:** | ||
| 5533 | |||
| 5534 | ```lua | ||
| 5535 | options: Config.Options | ||
| 5536 | ``` | ||
| 5537 | |||
| 5538 | ### traceback | ||
| 5539 | |||
| 5540 | **Tipe:** Function. | ||
| 5541 | |||
| 5542 | **Deskripsi:** | ||
| 5543 | |||
| 5544 | Fungsi traceback yang menulis ulang nomor baris stack trace ke nomor baris asli di kode YueScript. | ||
| 5545 | |||
| 5546 | **Signature:** | ||
| 5547 | |||
| 5548 | ```lua | ||
| 5549 | traceback: function(message: string): string | ||
| 5550 | ``` | ||
| 5551 | |||
| 5552 | **Parameter:** | ||
| 5553 | |||
| 5554 | | Parameter | Tipe | Deskripsi | | ||
| 5555 | | --------- | ------ | ---------------- | | ||
| 5556 | | message | string | Pesan traceback. | | ||
| 5557 | |||
| 5558 | **Return:** | ||
| 5559 | |||
| 5560 | | Tipe Return | Deskripsi | | ||
| 5561 | | ----------- | ----------------------------------------- | | ||
| 5562 | | string | Pesan traceback yang telah ditulis ulang. | | ||
| 5563 | |||
| 5564 | ### is_ast | ||
| 5565 | |||
| 5566 | **Tipe:** Function. | ||
| 5567 | |||
| 5568 | **Deskripsi:** | ||
| 5569 | |||
| 5570 | Memeriksa apakah kode cocok dengan AST yang ditentukan. | ||
| 5571 | |||
| 5572 | **Signature:** | ||
| 5573 | |||
| 5574 | ```lua | ||
| 5575 | is_ast: function(astName: string, code: string): boolean | ||
| 5576 | ``` | ||
| 5577 | |||
| 5578 | **Parameter:** | ||
| 5579 | |||
| 5580 | | Parameter | Tipe | Deskripsi | | ||
| 5581 | | --------- | ------ | --------- | | ||
| 5582 | | astName | string | Nama AST. | | ||
| 5583 | | code | string | Kode. | | ||
| 5584 | |||
| 5585 | **Return:** | ||
| 5586 | |||
| 5587 | | Tipe Return | Deskripsi | | ||
| 5588 | | ----------- | ----------------------------- | | ||
| 5589 | | boolean | Apakah kode cocok dengan AST. | | ||
| 5590 | |||
| 5591 | ### AST | ||
| 5592 | |||
| 5593 | **Tipe:** Field. | ||
| 5594 | |||
| 5595 | **Deskripsi:** | ||
| 5596 | |||
| 5597 | Definisi tipe AST dengan nama, baris, kolom, dan sub-node. | ||
| 5598 | |||
| 5599 | **Signature:** | ||
| 5600 | |||
| 5601 | ```lua | ||
| 5602 | type AST = {string, integer, integer, any} | ||
| 5603 | ``` | ||
| 5604 | |||
| 5605 | ### to_ast | ||
| 5606 | |||
| 5607 | **Tipe:** Function. | ||
| 5608 | |||
| 5609 | **Deskripsi:** | ||
| 5610 | |||
| 5611 | Mengonversi kode menjadi AST. | ||
| 5612 | |||
| 5613 | **Signature:** | ||
| 5614 | |||
| 5615 | ```lua | ||
| 5616 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): | ||
| 5617 | --[[AST]] AST | nil, | ||
| 5618 | --[[error]] nil | string | ||
| 5619 | ``` | ||
| 5620 | |||
| 5621 | **Parameter:** | ||
| 5622 | |||
| 5623 | | Parameter | Tipe | Deskripsi | | ||
| 5624 | | -------------- | ------- | ---------------------------------------------------------------------------------------- | | ||
| 5625 | | code | string | Kode. | | ||
| 5626 | | flattenLevel | integer | [Opsional] Tingkat perataan. Semakin tinggi berarti semakin rata. Default 0. Maksimum 2. | | ||
| 5627 | | astName | string | [Opsional] Nama AST. Default "File". | | ||
| 5628 | | reserveComment | boolean | [Opsional] Apakah akan mempertahankan komentar asli. Default false. | | ||
| 5629 | |||
| 5630 | **Return:** | ||
| 5631 | |||
| 5632 | | Tipe Return | Deskripsi | | ||
| 5633 | | ------------- | --------------------------------------------- | | ||
| 5634 | | AST \| nil | AST, atau nil jika konversi gagal. | | ||
| 5635 | | string \| nil | Pesan error, atau nil jika konversi berhasil. | | ||
| 5636 | |||
| 5637 | ### format | ||
| 5638 | |||
| 5639 | **Tipe:** Function. | ||
| 5640 | |||
| 5641 | **Deskripsi:** | ||
| 5642 | |||
| 5643 | Memformat kode YueScript. | ||
| 5644 | |||
| 5645 | **Signature:** | ||
| 5646 | |||
| 5647 | ```lua | ||
| 5648 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 5649 | ``` | ||
| 5650 | |||
| 5651 | **Parameter:** | ||
| 5652 | |||
| 5653 | | Parameter | Tipe | Deskripsi | | ||
| 5654 | | -------------- | ------- | ------------------------------------------------------------- | | ||
| 5655 | | code | string | Kode. | | ||
| 5656 | | tabSize | integer | [Opsional] Ukuran tab. Default 4. | | ||
| 5657 | | reserveComment | boolean | [Opsional] Apakah mempertahankan komentar asli. Default true. | | ||
| 5658 | |||
| 5659 | **Return:** | ||
| 5660 | |||
| 5661 | | Tipe Return | Deskripsi | | ||
| 5662 | | ----------- | ------------------------- | | ||
| 5663 | | string | Kode yang telah diformat. | | ||
| 5664 | |||
| 5665 | ### \_\_call | ||
| 5666 | |||
| 5667 | **Tipe:** Metamethod. | ||
| 5668 | |||
| 5669 | **Deskripsi:** | ||
| 5670 | |||
| 5671 | Me-require modul YueScript. | ||
| 5672 | Menulis ulang nomor baris error ke nomor baris asli di kode YueScript saat pemuatan gagal. | ||
| 5673 | |||
| 5674 | **Signature:** | ||
| 5675 | |||
| 5676 | ```lua | ||
| 5677 | metamethod __call: function(self: yue, module: string): any... | ||
| 5678 | ``` | ||
| 5679 | |||
| 5680 | **Parameter:** | ||
| 5681 | |||
| 5682 | | Parameter | Tipe | Deskripsi | | ||
| 5683 | | --------- | ------ | ----------- | | ||
| 5684 | | module | string | Nama modul. | | ||
| 5685 | |||
| 5686 | **Return:** | ||
| 5687 | |||
| 5688 | | Tipe Return | Deskripsi | | ||
| 5689 | | ----------- | ------------ | | ||
| 5690 | | any | Nilai modul. | | ||
| 5691 | |||
| 5692 | ## Config | ||
| 5693 | |||
| 5694 | **Deskripsi:** | ||
| 5695 | |||
| 5696 | Opsi kompilasi kompiler. | ||
| 5697 | |||
| 5698 | ### lint_global | ||
| 5699 | |||
| 5700 | **Tipe:** Field. | ||
| 5701 | |||
| 5702 | **Deskripsi:** | ||
| 5703 | |||
| 5704 | Apakah kompiler harus mengumpulkan variabel global yang muncul dalam kode. | ||
| 5705 | |||
| 5706 | **Signature:** | ||
| 5707 | |||
| 5708 | ```lua | ||
| 5709 | lint_global: boolean | ||
| 5710 | ``` | ||
| 5711 | |||
| 5712 | ### implicit_return_root | ||
| 5713 | |||
| 5714 | **Tipe:** Field. | ||
| 5715 | |||
| 5716 | **Deskripsi:** | ||
| 5717 | |||
| 5718 | Apakah kompiler harus melakukan return implisit untuk blok kode root. | ||
| 5719 | |||
| 5720 | **Signature:** | ||
| 5721 | |||
| 5722 | ```lua | ||
| 5723 | implicit_return_root: boolean | ||
| 5724 | ``` | ||
| 5725 | |||
| 5726 | ### reserve_line_number | ||
| 5727 | |||
| 5728 | **Tipe:** Field. | ||
| 5729 | |||
| 5730 | **Deskripsi:** | ||
| 5731 | |||
| 5732 | Apakah kompiler harus mempertahankan nomor baris asli di kode hasil kompilasi. | ||
| 5733 | |||
| 5734 | **Signature:** | ||
| 5735 | |||
| 5736 | ```lua | ||
| 5737 | reserve_line_number: boolean | ||
| 5738 | ``` | ||
| 5739 | |||
| 5740 | ### reserve_comment | ||
| 5741 | |||
| 5742 | **Tipe:** Field. | ||
| 5743 | |||
| 5744 | **Deskripsi:** | ||
| 5745 | |||
| 5746 | Apakah kompiler harus mempertahankan komentar asli di kode hasil kompilasi. | ||
| 5747 | |||
| 5748 | **Signature:** | ||
| 5749 | |||
| 5750 | ```lua | ||
| 5751 | reserve_comment: boolean | ||
| 5752 | ``` | ||
| 5753 | |||
| 5754 | ### space_over_tab | ||
| 5755 | |||
| 5756 | **Tipe:** Field. | ||
| 5757 | |||
| 5758 | **Deskripsi:** | ||
| 5759 | |||
| 5760 | Apakah kompiler harus menggunakan karakter spasi alih-alih tab di kode hasil kompilasi. | ||
| 5761 | |||
| 5762 | **Signature:** | ||
| 5763 | |||
| 5764 | ```lua | ||
| 5765 | space_over_tab: boolean | ||
| 5766 | ``` | ||
| 5767 | |||
| 5768 | ### same_module | ||
| 5769 | |||
| 5770 | **Tipe:** Field. | ||
| 5771 | |||
| 5772 | **Deskripsi:** | ||
| 5773 | |||
| 5774 | Apakah kompiler harus memperlakukan kode yang akan dikompilasi sebagai modul yang sama dengan modul yang sedang dikompilasi. Untuk penggunaan internal saja. | ||
| 5775 | |||
| 5776 | **Signature:** | ||
| 5777 | |||
| 5778 | ```lua | ||
| 5779 | same_module: boolean | ||
| 5780 | ``` | ||
| 5781 | |||
| 5782 | ### line_offset | ||
| 5783 | |||
| 5784 | **Tipe:** Field. | ||
| 5785 | |||
| 5786 | **Deskripsi:** | ||
| 5787 | |||
| 5788 | Apakah pesan error kompiler harus menyertakan offset nomor baris. Untuk penggunaan internal saja. | ||
| 5789 | |||
| 5790 | **Signature:** | ||
| 5791 | |||
| 5792 | ```lua | ||
| 5793 | line_offset: integer | ||
| 5794 | ``` | ||
| 5795 | |||
| 5796 | ### yue.Config.LuaTarget | ||
| 5797 | |||
| 5798 | **Tipe:** Enumeration. | ||
| 5799 | |||
| 5800 | **Deskripsi:** | ||
| 5801 | |||
| 5802 | Enumerasi versi Lua target. | ||
| 5803 | |||
| 5804 | **Signature:** | ||
| 5805 | |||
| 5806 | ```lua | ||
| 5807 | enum LuaTarget | ||
| 5808 | "5.1" | ||
| 5809 | "5.2" | ||
| 5810 | "5.3" | ||
| 5811 | "5.4" | ||
| 5812 | "5.5" | ||
| 5813 | end | ||
| 5814 | ``` | ||
| 5815 | |||
| 5816 | ### options | ||
| 5817 | |||
| 5818 | **Tipe:** Field. | ||
| 5819 | |||
| 5820 | **Deskripsi:** | ||
| 5821 | |||
| 5822 | Opsi tambahan untuk diteruskan ke fungsi kompilasi. | ||
| 5823 | |||
| 5824 | **Signature:** | ||
| 5825 | |||
| 5826 | ```lua | ||
| 5827 | options: Options | ||
| 5828 | ``` | ||
| 5829 | |||
| 5830 | ## Options | ||
| 5831 | |||
| 5832 | **Deskripsi:** | ||
| 5833 | |||
| 5834 | Definisi opsi kompiler tambahan. | ||
| 5835 | |||
| 5836 | ### target | ||
| 5837 | |||
| 5838 | **Tipe:** Field. | ||
| 5839 | |||
| 5840 | **Deskripsi:** | ||
| 5841 | |||
| 5842 | Versi Lua target untuk kompilasi. | ||
| 5843 | |||
| 5844 | **Signature:** | ||
| 5845 | |||
| 5846 | ```lua | ||
| 5847 | target: LuaTarget | ||
| 5848 | ``` | ||
| 5849 | |||
| 5850 | ### path | ||
| 5851 | |||
| 5852 | **Tipe:** Field. | ||
| 5853 | |||
| 5854 | **Deskripsi:** | ||
| 5855 | |||
| 5856 | Path pencarian modul tambahan. | ||
| 5857 | |||
| 5858 | **Signature:** | ||
| 5859 | |||
| 5860 | ```lua | ||
| 5861 | path: string | ||
| 5862 | ``` | ||
| 5863 | |||
| 5864 | ### dump_locals | ||
| 5865 | |||
| 5866 | **Tipe:** Field. | ||
| 5867 | |||
| 5868 | **Deskripsi:** | ||
| 5869 | |||
| 5870 | Apakah akan menampilkan variabel local dalam pesan error traceback. Default false. | ||
| 5871 | |||
| 5872 | **Signature:** | ||
| 5873 | |||
| 5874 | ```lua | ||
| 5875 | dump_locals: boolean | ||
| 5876 | ``` | ||
| 5877 | |||
| 5878 | ### simplified | ||
| 5879 | |||
| 5880 | **Tipe:** Field. | ||
| 5881 | |||
| 5882 | **Deskripsi:** | ||
| 5883 | |||
| 5884 | Apakah akan menyederhanakan pesan error. Default true. | ||
| 5885 | |||
| 5886 | **Signature:** | ||
| 5887 | |||
| 5888 | ```lua | ||
| 5889 | simplified: boolean | ||
| 5890 | ``` | ||
diff --git a/doc/yue-pt-br.md b/doc/yue-pt-br.md new file mode 100644 index 0000000..fccbdf6 --- /dev/null +++ b/doc/yue-pt-br.md | |||
| @@ -0,0 +1,5890 @@ | |||
| 1 | --- | ||
| 2 | title: Referência | ||
| 3 | --- | ||
| 4 | |||
| 5 | # Documentação do YueScript | ||
| 6 | |||
| 7 | <img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em; padding-bottom: 2em;"/> | ||
| 8 | |||
| 9 | Bem-vindo à documentação oficial do <b>YueScript</b>!<br/> | ||
| 10 | Aqui você encontra recursos da linguagem, uso, exemplos de referência e materiais úteis.<br/> | ||
| 11 | Selecione um capítulo na barra lateral para começar a aprender YueScript. | ||
| 12 | |||
| 13 | # Do | ||
| 14 | |||
| 15 | Quando usado como instrução, do funciona exatamente como no Lua. | ||
| 16 | |||
| 17 | ```yuescript | ||
| 18 | do | ||
| 19 | var = "hello" | ||
| 20 | print var | ||
| 21 | print var -- nil aqui | ||
| 22 | ``` | ||
| 23 | |||
| 24 | <YueDisplay> | ||
| 25 | |||
| 26 | ```yue | ||
| 27 | do | ||
| 28 | var = "hello" | ||
| 29 | print var | ||
| 30 | print var -- nil aqui | ||
| 31 | ``` | ||
| 32 | |||
| 33 | </YueDisplay> | ||
| 34 | |||
| 35 | O **do** do YueScript também pode ser usado como expressão. Permitindo combinar múltiplas linhas em uma. O resultado da expressão do é a última instrução em seu corpo. Expressões `do` suportam usar `break` para interromper o fluxo de execução e retornar múltiplos valores antecipadamente. | ||
| 36 | |||
| 37 | ```yuescript | ||
| 38 | status, value = do | ||
| 39 | n = 12 | ||
| 40 | if n > 10 | ||
| 41 | break "large", n | ||
| 42 | break "small", n | ||
| 43 | ``` | ||
| 44 | |||
| 45 | <YueDisplay> | ||
| 46 | |||
| 47 | ```yue | ||
| 48 | status, value = do | ||
| 49 | n = 12 | ||
| 50 | if n > 10 | ||
| 51 | break "large", n | ||
| 52 | break "small", n | ||
| 53 | ``` | ||
| 54 | |||
| 55 | </YueDisplay> | ||
| 56 | |||
| 57 | ```yuescript | ||
| 58 | counter = do | ||
| 59 | i = 0 | ||
| 60 | -> | ||
| 61 | i += 1 | ||
| 62 | i | ||
| 63 | |||
| 64 | print counter! | ||
| 65 | print counter! | ||
| 66 | ``` | ||
| 67 | |||
| 68 | <YueDisplay> | ||
| 69 | |||
| 70 | ```yue | ||
| 71 | counter = do | ||
| 72 | i = 0 | ||
| 73 | -> | ||
| 74 | i += 1 | ||
| 75 | i | ||
| 76 | |||
| 77 | print counter! | ||
| 78 | print counter! | ||
| 79 | ``` | ||
| 80 | |||
| 81 | </YueDisplay> | ||
| 82 | |||
| 83 | ```yuescript | ||
| 84 | tbl = { | ||
| 85 | key: do | ||
| 86 | print "assigning key!" | ||
| 87 | 1234 | ||
| 88 | } | ||
| 89 | ``` | ||
| 90 | |||
| 91 | <YueDisplay> | ||
| 92 | |||
| 93 | ```yue | ||
| 94 | tbl = { | ||
| 95 | key: do | ||
| 96 | print "assigning key!" | ||
| 97 | 1234 | ||
| 98 | } | ||
| 99 | ``` | ||
| 100 | |||
| 101 | </YueDisplay> | ||
| 102 | |||
| 103 | # Decoradores de linha | ||
| 104 | |||
| 105 | Por conveniência, o loop for e a instrução if podem ser aplicados a instruções únicas no final da linha: | ||
| 106 | |||
| 107 | ```yuescript | ||
| 108 | print "hello world" if name == "Rob" | ||
| 109 | ``` | ||
| 110 | |||
| 111 | <YueDisplay> | ||
| 112 | |||
| 113 | ```yue | ||
| 114 | print "hello world" if name == "Rob" | ||
| 115 | ``` | ||
| 116 | |||
| 117 | </YueDisplay> | ||
| 118 | |||
| 119 | E com loops básicos: | ||
| 120 | |||
| 121 | ```yuescript | ||
| 122 | print "item: ", item for item in *items | ||
| 123 | ``` | ||
| 124 | |||
| 125 | <YueDisplay> | ||
| 126 | |||
| 127 | ```yue | ||
| 128 | print "item: ", item for item in *items | ||
| 129 | ``` | ||
| 130 | |||
| 131 | </YueDisplay> | ||
| 132 | |||
| 133 | E com loops while: | ||
| 134 | |||
| 135 | ```yuescript | ||
| 136 | game\update! while game\isRunning! | ||
| 137 | |||
| 138 | reader\parse_line! until reader\eof! | ||
| 139 | ``` | ||
| 140 | |||
| 141 | <YueDisplay> | ||
| 142 | |||
| 143 | ```yue | ||
| 144 | game\update! while game\isRunning! | ||
| 145 | |||
| 146 | reader\parse_line! until reader\eof! | ||
| 147 | ``` | ||
| 148 | |||
| 149 | </YueDisplay> | ||
| 150 | |||
| 151 | # Macro | ||
| 152 | |||
| 153 | ## Uso comum | ||
| 154 | |||
| 155 | A função macro é usada para avaliar uma string em tempo de compilação e inserir os códigos gerados na compilação final. | ||
| 156 | |||
| 157 | ```yuescript | ||
| 158 | macro PI2 = -> math.pi * 2 | ||
| 159 | area = $PI2 * 5 | ||
| 160 | |||
| 161 | macro HELLO = -> "'hello world'" | ||
| 162 | print $HELLO | ||
| 163 | |||
| 164 | macro config = (debugging) -> | ||
| 165 | global debugMode = debugging == "true" | ||
| 166 | "" | ||
| 167 | |||
| 168 | macro asserts = (cond) -> | ||
| 169 | debugMode and "assert #{cond}" or "" | ||
| 170 | |||
| 171 | macro assert = (cond) -> | ||
| 172 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 173 | |||
| 174 | $config true | ||
| 175 | $asserts item ~= nil | ||
| 176 | |||
| 177 | $config false | ||
| 178 | value = $assert item | ||
| 179 | |||
| 180 | -- as expressões passadas são tratadas como strings | ||
| 181 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 182 | if $and f1!, f2!, f3! | ||
| 183 | print "OK" | ||
| 184 | ``` | ||
| 185 | |||
| 186 | <YueDisplay> | ||
| 187 | |||
| 188 | ```yue | ||
| 189 | macro PI2 = -> math.pi * 2 | ||
| 190 | area = $PI2 * 5 | ||
| 191 | |||
| 192 | macro HELLO = -> "'hello world'" | ||
| 193 | print $HELLO | ||
| 194 | |||
| 195 | macro config = (debugging) -> | ||
| 196 | global debugMode = debugging == "true" | ||
| 197 | "" | ||
| 198 | |||
| 199 | macro asserts = (cond) -> | ||
| 200 | debugMode and "assert #{cond}" or "" | ||
| 201 | |||
| 202 | macro assert = (cond) -> | ||
| 203 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 204 | |||
| 205 | $config true | ||
| 206 | $asserts item ~= nil | ||
| 207 | |||
| 208 | $config false | ||
| 209 | value = $assert item | ||
| 210 | |||
| 211 | -- as expressões passadas são tratadas como strings | ||
| 212 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 213 | if $and f1!, f2!, f3! | ||
| 214 | print "OK" | ||
| 215 | ``` | ||
| 216 | |||
| 217 | </YueDisplay> | ||
| 218 | |||
| 219 | ## Inserir códigos brutos | ||
| 220 | |||
| 221 | Uma função macro pode retornar uma string YueScript ou uma tabela de configuração contendo códigos Lua. | ||
| 222 | |||
| 223 | ```yuescript | ||
| 224 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 225 | $yueFunc funcA | ||
| 226 | funcA = -> "fail to assign to the Yue macro defined variable" | ||
| 227 | |||
| 228 | macro luaFunc = (var) -> { | ||
| 229 | code: "local function #{var}() end" | ||
| 230 | type: "lua" | ||
| 231 | } | ||
| 232 | $luaFunc funcB | ||
| 233 | funcB = -> "fail to assign to the Lua macro defined variable" | ||
| 234 | |||
| 235 | macro lua = (code) -> { | ||
| 236 | :code | ||
| 237 | type: "lua" | ||
| 238 | } | ||
| 239 | |||
| 240 | -- os símbolos inicial e final da string bruta são aparados automaticamente | ||
| 241 | $lua[==[ | ||
| 242 | -- inserção de códigos Lua brutos | ||
| 243 | if cond then | ||
| 244 | print("output") | ||
| 245 | end | ||
| 246 | ]==] | ||
| 247 | ``` | ||
| 248 | |||
| 249 | <YueDisplay> | ||
| 250 | |||
| 251 | ```yue | ||
| 252 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 253 | $yueFunc funcA | ||
| 254 | funcA = -> "fail to assign to the Yue macro defined variable" | ||
| 255 | |||
| 256 | macro luaFunc = (var) -> { | ||
| 257 | code: "local function #{var}() end" | ||
| 258 | type: "lua" | ||
| 259 | } | ||
| 260 | $luaFunc funcB | ||
| 261 | funcB = -> "fail to assign to the Lua macro defined variable" | ||
| 262 | |||
| 263 | macro lua = (code) -> { | ||
| 264 | :code | ||
| 265 | type: "lua" | ||
| 266 | } | ||
| 267 | |||
| 268 | -- os símbolos inicial e final da string bruta são aparados automaticamente | ||
| 269 | $lua[==[ | ||
| 270 | -- inserção de códigos Lua brutos | ||
| 271 | if cond then | ||
| 272 | print("output") | ||
| 273 | end | ||
| 274 | ]==] | ||
| 275 | ``` | ||
| 276 | |||
| 277 | </YueDisplay> | ||
| 278 | |||
| 279 | ## Exportar macro | ||
| 280 | |||
| 281 | Funções macro podem ser exportadas de um módulo e importadas em outro módulo. Você deve colocar funções export macro em um único arquivo para uso, e apenas definição de macro, importação de macro e expansão de macro inline podem ser colocadas no módulo exportador de macro. | ||
| 282 | |||
| 283 | ```yuescript | ||
| 284 | -- arquivo: utils.yue | ||
| 285 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 286 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 287 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 288 | #{action}" | ||
| 289 | |||
| 290 | -- arquivo main.yue | ||
| 291 | import "utils" as { | ||
| 292 | $, -- símbolo para importar todas as macros | ||
| 293 | $foreach: $each -- renomear macro $foreach para $each | ||
| 294 | } | ||
| 295 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 296 | ``` | ||
| 297 | |||
| 298 | <YueDisplay> | ||
| 299 | |||
| 300 | ```yue | ||
| 301 | -- arquivo: utils.yue | ||
| 302 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 303 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 304 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 305 | #{action}" | ||
| 306 | |||
| 307 | -- arquivo main.yue | ||
| 308 | --[[ | ||
| 309 | import "utils" as { | ||
| 310 | $, -- símbolo para importar todas as macros | ||
| 311 | $foreach: $each -- renomear macro $foreach para $each | ||
| 312 | } | ||
| 313 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 314 | ]] | ||
| 315 | ``` | ||
| 316 | |||
| 317 | </YueDisplay> | ||
| 318 | |||
| 319 | ## Macro embutida | ||
| 320 | |||
| 321 | Existem algumas macros embutidas, mas você pode sobrescrevê-las declarando macros com os mesmos nomes. | ||
| 322 | |||
| 323 | ```yuescript | ||
| 324 | print $FILE -- obtém string do nome do módulo atual | ||
| 325 | print $LINE -- obtém número 2 | ||
| 326 | ``` | ||
| 327 | |||
| 328 | <YueDisplay> | ||
| 329 | |||
| 330 | ```yue | ||
| 331 | print $FILE -- obtém string do nome do módulo atual | ||
| 332 | print $LINE -- obtém número 2 | ||
| 333 | ``` | ||
| 334 | |||
| 335 | </YueDisplay> | ||
| 336 | |||
| 337 | ## Gerando macros com macros | ||
| 338 | |||
| 339 | No YueScript, as funções macro permitem que você gere código em tempo de compilação. Aninhando funções macro, você pode criar padrões de geração mais complexos. Este recurso permite que você defina uma função macro que gera outra função macro, permitindo geração de código mais dinâmica. | ||
| 340 | |||
| 341 | ```yuescript | ||
| 342 | macro Enum = (...) -> | ||
| 343 | items = {...} | ||
| 344 | itemSet = {item, true for item in *items} | ||
| 345 | (item) -> | ||
| 346 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 347 | "\"#{item}\"" | ||
| 348 | |||
| 349 | macro BodyType = $Enum( | ||
| 350 | Static | ||
| 351 | Dynamic | ||
| 352 | Kinematic | ||
| 353 | ) | ||
| 354 | |||
| 355 | print "Valid enum type:", $BodyType Static | ||
| 356 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 357 | ``` | ||
| 358 | |||
| 359 | <YueDisplay> | ||
| 360 | |||
| 361 | ```yue | ||
| 362 | macro Enum = (...) -> | ||
| 363 | items = {...} | ||
| 364 | itemSet = {item, true for item in *items} | ||
| 365 | (item) -> | ||
| 366 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 367 | "\"#{item}\"" | ||
| 368 | |||
| 369 | macro BodyType = $Enum( | ||
| 370 | Static | ||
| 371 | Dynamic | ||
| 372 | Kinematic | ||
| 373 | ) | ||
| 374 | |||
| 375 | print "Valid enum type:", $BodyType Static | ||
| 376 | -- print "Compilation error with enum type:", $BodyType Unknown | ||
| 377 | ``` | ||
| 378 | |||
| 379 | </YueDisplay> | ||
| 380 | |||
| 381 | ## Validação de argumentos | ||
| 382 | |||
| 383 | Você pode declarar os tipos de nós AST esperados na lista de argumentos e verificar se os argumentos da macro recebidos atendem às expectativas em tempo de compilação. | ||
| 384 | |||
| 385 | ```yuescript | ||
| 386 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 387 | print( | ||
| 388 | #{num} | ||
| 389 | #{str} | ||
| 390 | ) | ||
| 391 | |||
| 392 | $printNumAndStr 123, "hello" | ||
| 393 | ``` | ||
| 394 | |||
| 395 | <YueDisplay> | ||
| 396 | |||
| 397 | ```yue | ||
| 398 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 399 | print( | ||
| 400 | #{num} | ||
| 401 | #{str} | ||
| 402 | ) | ||
| 403 | |||
| 404 | $printNumAndStr 123, "hello" | ||
| 405 | ``` | ||
| 406 | |||
| 407 | </YueDisplay> | ||
| 408 | |||
| 409 | Se você precisar de verificação de argumentos mais flexível, pode usar a função macro embutida `$is_ast` para verificar manualmente no lugar apropriado. | ||
| 410 | |||
| 411 | ```yuescript | ||
| 412 | macro printNumAndStr = (num, str) -> | ||
| 413 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 414 | error "expected String as second argument" unless $is_ast String, str | ||
| 415 | "print(#{num}, #{str})" | ||
| 416 | |||
| 417 | $printNumAndStr 123, "hello" | ||
| 418 | ``` | ||
| 419 | |||
| 420 | <YueDisplay> | ||
| 421 | |||
| 422 | ```yue | ||
| 423 | macro printNumAndStr = (num, str) -> | ||
| 424 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 425 | error "expected String as second argument" unless $is_ast String, str | ||
| 426 | "print(#{num}, #{str})" | ||
| 427 | |||
| 428 | $printNumAndStr 123, "hello" | ||
| 429 | ``` | ||
| 430 | |||
| 431 | </YueDisplay> | ||
| 432 | |||
| 433 | Para mais detalhes sobre os nós AST disponíveis, consulte as definições em maiúsculas em [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
| 434 | |||
| 435 | # Try | ||
| 436 | |||
| 437 | A sintaxe para tratamento de erros do Lua em uma forma comum. | ||
| 438 | |||
| 439 | ```yuescript | ||
| 440 | try | ||
| 441 | func 1, 2, 3 | ||
| 442 | catch err | ||
| 443 | print yue.traceback err | ||
| 444 | |||
| 445 | success, result = try | ||
| 446 | func 1, 2, 3 | ||
| 447 | catch err | ||
| 448 | yue.traceback err | ||
| 449 | |||
| 450 | try func 1, 2, 3 | ||
| 451 | catch err | ||
| 452 | print yue.traceback err | ||
| 453 | |||
| 454 | success, result = try func 1, 2, 3 | ||
| 455 | |||
| 456 | try | ||
| 457 | print "trying" | ||
| 458 | func 1, 2, 3 | ||
| 459 | |||
| 460 | -- funcionando com padrão de atribuição em if | ||
| 461 | if success, result := try func 1, 2, 3 | ||
| 462 | catch err | ||
| 463 | print yue.traceback err | ||
| 464 | print result | ||
| 465 | ``` | ||
| 466 | |||
| 467 | <YueDisplay> | ||
| 468 | |||
| 469 | ```yue | ||
| 470 | try | ||
| 471 | func 1, 2, 3 | ||
| 472 | catch err | ||
| 473 | print yue.traceback err | ||
| 474 | |||
| 475 | success, result = try | ||
| 476 | func 1, 2, 3 | ||
| 477 | catch err | ||
| 478 | yue.traceback err | ||
| 479 | |||
| 480 | try func 1, 2, 3 | ||
| 481 | catch err | ||
| 482 | print yue.traceback err | ||
| 483 | |||
| 484 | success, result = try func 1, 2, 3 | ||
| 485 | |||
| 486 | try | ||
| 487 | print "trying" | ||
| 488 | func 1, 2, 3 | ||
| 489 | |||
| 490 | -- funcionando com padrão de atribuição em if | ||
| 491 | if success, result := try func 1, 2, 3 | ||
| 492 | catch err | ||
| 493 | print yue.traceback err | ||
| 494 | print result | ||
| 495 | ``` | ||
| 496 | |||
| 497 | </YueDisplay> | ||
| 498 | |||
| 499 | ## Try? | ||
| 500 | |||
| 501 | `try?` é um uso simplificado para sintaxe de tratamento de erros que omite o status booleano da instrução `try`, e retornará o resultado do bloco try quando tiver sucesso, retornando nil em vez do objeto de erro caso contrário. | ||
| 502 | |||
| 503 | ```yuescript | ||
| 504 | a, b, c = try? func! | ||
| 505 | |||
| 506 | -- com operador de coalescência de nil | ||
| 507 | a = (try? func!) ?? "default" | ||
| 508 | |||
| 509 | -- como argumento de função | ||
| 510 | f try? func! | ||
| 511 | |||
| 512 | -- com bloco catch | ||
| 513 | f try? | ||
| 514 | print 123 | ||
| 515 | func! | ||
| 516 | catch e | ||
| 517 | print e | ||
| 518 | e | ||
| 519 | ``` | ||
| 520 | |||
| 521 | <YueDisplay> | ||
| 522 | |||
| 523 | ```yue | ||
| 524 | a, b, c = try? func! | ||
| 525 | |||
| 526 | -- com operador de coalescência de nil | ||
| 527 | a = (try? func!) ?? "default" | ||
| 528 | |||
| 529 | -- como argumento de função | ||
| 530 | f try? func! | ||
| 531 | |||
| 532 | -- com bloco catch | ||
| 533 | f try? | ||
| 534 | print 123 | ||
| 535 | func! | ||
| 536 | catch e | ||
| 537 | print e | ||
| 538 | e | ||
| 539 | ``` | ||
| 540 | |||
| 541 | </YueDisplay> | ||
| 542 | |||
| 543 | # Literais de tabela | ||
| 544 | |||
| 545 | Como no Lua, as tabelas são delimitadas por chaves. | ||
| 546 | |||
| 547 | ```yuescript | ||
| 548 | some_values = [1, 2, 3, 4] | ||
| 549 | ``` | ||
| 550 | |||
| 551 | <YueDisplay> | ||
| 552 | |||
| 553 | ```yue | ||
| 554 | some_values = [1, 2, 3, 4] | ||
| 555 | ``` | ||
| 556 | |||
| 557 | </YueDisplay> | ||
| 558 | |||
| 559 | Diferente do Lua, atribuir um valor a uma chave em uma tabela é feito com **:** (em vez de **=**). | ||
| 560 | |||
| 561 | ```yuescript | ||
| 562 | some_values = { | ||
| 563 | name: "Bill", | ||
| 564 | age: 200, | ||
| 565 | ["favorite food"]: "rice" | ||
| 566 | } | ||
| 567 | ``` | ||
| 568 | |||
| 569 | <YueDisplay> | ||
| 570 | |||
| 571 | ```yue | ||
| 572 | some_values = { | ||
| 573 | name: "Bill", | ||
| 574 | age: 200, | ||
| 575 | ["favorite food"]: "rice" | ||
| 576 | } | ||
| 577 | ``` | ||
| 578 | |||
| 579 | </YueDisplay> | ||
| 580 | |||
| 581 | As chaves podem ser omitidas se uma única tabela de pares chave-valor está sendo atribuída. | ||
| 582 | |||
| 583 | ```yuescript | ||
| 584 | profile = | ||
| 585 | height: "4 feet", | ||
| 586 | shoe_size: 13, | ||
| 587 | favorite_foods: ["ice cream", "donuts"] | ||
| 588 | ``` | ||
| 589 | |||
| 590 | <YueDisplay> | ||
| 591 | |||
| 592 | ```yue | ||
| 593 | profile = | ||
| 594 | height: "4 feet", | ||
| 595 | shoe_size: 13, | ||
| 596 | favorite_foods: ["ice cream", "donuts"] | ||
| 597 | ``` | ||
| 598 | |||
| 599 | </YueDisplay> | ||
| 600 | |||
| 601 | Quebras de linha podem ser usadas para delimitar valores em vez de vírgula (ou ambos): | ||
| 602 | |||
| 603 | ```yuescript | ||
| 604 | values = { | ||
| 605 | 1, 2, 3, 4 | ||
| 606 | 5, 6, 7, 8 | ||
| 607 | name: "superman" | ||
| 608 | occupation: "crime fighting" | ||
| 609 | } | ||
| 610 | ``` | ||
| 611 | |||
| 612 | <YueDisplay> | ||
| 613 | |||
| 614 | ```yue | ||
| 615 | values = { | ||
| 616 | 1, 2, 3, 4 | ||
| 617 | 5, 6, 7, 8 | ||
| 618 | name: "superman" | ||
| 619 | occupation: "crime fighting" | ||
| 620 | } | ||
| 621 | ``` | ||
| 622 | |||
| 623 | </YueDisplay> | ||
| 624 | |||
| 625 | Ao criar um literal de tabela em uma única linha, as chaves também podem ser omitidas: | ||
| 626 | |||
| 627 | ```yuescript | ||
| 628 | my_function dance: "Tango", partner: "none" | ||
| 629 | |||
| 630 | y = type: "dog", legs: 4, tails: 1 | ||
| 631 | ``` | ||
| 632 | |||
| 633 | <YueDisplay> | ||
| 634 | |||
| 635 | ```yue | ||
| 636 | my_function dance: "Tango", partner: "none" | ||
| 637 | |||
| 638 | y = type: "dog", legs: 4, tails: 1 | ||
| 639 | ``` | ||
| 640 | |||
| 641 | </YueDisplay> | ||
| 642 | |||
| 643 | As chaves de um literal de tabela podem ser palavras-chave da linguagem sem precisar escapar: | ||
| 644 | |||
| 645 | ```yuescript | ||
| 646 | tbl = { | ||
| 647 | do: "something" | ||
| 648 | end: "hunger" | ||
| 649 | } | ||
| 650 | ``` | ||
| 651 | |||
| 652 | <YueDisplay> | ||
| 653 | |||
| 654 | ```yue | ||
| 655 | tbl = { | ||
| 656 | do: "something" | ||
| 657 | end: "hunger" | ||
| 658 | } | ||
| 659 | ``` | ||
| 660 | |||
| 661 | </YueDisplay> | ||
| 662 | |||
| 663 | Se você está construindo uma tabela a partir de variáveis e deseja que as chaves sejam iguais aos nomes das variáveis, então o operador de prefixo **:** pode ser usado: | ||
| 664 | |||
| 665 | ```yuescript | ||
| 666 | hair = "golden" | ||
| 667 | height = 200 | ||
| 668 | person = { :hair, :height, shoe_size: 40 } | ||
| 669 | |||
| 670 | print_table :hair, :height | ||
| 671 | ``` | ||
| 672 | |||
| 673 | <YueDisplay> | ||
| 674 | |||
| 675 | ```yue | ||
| 676 | hair = "golden" | ||
| 677 | height = 200 | ||
| 678 | person = { :hair, :height, shoe_size: 40 } | ||
| 679 | |||
| 680 | print_table :hair, :height | ||
| 681 | ``` | ||
| 682 | |||
| 683 | </YueDisplay> | ||
| 684 | |||
| 685 | Se você quiser que a chave de um campo na tabela seja o resultado de uma expressão, então pode envolvê-la em **[ ]**, assim como no Lua. Você também pode usar um literal de string diretamente como chave, omitindo os colchetes. Isso é útil se sua chave tiver caracteres especiais. | ||
| 686 | |||
| 687 | ```yuescript | ||
| 688 | t = { | ||
| 689 | [1 + 2]: "hello" | ||
| 690 | "hello world": true | ||
| 691 | } | ||
| 692 | ``` | ||
| 693 | |||
| 694 | <YueDisplay> | ||
| 695 | |||
| 696 | ```yue | ||
| 697 | t = { | ||
| 698 | [1 + 2]: "hello" | ||
| 699 | "hello world": true | ||
| 700 | } | ||
| 701 | ``` | ||
| 702 | |||
| 703 | </YueDisplay> | ||
| 704 | |||
| 705 | As tabelas Lua têm tanto uma parte array quanto uma parte hash, mas às vezes você quer fazer uma distinção semântica entre uso de array e hash ao escrever tabelas Lua. Então você pode escrever tabela Lua com **[ ]** em vez de **{ }** para representar uma tabela array, e escrever qualquer par chave-valor em uma tabela lista não será permitido. | ||
| 706 | |||
| 707 | ```yuescript | ||
| 708 | some_values = [1, 2, 3, 4] | ||
| 709 | list_with_one_element = [1, ] | ||
| 710 | ``` | ||
| 711 | |||
| 712 | <YueDisplay> | ||
| 713 | |||
| 714 | ```yue | ||
| 715 | some_values = [1, 2, 3, 4] | ||
| 716 | list_with_one_element = [1, ] | ||
| 717 | ``` | ||
| 718 | |||
| 719 | </YueDisplay> | ||
| 720 | |||
| 721 | # Compreensões | ||
| 722 | |||
| 723 | As compreensões fornecem uma sintaxe conveniente para construir uma nova tabela iterando sobre algum objeto existente e aplicando uma expressão a seus valores. Existem dois tipos de compreensões: compreensões de lista e compreensões de tabela. Ambas produzem tabelas Lua; as compreensões de lista acumulam valores em uma tabela semelhante a array, e as compreensões de tabela permitem definir tanto a chave quanto o valor em cada iteração. | ||
| 724 | |||
| 725 | ## Compreensões de lista | ||
| 726 | |||
| 727 | O seguinte cria uma cópia da tabela items mas com todos os valores dobrados. | ||
| 728 | |||
| 729 | ```yuescript | ||
| 730 | items = [ 1, 2, 3, 4 ] | ||
| 731 | doubled = [item * 2 for i, item in ipairs items] | ||
| 732 | ``` | ||
| 733 | |||
| 734 | <YueDisplay> | ||
| 735 | |||
| 736 | ```yue | ||
| 737 | items = [ 1, 2, 3, 4 ] | ||
| 738 | doubled = [item * 2 for i, item in ipairs items] | ||
| 739 | ``` | ||
| 740 | |||
| 741 | </YueDisplay> | ||
| 742 | |||
| 743 | Os itens incluídos na nova tabela podem ser restringidos com uma cláusula when: | ||
| 744 | |||
| 745 | ```yuescript | ||
| 746 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 747 | ``` | ||
| 748 | |||
| 749 | <YueDisplay> | ||
| 750 | |||
| 751 | ```yue | ||
| 752 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 753 | ``` | ||
| 754 | |||
| 755 | </YueDisplay> | ||
| 756 | |||
| 757 | Como é comum iterar sobre os valores de uma tabela indexada numericamente, um operador **\*** é introduzido. O exemplo doubled pode ser reescrito como: | ||
| 758 | |||
| 759 | ```yuescript | ||
| 760 | doubled = [item * 2 for item in *items] | ||
| 761 | ``` | ||
| 762 | |||
| 763 | <YueDisplay> | ||
| 764 | |||
| 765 | ```yue | ||
| 766 | doubled = [item * 2 for item in *items] | ||
| 767 | ``` | ||
| 768 | |||
| 769 | </YueDisplay> | ||
| 770 | |||
| 771 | Nas compreensões de lista, você também pode usar o operador spread `...` para achatar listas aninhadas, alcançando um efeito de flat map: | ||
| 772 | |||
| 773 | ```yuescript | ||
| 774 | data = | ||
| 775 | a: [1, 2, 3] | ||
| 776 | b: [4, 5, 6] | ||
| 777 | |||
| 778 | flat = [...v for k,v in pairs data] | ||
| 779 | -- flat agora é [1, 2, 3, 4, 5, 6] | ||
| 780 | ``` | ||
| 781 | |||
| 782 | <YueDisplay> | ||
| 783 | |||
| 784 | ```yue | ||
| 785 | data = | ||
| 786 | a: [1, 2, 3] | ||
| 787 | b: [4, 5, 6] | ||
| 788 | |||
| 789 | flat = [...v for k,v in pairs data] | ||
| 790 | -- flat agora é [1, 2, 3, 4, 5, 6] | ||
| 791 | ``` | ||
| 792 | |||
| 793 | </YueDisplay> | ||
| 794 | |||
| 795 | As cláusulas for e when podem ser encadeadas tanto quanto desejado. O único requisito é que uma compreensão tenha pelo menos uma cláusula for. | ||
| 796 | |||
| 797 | Usar múltiplas cláusulas for é o mesmo que usar loops aninhados: | ||
| 798 | |||
| 799 | ```yuescript | ||
| 800 | x_coords = [4, 5, 6, 7] | ||
| 801 | y_coords = [9, 2, 3] | ||
| 802 | |||
| 803 | points = [ [x, y] for x in *x_coords \ | ||
| 804 | for y in *y_coords] | ||
| 805 | ``` | ||
| 806 | |||
| 807 | <YueDisplay> | ||
| 808 | |||
| 809 | ```yue | ||
| 810 | x_coords = [4, 5, 6, 7] | ||
| 811 | y_coords = [9, 2, 3] | ||
| 812 | |||
| 813 | points = [ [x, y] for x in *x_coords \ | ||
| 814 | for y in *y_coords] | ||
| 815 | ``` | ||
| 816 | |||
| 817 | </YueDisplay> | ||
| 818 | |||
| 819 | Loops for numéricos também podem ser usados em compreensões: | ||
| 820 | |||
| 821 | ```yuescript | ||
| 822 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 823 | ``` | ||
| 824 | |||
| 825 | <YueDisplay> | ||
| 826 | |||
| 827 | ```yue | ||
| 828 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 829 | ``` | ||
| 830 | |||
| 831 | </YueDisplay> | ||
| 832 | |||
| 833 | ## Compreensões de tabela | ||
| 834 | |||
| 835 | A sintaxe para compreensões de tabela é muito semelhante, diferindo apenas por usar **{** e **}** e receber dois valores de cada iteração. | ||
| 836 | |||
| 837 | Este exemplo faz uma cópia da tabela thing: | ||
| 838 | |||
| 839 | ```yuescript | ||
| 840 | thing = { | ||
| 841 | color: "red" | ||
| 842 | name: "fast" | ||
| 843 | width: 123 | ||
| 844 | } | ||
| 845 | |||
| 846 | thing_copy = {k, v for k, v in pairs thing} | ||
| 847 | ``` | ||
| 848 | |||
| 849 | <YueDisplay> | ||
| 850 | |||
| 851 | ```yue | ||
| 852 | thing = { | ||
| 853 | color: "red" | ||
| 854 | name: "fast" | ||
| 855 | width: 123 | ||
| 856 | } | ||
| 857 | |||
| 858 | thing_copy = {k, v for k, v in pairs thing} | ||
| 859 | ``` | ||
| 860 | |||
| 861 | </YueDisplay> | ||
| 862 | |||
| 863 | ```yuescript | ||
| 864 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 865 | ``` | ||
| 866 | |||
| 867 | <YueDisplay> | ||
| 868 | |||
| 869 | ```yue | ||
| 870 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 871 | ``` | ||
| 872 | |||
| 873 | </YueDisplay> | ||
| 874 | |||
| 875 | O operador **\*** também é suportado. Aqui criamos uma tabela de consulta de raiz quadrada para alguns números. | ||
| 876 | |||
| 877 | ```yuescript | ||
| 878 | numbers = [1, 2, 3, 4] | ||
| 879 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 880 | ``` | ||
| 881 | |||
| 882 | <YueDisplay> | ||
| 883 | |||
| 884 | ```yue | ||
| 885 | numbers = [1, 2, 3, 4] | ||
| 886 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 887 | ``` | ||
| 888 | |||
| 889 | </YueDisplay> | ||
| 890 | |||
| 891 | A tupla chave-valor em uma compreensão de tabela também pode vir de uma única expressão, caso em que a expressão deve retornar dois valores. O primeiro é usado como chave e o segundo é usado como valor: | ||
| 892 | |||
| 893 | Neste exemplo convertemos um array de pares em uma tabela onde o primeiro item do par é a chave e o segundo é o valor. | ||
| 894 | |||
| 895 | ```yuescript | ||
| 896 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 897 | tbl = {unpack tuple for tuple in *tuples} | ||
| 898 | ``` | ||
| 899 | |||
| 900 | <YueDisplay> | ||
| 901 | |||
| 902 | ```yue | ||
| 903 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 904 | tbl = {unpack tuple for tuple in *tuples} | ||
| 905 | ``` | ||
| 906 | |||
| 907 | </YueDisplay> | ||
| 908 | |||
| 909 | ## Slicing | ||
| 910 | |||
| 911 | Uma sintaxe especial é fornecida para restringir os itens sobre os quais se itera ao usar o operador **\***. Isso é equivalente a definir os limites de iteração e um tamanho de passo em um loop for. | ||
| 912 | |||
| 913 | Aqui podemos definir os limites mínimo e máximo, pegando todos os itens com índices entre 1 e 5 inclusive: | ||
| 914 | |||
| 915 | ```yuescript | ||
| 916 | slice = [item for item in *items[1, 5]] | ||
| 917 | ``` | ||
| 918 | |||
| 919 | <YueDisplay> | ||
| 920 | |||
| 921 | ```yue | ||
| 922 | slice = [item for item in *items[1, 5]] | ||
| 923 | ``` | ||
| 924 | |||
| 925 | </YueDisplay> | ||
| 926 | |||
| 927 | Qualquer um dos argumentos do slice pode ser omitido para usar um padrão sensato. Neste exemplo, se o índice máximo for omitido, ele usa como padrão o comprimento da tabela. Isso pegará tudo exceto o primeiro elemento: | ||
| 928 | |||
| 929 | ```yuescript | ||
| 930 | slice = [item for item in *items[2,]] | ||
| 931 | ``` | ||
| 932 | |||
| 933 | <YueDisplay> | ||
| 934 | |||
| 935 | ```yue | ||
| 936 | slice = [item for item in *items[2,]] | ||
| 937 | ``` | ||
| 938 | |||
| 939 | </YueDisplay> | ||
| 940 | |||
| 941 | Se o limite mínimo for omitido, ele usa como padrão 1. Aqui fornecemos apenas um tamanho de passo e deixamos os outros limites em branco. Isso pega todos os itens com índice ímpar: (1, 3, 5, …) | ||
| 942 | |||
| 943 | ```yuescript | ||
| 944 | slice = [item for item in *items[,,2]] | ||
| 945 | ``` | ||
| 946 | |||
| 947 | <YueDisplay> | ||
| 948 | |||
| 949 | ```yue | ||
| 950 | slice = [item for item in *items[,,2]] | ||
| 951 | ``` | ||
| 952 | |||
| 953 | </YueDisplay> | ||
| 954 | |||
| 955 | Tanto o limite mínimo quanto o máximo podem ser negativos, o que significa que os limites são contados a partir do fim da tabela. | ||
| 956 | |||
| 957 | ```yuescript | ||
| 958 | -- pegar os últimos 4 itens | ||
| 959 | slice = [item for item in *items[-4,-1]] | ||
| 960 | ``` | ||
| 961 | |||
| 962 | <YueDisplay> | ||
| 963 | |||
| 964 | ```yue | ||
| 965 | -- pegar os últimos 4 itens | ||
| 966 | slice = [item for item in *items[-4,-1]] | ||
| 967 | ``` | ||
| 968 | |||
| 969 | </YueDisplay> | ||
| 970 | |||
| 971 | O tamanho do passo também pode ser negativo, o que significa que os itens são tomados em ordem reversa. | ||
| 972 | |||
| 973 | ```yuescript | ||
| 974 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 975 | ``` | ||
| 976 | |||
| 977 | <YueDisplay> | ||
| 978 | |||
| 979 | ```yue | ||
| 980 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 981 | ``` | ||
| 982 | |||
| 983 | </YueDisplay> | ||
| 984 | |||
| 985 | ### Expressão de slicing | ||
| 986 | |||
| 987 | O slicing também pode ser usado como expressão. Isso é útil para obter uma sublista de uma tabela. | ||
| 988 | |||
| 989 | ```yuescript | ||
| 990 | -- pegar o 2º e 4º itens como nova lista | ||
| 991 | sub_list = items[2, 4] | ||
| 992 | |||
| 993 | -- pegar os últimos 4 itens | ||
| 994 | last_four_items = items[-4, -1] | ||
| 995 | ``` | ||
| 996 | |||
| 997 | <YueDisplay> | ||
| 998 | |||
| 999 | ```yue | ||
| 1000 | -- pegar o 2º e 4º itens como nova lista | ||
| 1001 | sub_list = items[2, 4] | ||
| 1002 | |||
| 1003 | -- pegar os últimos 4 itens | ||
| 1004 | last_four_items = items[-4, -1] | ||
| 1005 | ``` | ||
| 1006 | |||
| 1007 | </YueDisplay> | ||
| 1008 | |||
| 1009 | # Programação orientada a objetos | ||
| 1010 | |||
| 1011 | Nestes exemplos, o código Lua gerado pode parecer avassalador. É melhor focar primeiro no significado do código YueScript e depois olhar o código Lua se desejar conhecer os detalhes da implementação. | ||
| 1012 | |||
| 1013 | Uma classe simples: | ||
| 1014 | |||
| 1015 | ```yuescript | ||
| 1016 | class Inventory | ||
| 1017 | new: => | ||
| 1018 | @items = {} | ||
| 1019 | |||
| 1020 | add_item: (name) => | ||
| 1021 | if @items[name] | ||
| 1022 | @items[name] += 1 | ||
| 1023 | else | ||
| 1024 | @items[name] = 1 | ||
| 1025 | ``` | ||
| 1026 | |||
| 1027 | <YueDisplay> | ||
| 1028 | |||
| 1029 | ```yue | ||
| 1030 | class Inventory | ||
| 1031 | new: => | ||
| 1032 | @items = {} | ||
| 1033 | |||
| 1034 | add_item: (name) => | ||
| 1035 | if @items[name] | ||
| 1036 | @items[name] += 1 | ||
| 1037 | else | ||
| 1038 | @items[name] = 1 | ||
| 1039 | ``` | ||
| 1040 | |||
| 1041 | </YueDisplay> | ||
| 1042 | |||
| 1043 | Uma classe é declarada com uma instrução class seguida de uma declaração semelhante a tabela onde todos os métodos e propriedades são listados. | ||
| 1044 | |||
| 1045 | A propriedade new é especial pois se tornará o construtor. | ||
| 1046 | |||
| 1047 | Observe como todos os métodos da classe usam a sintaxe de função seta fat. Ao chamar métodos em uma instância, a própria instância é enviada como primeiro argumento. A seta fat cuida da criação do argumento self. | ||
| 1048 | |||
| 1049 | O prefixo @ em um nome de variável é abreviação para self.. @items torna-se self.items. | ||
| 1050 | |||
| 1051 | Criar uma instância da classe é feito chamando o nome da classe como uma função. | ||
| 1052 | |||
| 1053 | ```yuescript | ||
| 1054 | inv = Inventory! | ||
| 1055 | inv\add_item "t-shirt" | ||
| 1056 | inv\add_item "pants" | ||
| 1057 | ``` | ||
| 1058 | |||
| 1059 | <YueDisplay> | ||
| 1060 | |||
| 1061 | ```yue | ||
| 1062 | inv = Inventory! | ||
| 1063 | inv\add_item "t-shirt" | ||
| 1064 | inv\add_item "pants" | ||
| 1065 | ``` | ||
| 1066 | |||
| 1067 | </YueDisplay> | ||
| 1068 | |||
| 1069 | Como a instância da classe precisa ser enviada aos métodos quando são chamados, o operador \ é usado. | ||
| 1070 | |||
| 1071 | Todas as propriedades de uma classe são compartilhadas entre as instâncias. Isso é bom para funções, mas para outros tipos de objetos, resultados indesejados podem ocorrer. | ||
| 1072 | |||
| 1073 | Considere o exemplo abaixo, a propriedade clothes é compartilhada entre todas as instâncias, então modificações nela em uma instância aparecerão em outra: | ||
| 1074 | |||
| 1075 | ```yuescript | ||
| 1076 | class Person | ||
| 1077 | clothes: [] | ||
| 1078 | give_item: (name) => | ||
| 1079 | table.insert @clothes, name | ||
| 1080 | |||
| 1081 | a = Person! | ||
| 1082 | b = Person! | ||
| 1083 | |||
| 1084 | a\give_item "pants" | ||
| 1085 | b\give_item "shirt" | ||
| 1086 | |||
| 1087 | -- vai imprimir tanto pants quanto shirt | ||
| 1088 | print item for item in *a.clothes | ||
| 1089 | ``` | ||
| 1090 | |||
| 1091 | <YueDisplay> | ||
| 1092 | |||
| 1093 | ```yue | ||
| 1094 | class Person | ||
| 1095 | clothes: [] | ||
| 1096 | give_item: (name) => | ||
| 1097 | table.insert @clothes, name | ||
| 1098 | |||
| 1099 | a = Person! | ||
| 1100 | b = Person! | ||
| 1101 | |||
| 1102 | a\give_item "pants" | ||
| 1103 | b\give_item "shirt" | ||
| 1104 | |||
| 1105 | -- vai imprimir tanto pants quanto shirt | ||
| 1106 | print item for item in *a.clothes | ||
| 1107 | ``` | ||
| 1108 | |||
| 1109 | </YueDisplay> | ||
| 1110 | |||
| 1111 | A forma correta de evitar esse problema é criar o estado mutável do objeto no construtor: | ||
| 1112 | |||
| 1113 | ```yuescript | ||
| 1114 | class Person | ||
| 1115 | new: => | ||
| 1116 | @clothes = [] | ||
| 1117 | ``` | ||
| 1118 | |||
| 1119 | <YueDisplay> | ||
| 1120 | |||
| 1121 | ```yue | ||
| 1122 | class Person | ||
| 1123 | new: => | ||
| 1124 | @clothes = [] | ||
| 1125 | ``` | ||
| 1126 | |||
| 1127 | </YueDisplay> | ||
| 1128 | |||
| 1129 | ## Herança | ||
| 1130 | |||
| 1131 | A palavra-chave extends pode ser usada em uma declaração de classe para herdar as propriedades e métodos de outra classe. | ||
| 1132 | |||
| 1133 | ```yuescript | ||
| 1134 | class BackPack extends Inventory | ||
| 1135 | size: 10 | ||
| 1136 | add_item: (name) => | ||
| 1137 | if #@items > size then error "backpack is full" | ||
| 1138 | super name | ||
| 1139 | ``` | ||
| 1140 | |||
| 1141 | <YueDisplay> | ||
| 1142 | |||
| 1143 | ```yue | ||
| 1144 | class BackPack extends Inventory | ||
| 1145 | size: 10 | ||
| 1146 | add_item: (name) => | ||
| 1147 | if #@items > size then error "backpack is full" | ||
| 1148 | super name | ||
| 1149 | ``` | ||
| 1150 | |||
| 1151 | </YueDisplay> | ||
| 1152 | |||
| 1153 | Aqui estendemos nossa classe Inventory e limitamos a quantidade de itens que ela pode carregar. | ||
| 1154 | |||
| 1155 | Neste exemplo, não definimos um construtor na subclasse, então o construtor da classe pai é chamado quando criamos uma nova instância. Se definirmos um construtor, podemos usar o método super para chamar o construtor pai. | ||
| 1156 | |||
| 1157 | Sempre que uma classe herda de outra, ela envia uma mensagem à classe pai chamando o método \_\_inherited na classe pai se ele existir. A função recebe dois argumentos: a classe que está sendo herdada e a classe filha. | ||
| 1158 | |||
| 1159 | ```yuescript | ||
| 1160 | class Shelf | ||
| 1161 | @__inherited: (child) => | ||
| 1162 | print @__name, "was inherited by", child.__name | ||
| 1163 | |||
| 1164 | -- vai imprimir: Shelf was inherited by Cupboard | ||
| 1165 | class Cupboard extends Shelf | ||
| 1166 | ``` | ||
| 1167 | |||
| 1168 | <YueDisplay> | ||
| 1169 | |||
| 1170 | ```yue | ||
| 1171 | class Shelf | ||
| 1172 | @__inherited: (child) => | ||
| 1173 | print @__name, "was inherited by", child.__name | ||
| 1174 | |||
| 1175 | -- vai imprimir: Shelf was inherited by Cupboard | ||
| 1176 | class Cupboard extends Shelf | ||
| 1177 | ``` | ||
| 1178 | |||
| 1179 | </YueDisplay> | ||
| 1180 | |||
| 1181 | ## Super | ||
| 1182 | |||
| 1183 | **super** é uma palavra-chave especial que pode ser usada de duas formas diferentes: pode ser tratado como um objeto, ou pode ser chamado como uma função. Só tem funcionalidade especial quando está dentro de uma classe. | ||
| 1184 | |||
| 1185 | Quando chamado como função, chamará a função de mesmo nome na classe pai. O self atual será automaticamente passado como primeiro argumento. (Como visto no exemplo de herança acima) | ||
| 1186 | |||
| 1187 | Quando super é usado como valor normal, é uma referência ao objeto da classe pai. | ||
| 1188 | |||
| 1189 | Pode ser acessado como qualquer objeto para recuperar valores na classe pai que possam ter sido sombreados pela classe filha. | ||
| 1190 | |||
| 1191 | Quando o operador de chamada \ é usado com super, self é inserido como primeiro argumento em vez do valor do próprio super. Ao usar . para recuperar uma função, a função bruta é retornada. | ||
| 1192 | |||
| 1193 | Alguns exemplos de uso de super de diferentes formas: | ||
| 1194 | |||
| 1195 | ```yuescript | ||
| 1196 | class MyClass extends ParentClass | ||
| 1197 | a_method: => | ||
| 1198 | -- os seguintes têm o mesmo efeito: | ||
| 1199 | super "hello", "world" | ||
| 1200 | super\a_method "hello", "world" | ||
| 1201 | super.a_method self, "hello", "world" | ||
| 1202 | |||
| 1203 | -- super como valor é igual à classe pai: | ||
| 1204 | assert super == ParentClass | ||
| 1205 | ``` | ||
| 1206 | |||
| 1207 | <YueDisplay> | ||
| 1208 | |||
| 1209 | ```yue | ||
| 1210 | class MyClass extends ParentClass | ||
| 1211 | a_method: => | ||
| 1212 | -- os seguintes têm o mesmo efeito: | ||
| 1213 | super "hello", "world" | ||
| 1214 | super\a_method "hello", "world" | ||
| 1215 | super.a_method self, "hello", "world" | ||
| 1216 | |||
| 1217 | -- super como valor é igual à classe pai: | ||
| 1218 | assert super == ParentClass | ||
| 1219 | ``` | ||
| 1220 | |||
| 1221 | </YueDisplay> | ||
| 1222 | |||
| 1223 | **super** também pode ser usado no lado esquerdo de um Function Stub. A única diferença principal é que, em vez da função resultante estar vinculada ao valor de super, ela está vinculada a self. | ||
| 1224 | |||
| 1225 | ## Tipos | ||
| 1226 | |||
| 1227 | Cada instância de uma classe carrega seu tipo consigo. Isso é armazenado na propriedade especial \_\_class. Esta propriedade contém o objeto da classe. O objeto da classe é o que chamamos para construir uma nova instância. Também podemos indexar o objeto da classe para recuperar métodos e propriedades da classe. | ||
| 1228 | |||
| 1229 | ```yuescript | ||
| 1230 | b = BackPack! | ||
| 1231 | assert b.__class == BackPack | ||
| 1232 | |||
| 1233 | print BackPack.size -- imprime 10 | ||
| 1234 | ``` | ||
| 1235 | |||
| 1236 | <YueDisplay> | ||
| 1237 | |||
| 1238 | ```yue | ||
| 1239 | b = BackPack! | ||
| 1240 | assert b.__class == BackPack | ||
| 1241 | |||
| 1242 | print BackPack.size -- imprime 10 | ||
| 1243 | ``` | ||
| 1244 | |||
| 1245 | </YueDisplay> | ||
| 1246 | |||
| 1247 | ## Objetos de classe | ||
| 1248 | |||
| 1249 | O objeto da classe é o que criamos quando usamos uma instrução class. O objeto da classe é armazenado em uma variável com o mesmo nome da classe. | ||
| 1250 | |||
| 1251 | O objeto da classe pode ser chamado como uma função para criar novas instâncias. É assim que criamos instâncias de classes nos exemplos acima. | ||
| 1252 | |||
| 1253 | Uma classe é composta por duas tabelas. A própria tabela da classe e a tabela base. A base é usada como metatable para todas as instâncias. Todas as propriedades listadas na declaração da classe são colocadas na base. | ||
| 1254 | |||
| 1255 | A metatable do objeto da classe lê propriedades da base se não existirem no objeto da classe. Isso significa que podemos acessar funções e propriedades diretamente da classe. | ||
| 1256 | |||
| 1257 | É importante notar que atribuir ao objeto da classe não atribui à base, então não é uma forma válida de adicionar novos métodos às instâncias. Em vez disso, a base deve ser alterada explicitamente. Veja o campo \_\_base abaixo. | ||
| 1258 | |||
| 1259 | O objeto da classe tem algumas propriedades especiais: | ||
| 1260 | |||
| 1261 | O nome da classe quando foi declarada é armazenado como string no campo \_\_name do objeto da classe. | ||
| 1262 | |||
| 1263 | ```yuescript | ||
| 1264 | print BackPack.__name -- imprime Backpack | ||
| 1265 | ``` | ||
| 1266 | |||
| 1267 | <YueDisplay> | ||
| 1268 | |||
| 1269 | ```yue | ||
| 1270 | print BackPack.__name -- imprime Backpack | ||
| 1271 | ``` | ||
| 1272 | |||
| 1273 | </YueDisplay> | ||
| 1274 | |||
| 1275 | O objeto base é armazenado em \_\_base. Podemos modificar esta tabela para adicionar funcionalidade a instâncias que já foram criadas e às que ainda serão criadas. | ||
| 1276 | |||
| 1277 | Se a classe estende de algo, o objeto da classe pai é armazenado em \_\_parent. | ||
| 1278 | |||
| 1279 | ## Variáveis de classe | ||
| 1280 | |||
| 1281 | Podemos criar variáveis diretamente no objeto da classe em vez da base usando @ na frente do nome da propriedade em uma declaração de classe. | ||
| 1282 | |||
| 1283 | ```yuescript | ||
| 1284 | class Things | ||
| 1285 | @some_func: => print "Hello from", @__name | ||
| 1286 | |||
| 1287 | Things\some_func! | ||
| 1288 | |||
| 1289 | -- variáveis de classe não visíveis em instâncias | ||
| 1290 | assert Things().some_func == nil | ||
| 1291 | ``` | ||
| 1292 | |||
| 1293 | <YueDisplay> | ||
| 1294 | |||
| 1295 | ```yue | ||
| 1296 | class Things | ||
| 1297 | @some_func: => print "Hello from", @__name | ||
| 1298 | |||
| 1299 | Things\some_func! | ||
| 1300 | |||
| 1301 | -- variáveis de classe não visíveis em instâncias | ||
| 1302 | assert Things().some_func == nil | ||
| 1303 | ``` | ||
| 1304 | |||
| 1305 | </YueDisplay> | ||
| 1306 | |||
| 1307 | Em expressões, podemos usar @@ para acessar um valor armazenado no **class de self. Assim, @@hello é abreviação para self.**class.hello. | ||
| 1308 | |||
| 1309 | ```yuescript | ||
| 1310 | class Counter | ||
| 1311 | @count: 0 | ||
| 1312 | |||
| 1313 | new: => | ||
| 1314 | @@count += 1 | ||
| 1315 | |||
| 1316 | Counter! | ||
| 1317 | Counter! | ||
| 1318 | |||
| 1319 | print Counter.count -- imprime 2 | ||
| 1320 | ``` | ||
| 1321 | |||
| 1322 | <YueDisplay> | ||
| 1323 | |||
| 1324 | ```yue | ||
| 1325 | class Counter | ||
| 1326 | @count: 0 | ||
| 1327 | |||
| 1328 | new: => | ||
| 1329 | @@count += 1 | ||
| 1330 | |||
| 1331 | Counter! | ||
| 1332 | Counter! | ||
| 1333 | |||
| 1334 | print Counter.count -- imprime 2 | ||
| 1335 | ``` | ||
| 1336 | |||
| 1337 | </YueDisplay> | ||
| 1338 | |||
| 1339 | A semântica de chamada de @@ é semelhante a @. Chamar um nome @@ passará a classe como primeiro argumento usando a sintaxe de dois pontos do Lua. | ||
| 1340 | |||
| 1341 | ```yuescript | ||
| 1342 | @@hello 1,2,3,4 | ||
| 1343 | ``` | ||
| 1344 | |||
| 1345 | <YueDisplay> | ||
| 1346 | |||
| 1347 | ```yue | ||
| 1348 | @@hello 1,2,3,4 | ||
| 1349 | ``` | ||
| 1350 | |||
| 1351 | </YueDisplay> | ||
| 1352 | |||
| 1353 | ## Instruções de declaração de classe | ||
| 1354 | |||
| 1355 | No corpo de uma declaração de classe, podemos ter expressões normais além de pares chave/valor. Neste contexto, self é igual ao objeto da classe. | ||
| 1356 | |||
| 1357 | Aqui está uma forma alternativa de criar variável de classe comparada ao descrito acima: | ||
| 1358 | |||
| 1359 | ```yuescript | ||
| 1360 | class Things | ||
| 1361 | @class_var = "hello world" | ||
| 1362 | ``` | ||
| 1363 | |||
| 1364 | <YueDisplay> | ||
| 1365 | |||
| 1366 | ```yue | ||
| 1367 | class Things | ||
| 1368 | @class_var = "hello world" | ||
| 1369 | ``` | ||
| 1370 | |||
| 1371 | </YueDisplay> | ||
| 1372 | |||
| 1373 | Estas expressões são executadas após todas as propriedades terem sido adicionadas à base. | ||
| 1374 | |||
| 1375 | Todas as variáveis declaradas no corpo da classe são locais às propriedades da classe. Isso é conveniente para colocar valores privados ou funções auxiliares que apenas os métodos da classe podem acessar: | ||
| 1376 | |||
| 1377 | ```yuescript | ||
| 1378 | class MoreThings | ||
| 1379 | secret = 123 | ||
| 1380 | log = (msg) -> print "LOG:", msg | ||
| 1381 | |||
| 1382 | some_method: => | ||
| 1383 | log "hello world: " .. secret | ||
| 1384 | ``` | ||
| 1385 | |||
| 1386 | <YueDisplay> | ||
| 1387 | |||
| 1388 | ```yue | ||
| 1389 | class MoreThings | ||
| 1390 | secret = 123 | ||
| 1391 | log = (msg) -> print "LOG:", msg | ||
| 1392 | |||
| 1393 | some_method: => | ||
| 1394 | log "hello world: " .. secret | ||
| 1395 | ``` | ||
| 1396 | |||
| 1397 | </YueDisplay> | ||
| 1398 | |||
| 1399 | ## Valores @ e @@ | ||
| 1400 | |||
| 1401 | Quando @ e @@ são prefixados na frente de um nome, eles representam, respectivamente, esse nome acessado em self e self.\_\_class. | ||
| 1402 | |||
| 1403 | Se forem usados sozinhos, são aliases para self e self.\_\_class. | ||
| 1404 | |||
| 1405 | ```yuescript | ||
| 1406 | assert @ == self | ||
| 1407 | assert @@ == self.__class | ||
| 1408 | ``` | ||
| 1409 | |||
| 1410 | <YueDisplay> | ||
| 1411 | |||
| 1412 | ```yue | ||
| 1413 | assert @ == self | ||
| 1414 | assert @@ == self.__class | ||
| 1415 | ``` | ||
| 1416 | |||
| 1417 | </YueDisplay> | ||
| 1418 | |||
| 1419 | Por exemplo, uma forma rápida de criar uma nova instância da mesma classe a partir de um método de instância usando @@: | ||
| 1420 | |||
| 1421 | ```yuescript | ||
| 1422 | some_instance_method = (...) => @@ ... | ||
| 1423 | ``` | ||
| 1424 | |||
| 1425 | <YueDisplay> | ||
| 1426 | |||
| 1427 | ```yue | ||
| 1428 | some_instance_method = (...) => @@ ... | ||
| 1429 | ``` | ||
| 1430 | |||
| 1431 | </YueDisplay> | ||
| 1432 | |||
| 1433 | ## Promoção de propriedade no construtor | ||
| 1434 | |||
| 1435 | Para reduzir o código repetitivo na definição de objetos de valor simples. Você pode escrever uma classe simples como: | ||
| 1436 | |||
| 1437 | ```yuescript | ||
| 1438 | class Something | ||
| 1439 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1440 | |||
| 1441 | -- O que é abreviação para | ||
| 1442 | |||
| 1443 | class Something | ||
| 1444 | new: (foo, bar, biz, baz) => | ||
| 1445 | @foo = foo | ||
| 1446 | @bar = bar | ||
| 1447 | @@biz = biz | ||
| 1448 | @@baz = baz | ||
| 1449 | ``` | ||
| 1450 | |||
| 1451 | <YueDisplay> | ||
| 1452 | |||
| 1453 | ```yue | ||
| 1454 | class Something | ||
| 1455 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1456 | |||
| 1457 | -- O que é abreviação para | ||
| 1458 | |||
| 1459 | class Something | ||
| 1460 | new: (foo, bar, biz, baz) => | ||
| 1461 | @foo = foo | ||
| 1462 | @bar = bar | ||
| 1463 | @@biz = biz | ||
| 1464 | @@baz = baz | ||
| 1465 | ``` | ||
| 1466 | |||
| 1467 | </YueDisplay> | ||
| 1468 | |||
| 1469 | Você também pode usar esta sintaxe para uma função comum para inicializar os campos de um objeto. | ||
| 1470 | |||
| 1471 | ```yuescript | ||
| 1472 | new = (@fieldA, @fieldB) => @ | ||
| 1473 | obj = new {}, 123, "abc" | ||
| 1474 | print obj | ||
| 1475 | ``` | ||
| 1476 | |||
| 1477 | <YueDisplay> | ||
| 1478 | |||
| 1479 | ```yue | ||
| 1480 | new = (@fieldA, @fieldB) => @ | ||
| 1481 | obj = new {}, 123, "abc" | ||
| 1482 | print obj | ||
| 1483 | ``` | ||
| 1484 | |||
| 1485 | </YueDisplay> | ||
| 1486 | |||
| 1487 | ## Expressões de classe | ||
| 1488 | |||
| 1489 | A sintaxe de classe também pode ser usada como expressão que pode ser atribuída a uma variável ou retornada explicitamente. | ||
| 1490 | |||
| 1491 | ```yuescript | ||
| 1492 | x = class Bucket | ||
| 1493 | drops: 0 | ||
| 1494 | add_drop: => @drops += 1 | ||
| 1495 | ``` | ||
| 1496 | |||
| 1497 | <YueDisplay> | ||
| 1498 | |||
| 1499 | ```yue | ||
| 1500 | x = class Bucket | ||
| 1501 | drops: 0 | ||
| 1502 | add_drop: => @drops += 1 | ||
| 1503 | ``` | ||
| 1504 | |||
| 1505 | </YueDisplay> | ||
| 1506 | |||
| 1507 | ## Classes anônimas | ||
| 1508 | |||
| 1509 | O nome pode ser omitido ao declarar uma classe. O atributo \_\_name será nil, a menos que a expressão da classe esteja em uma atribuição. O nome no lado esquerdo da atribuição é usado em vez de nil. | ||
| 1510 | |||
| 1511 | ```yuescript | ||
| 1512 | BigBucket = class extends Bucket | ||
| 1513 | add_drop: => @drops += 10 | ||
| 1514 | |||
| 1515 | assert Bucket.__name == "BigBucket" | ||
| 1516 | ``` | ||
| 1517 | |||
| 1518 | <YueDisplay> | ||
| 1519 | |||
| 1520 | ```yue | ||
| 1521 | BigBucket = class extends Bucket | ||
| 1522 | add_drop: => @drops += 10 | ||
| 1523 | |||
| 1524 | assert Bucket.__name == "BigBucket" | ||
| 1525 | ``` | ||
| 1526 | |||
| 1527 | </YueDisplay> | ||
| 1528 | |||
| 1529 | Você pode até omitir o corpo, significando que pode escrever uma classe anônima em branco assim: | ||
| 1530 | |||
| 1531 | ```yuescript | ||
| 1532 | x = class | ||
| 1533 | ``` | ||
| 1534 | |||
| 1535 | <YueDisplay> | ||
| 1536 | |||
| 1537 | ```yue | ||
| 1538 | x = class | ||
| 1539 | ``` | ||
| 1540 | |||
| 1541 | </YueDisplay> | ||
| 1542 | |||
| 1543 | ## Mistura de classes | ||
| 1544 | |||
| 1545 | Você pode fazer mistura com a palavra-chave `using` para copiar funções de uma tabela simples ou de um objeto de classe predefinido para sua nova classe. Ao fazer mistura com uma tabela simples, você pode sobrescrever a função de indexação da classe (metamétodo `__index`) para sua implementação personalizada. Ao fazer mistura com um objeto de classe existente, os metamétodos do objeto da classe não serão copiados. | ||
| 1546 | |||
| 1547 | ```yuescript | ||
| 1548 | MyIndex = __index: var: 1 | ||
| 1549 | |||
| 1550 | class X using MyIndex | ||
| 1551 | func: => | ||
| 1552 | print 123 | ||
| 1553 | |||
| 1554 | x = X! | ||
| 1555 | print x.var | ||
| 1556 | |||
| 1557 | class Y using X | ||
| 1558 | |||
| 1559 | y = Y! | ||
| 1560 | y\func! | ||
| 1561 | |||
| 1562 | assert y.__class.__parent ~= X -- X não é pai de Y | ||
| 1563 | ``` | ||
| 1564 | |||
| 1565 | <YueDisplay> | ||
| 1566 | |||
| 1567 | ```yue | ||
| 1568 | MyIndex = __index: var: 1 | ||
| 1569 | |||
| 1570 | class X using MyIndex | ||
| 1571 | func: => | ||
| 1572 | print 123 | ||
| 1573 | |||
| 1574 | x = X! | ||
| 1575 | print x.var | ||
| 1576 | |||
| 1577 | class Y using X | ||
| 1578 | |||
| 1579 | y = Y! | ||
| 1580 | y\func! | ||
| 1581 | |||
| 1582 | assert y.__class.__parent ~= X -- X não é pai de Y | ||
| 1583 | ``` | ||
| 1584 | |||
| 1585 | </YueDisplay> | ||
| 1586 | |||
| 1587 | # Instrução With | ||
| 1588 | |||
| 1589 | Um padrão comum envolvendo a criação de um objeto é chamar uma série de funções e definir uma série de propriedades imediatamente após criá-lo. | ||
| 1590 | |||
| 1591 | Isso resulta em repetir o nome do objeto várias vezes no código, adicionando ruído desnecessário. Uma solução comum para isso é passar uma tabela como argumento que contém uma coleção de chaves e valores para sobrescrever. O inconveniente é que o construtor desse objeto deve suportar essa forma. | ||
| 1592 | |||
| 1593 | O bloco with ajuda a aliviar isso. Dentro de um bloco with podemos usar instruções especiais que começam com . ou \ que representam essas operações aplicadas ao objeto com o qual estamos usando with. | ||
| 1594 | |||
| 1595 | Por exemplo, trabalhamos com um objeto recém-criado: | ||
| 1596 | |||
| 1597 | ```yuescript | ||
| 1598 | with Person! | ||
| 1599 | .name = "Oswald" | ||
| 1600 | \add_relative my_dad | ||
| 1601 | \save! | ||
| 1602 | print .name | ||
| 1603 | ``` | ||
| 1604 | |||
| 1605 | <YueDisplay> | ||
| 1606 | |||
| 1607 | ```yue | ||
| 1608 | with Person! | ||
| 1609 | .name = "Oswald" | ||
| 1610 | \add_relative my_dad | ||
| 1611 | \save! | ||
| 1612 | print .name | ||
| 1613 | ``` | ||
| 1614 | |||
| 1615 | </YueDisplay> | ||
| 1616 | |||
| 1617 | A instrução with também pode ser usada como expressão que retorna o valor ao qual foi dado acesso. | ||
| 1618 | |||
| 1619 | ```yuescript | ||
| 1620 | file = with File "favorite_foods.txt" | ||
| 1621 | \set_encoding "utf8" | ||
| 1622 | ``` | ||
| 1623 | |||
| 1624 | <YueDisplay> | ||
| 1625 | |||
| 1626 | ```yue | ||
| 1627 | file = with File "favorite_foods.txt" | ||
| 1628 | \set_encoding "utf8" | ||
| 1629 | ``` | ||
| 1630 | |||
| 1631 | </YueDisplay> | ||
| 1632 | |||
| 1633 | Expressões `with` suportam `break` com um valor: | ||
| 1634 | |||
| 1635 | ```yuescript | ||
| 1636 | result = with obj | ||
| 1637 | break .value | ||
| 1638 | ``` | ||
| 1639 | |||
| 1640 | <YueDisplay> | ||
| 1641 | |||
| 1642 | ```yue | ||
| 1643 | result = with obj | ||
| 1644 | break .value | ||
| 1645 | ``` | ||
| 1646 | |||
| 1647 | </YueDisplay> | ||
| 1648 | |||
| 1649 | Depois que `break value` é usado dentro de `with`, a expressão `with` deixa de retornar seu objeto-alvo e passa a retornar o valor de `break`. | ||
| 1650 | |||
| 1651 | ```yuescript | ||
| 1652 | a = with obj | ||
| 1653 | .x = 1 | ||
| 1654 | -- a é obj | ||
| 1655 | |||
| 1656 | b = with obj | ||
| 1657 | break .x | ||
| 1658 | -- b é .x, não obj | ||
| 1659 | ``` | ||
| 1660 | |||
| 1661 | <YueDisplay> | ||
| 1662 | |||
| 1663 | ```yue | ||
| 1664 | a = with obj | ||
| 1665 | .x = 1 | ||
| 1666 | -- a é obj | ||
| 1667 | |||
| 1668 | b = with obj | ||
| 1669 | break .x | ||
| 1670 | -- b é .x, não obj | ||
| 1671 | ``` | ||
| 1672 | |||
| 1673 | </YueDisplay> | ||
| 1674 | |||
| 1675 | Diferente de `for` / `while` / `repeat` / `do`, `with` suporta apenas um valor de `break`. | ||
| 1676 | |||
| 1677 | Ou… | ||
| 1678 | |||
| 1679 | ```yuescript | ||
| 1680 | create_person = (name, relatives) -> | ||
| 1681 | with Person! | ||
| 1682 | .name = name | ||
| 1683 | \add_relative relative for relative in *relatives | ||
| 1684 | |||
| 1685 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1686 | ``` | ||
| 1687 | |||
| 1688 | <YueDisplay> | ||
| 1689 | |||
| 1690 | ```yue | ||
| 1691 | create_person = (name, relatives) -> | ||
| 1692 | with Person! | ||
| 1693 | .name = name | ||
| 1694 | \add_relative relative for relative in *relatives | ||
| 1695 | |||
| 1696 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1697 | ``` | ||
| 1698 | |||
| 1699 | </YueDisplay> | ||
| 1700 | |||
| 1701 | Neste uso, with pode ser visto como uma forma especial do combinador K. | ||
| 1702 | |||
| 1703 | A expressão na instrução with também pode ser uma atribuição, se você quiser dar um nome à expressão. | ||
| 1704 | |||
| 1705 | ```yuescript | ||
| 1706 | with str := "Hello" | ||
| 1707 | print "original:", str | ||
| 1708 | print "upper:", \upper! | ||
| 1709 | ``` | ||
| 1710 | |||
| 1711 | <YueDisplay> | ||
| 1712 | |||
| 1713 | ```yue | ||
| 1714 | with str := "Hello" | ||
| 1715 | print "original:", str | ||
| 1716 | print "upper:", \upper! | ||
| 1717 | ``` | ||
| 1718 | |||
| 1719 | </YueDisplay> | ||
| 1720 | |||
| 1721 | Você pode acessar chaves especiais com `[]` em uma instrução `with`. | ||
| 1722 | |||
| 1723 | ```yuescript | ||
| 1724 | with tb | ||
| 1725 | [1] = 1 | ||
| 1726 | print [2] | ||
| 1727 | with [abc] | ||
| 1728 | [3] = [2]\func! | ||
| 1729 | ["key-name"] = value | ||
| 1730 | [] = "abc" -- anexando a "tb" | ||
| 1731 | ``` | ||
| 1732 | |||
| 1733 | <YueDisplay> | ||
| 1734 | |||
| 1735 | ```yue | ||
| 1736 | with tb | ||
| 1737 | [1] = 1 | ||
| 1738 | print [2] | ||
| 1739 | with [abc] | ||
| 1740 | [3] = [2]\func! | ||
| 1741 | ["key-name"] = value | ||
| 1742 | [] = "abc" -- anexando a "tb" | ||
| 1743 | ``` | ||
| 1744 | |||
| 1745 | </YueDisplay> | ||
| 1746 | |||
| 1747 | `with?` é uma versão aprimorada da sintaxe `with`, que introduz uma verificação existencial para acessar com segurança objetos que podem ser nil sem verificações explícitas de null. | ||
| 1748 | |||
| 1749 | ```yuescript | ||
| 1750 | with? obj | ||
| 1751 | print obj.name | ||
| 1752 | ``` | ||
| 1753 | |||
| 1754 | <YueDisplay> | ||
| 1755 | |||
| 1756 | ```yue | ||
| 1757 | with? obj | ||
| 1758 | print obj.name | ||
| 1759 | ``` | ||
| 1760 | |||
| 1761 | </YueDisplay> | ||
| 1762 | |||
| 1763 | # Atribuição | ||
| 1764 | |||
| 1765 | A variável é tipada dinamicamente e é definida como local por padrão. Mas você pode alterar o escopo da declaração pelas instruções **local** e **global**. | ||
| 1766 | |||
| 1767 | ```yuescript | ||
| 1768 | hello = "world" | ||
| 1769 | a, b, c = 1, 2, 3 | ||
| 1770 | hello = 123 -- usa a variável existente | ||
| 1771 | ``` | ||
| 1772 | |||
| 1773 | <YueDisplay> | ||
| 1774 | |||
| 1775 | ```yue | ||
| 1776 | hello = "world" | ||
| 1777 | a, b, c = 1, 2, 3 | ||
| 1778 | hello = 123 -- usa a variável existente | ||
| 1779 | ``` | ||
| 1780 | |||
| 1781 | </YueDisplay> | ||
| 1782 | |||
| 1783 | ## Atualização | ||
| 1784 | |||
| 1785 | Você pode realizar atribuição de atualização com muitos operadores binários. | ||
| 1786 | |||
| 1787 | ```yuescript | ||
| 1788 | x = 1 | ||
| 1789 | x += 1 | ||
| 1790 | x -= 1 | ||
| 1791 | x *= 10 | ||
| 1792 | x /= 10 | ||
| 1793 | x %= 10 | ||
| 1794 | s ..= "world" -- adiciona um novo local se a variável local não existir | ||
| 1795 | arg or= "valor padrão" | ||
| 1796 | ``` | ||
| 1797 | |||
| 1798 | <YueDisplay> | ||
| 1799 | |||
| 1800 | ```yue | ||
| 1801 | x = 1 | ||
| 1802 | x += 1 | ||
| 1803 | x -= 1 | ||
| 1804 | x *= 10 | ||
| 1805 | x /= 10 | ||
| 1806 | x %= 10 | ||
| 1807 | s ..= "world" -- adiciona um novo local se a variável local não existir | ||
| 1808 | arg or= "valor padrão" | ||
| 1809 | ``` | ||
| 1810 | |||
| 1811 | </YueDisplay> | ||
| 1812 | |||
| 1813 | ## Atribuição encadeada | ||
| 1814 | |||
| 1815 | Você pode fazer atribuição encadeada para atribuir múltiplos itens ao mesmo valor. | ||
| 1816 | |||
| 1817 | ```yuescript | ||
| 1818 | a = b = c = d = e = 0 | ||
| 1819 | x = y = z = f! | ||
| 1820 | ``` | ||
| 1821 | |||
| 1822 | <YueDisplay> | ||
| 1823 | |||
| 1824 | ```yue | ||
| 1825 | a = b = c = d = e = 0 | ||
| 1826 | x = y = z = f! | ||
| 1827 | ``` | ||
| 1828 | |||
| 1829 | </YueDisplay> | ||
| 1830 | |||
| 1831 | ## Locais explícitos | ||
| 1832 | |||
| 1833 | ```yuescript | ||
| 1834 | do | ||
| 1835 | local a = 1 | ||
| 1836 | local * | ||
| 1837 | print "declarar antecipadamente todas as variáveis como locais" | ||
| 1838 | x = -> 1 + y + z | ||
| 1839 | y, z = 2, 3 | ||
| 1840 | global instance = Item\new! | ||
| 1841 | |||
| 1842 | do | ||
| 1843 | local X = 1 | ||
| 1844 | local ^ | ||
| 1845 | print "declarar antecipadamente apenas variáveis em maiúsculas" | ||
| 1846 | a = 1 | ||
| 1847 | B = 2 | ||
| 1848 | ``` | ||
| 1849 | |||
| 1850 | <YueDisplay> | ||
| 1851 | |||
| 1852 | ```yue | ||
| 1853 | do | ||
| 1854 | local a = 1 | ||
| 1855 | local * | ||
| 1856 | print "declarar antecipadamente todas as variáveis como locais" | ||
| 1857 | x = -> 1 + y + z | ||
| 1858 | y, z = 2, 3 | ||
| 1859 | global instance = Item\new! | ||
| 1860 | |||
| 1861 | do | ||
| 1862 | local X = 1 | ||
| 1863 | local ^ | ||
| 1864 | print "declarar antecipadamente apenas variáveis em maiúsculas" | ||
| 1865 | a = 1 | ||
| 1866 | B = 2 | ||
| 1867 | ``` | ||
| 1868 | |||
| 1869 | </YueDisplay> | ||
| 1870 | |||
| 1871 | ## Globais explícitos | ||
| 1872 | |||
| 1873 | ```yuescript | ||
| 1874 | do | ||
| 1875 | global a = 1 | ||
| 1876 | global * | ||
| 1877 | print "declarar todas as variáveis como globais" | ||
| 1878 | x = -> 1 + y + z | ||
| 1879 | y, z = 2, 3 | ||
| 1880 | |||
| 1881 | do | ||
| 1882 | global X = 1 | ||
| 1883 | global ^ | ||
| 1884 | print "declarar apenas variáveis em maiúsculas como globais" | ||
| 1885 | a = 1 | ||
| 1886 | B = 2 | ||
| 1887 | local Temp = "um valor local" | ||
| 1888 | ``` | ||
| 1889 | |||
| 1890 | <YueDisplay> | ||
| 1891 | |||
| 1892 | ```yue | ||
| 1893 | do | ||
| 1894 | global a = 1 | ||
| 1895 | global * | ||
| 1896 | print "declarar todas as variáveis como globais" | ||
| 1897 | x = -> 1 + y + z | ||
| 1898 | y, z = 2, 3 | ||
| 1899 | |||
| 1900 | do | ||
| 1901 | global X = 1 | ||
| 1902 | global ^ | ||
| 1903 | print "declarar apenas variáveis em maiúsculas como globais" | ||
| 1904 | a = 1 | ||
| 1905 | B = 2 | ||
| 1906 | local Temp = "um valor local" | ||
| 1907 | ``` | ||
| 1908 | |||
| 1909 | </YueDisplay> | ||
| 1910 | |||
| 1911 | # Atribuição de varargs | ||
| 1912 | |||
| 1913 | Você pode atribuir os resultados retornados de uma função a um símbolo varargs `...`. E então acessar seu conteúdo da forma Lua. | ||
| 1914 | |||
| 1915 | ```yuescript | ||
| 1916 | list = [1, 2, 3, 4, 5] | ||
| 1917 | fn = (ok) -> ok, table.unpack list | ||
| 1918 | ok, ... = fn true | ||
| 1919 | count = select '#', ... | ||
| 1920 | first = select 1, ... | ||
| 1921 | print ok, count, first | ||
| 1922 | ``` | ||
| 1923 | |||
| 1924 | <YueDisplay> | ||
| 1925 | |||
| 1926 | ```yue | ||
| 1927 | list = [1, 2, 3, 4, 5] | ||
| 1928 | fn = (ok) -> ok, table.unpack list | ||
| 1929 | ok, ... = fn true | ||
| 1930 | count = select '#', ... | ||
| 1931 | first = select 1, ... | ||
| 1932 | print ok, count, first | ||
| 1933 | ``` | ||
| 1934 | |||
| 1935 | </YueDisplay> | ||
| 1936 | |||
| 1937 | # Atribuição em if | ||
| 1938 | |||
| 1939 | Os blocos `if` e `elseif` podem receber uma atribuição no lugar de uma expressão condicional. Ao avaliar o condicional, a atribuição será realizada e o valor que foi atribuído será usado como expressão condicional. A variável atribuída está no escopo apenas para o corpo do condicional, ou seja, nunca está disponível se o valor não for truthy. E você precisa usar o "operador walrus" `:=` em vez de `=` para fazer a atribuição. | ||
| 1940 | |||
| 1941 | ```yuescript | ||
| 1942 | if user := database.find_user "moon" | ||
| 1943 | print user.name | ||
| 1944 | ``` | ||
| 1945 | |||
| 1946 | <YueDisplay> | ||
| 1947 | |||
| 1948 | ```yue | ||
| 1949 | if user := database.find_user "moon" | ||
| 1950 | print user.name | ||
| 1951 | ``` | ||
| 1952 | |||
| 1953 | </YueDisplay> | ||
| 1954 | |||
| 1955 | ```yuescript | ||
| 1956 | if hello := os.getenv "hello" | ||
| 1957 | print "Você tem hello", hello | ||
| 1958 | elseif world := os.getenv "world" | ||
| 1959 | print "você tem world", world | ||
| 1960 | else | ||
| 1961 | print "nada :(" | ||
| 1962 | ``` | ||
| 1963 | |||
| 1964 | <YueDisplay> | ||
| 1965 | |||
| 1966 | ```yue | ||
| 1967 | if hello := os.getenv "hello" | ||
| 1968 | print "Você tem hello", hello | ||
| 1969 | elseif world := os.getenv "world" | ||
| 1970 | print "você tem world", world | ||
| 1971 | else | ||
| 1972 | print "nada :(" | ||
| 1973 | ``` | ||
| 1974 | |||
| 1975 | </YueDisplay> | ||
| 1976 | |||
| 1977 | Atribuição em if com múltiplos valores de retorno. Apenas o primeiro valor é verificado, os outros valores estão no escopo. | ||
| 1978 | |||
| 1979 | ```yuescript | ||
| 1980 | if success, result := pcall -> "obter resultado sem problemas" | ||
| 1981 | print result -- variável result está no escopo | ||
| 1982 | print "OK" | ||
| 1983 | ``` | ||
| 1984 | |||
| 1985 | <YueDisplay> | ||
| 1986 | |||
| 1987 | ```yue | ||
| 1988 | if success, result := pcall -> "obter resultado sem problemas" | ||
| 1989 | print result -- variável result está no escopo | ||
| 1990 | print "OK" | ||
| 1991 | ``` | ||
| 1992 | |||
| 1993 | </YueDisplay> | ||
| 1994 | |||
| 1995 | ## Atribuição em while | ||
| 1996 | |||
| 1997 | Você também pode usar atribuição em if em um loop while para obter o valor como condição do loop. | ||
| 1998 | |||
| 1999 | ```yuescript | ||
| 2000 | while byte := stream\read_one! | ||
| 2001 | -- fazer algo com o byte | ||
| 2002 | print byte | ||
| 2003 | ``` | ||
| 2004 | |||
| 2005 | <YueDisplay> | ||
| 2006 | |||
| 2007 | ```yue | ||
| 2008 | while byte := stream\read_one! | ||
| 2009 | -- fazer algo com o byte | ||
| 2010 | print byte | ||
| 2011 | ``` | ||
| 2012 | |||
| 2013 | </YueDisplay> | ||
| 2014 | |||
| 2015 | # Atribuição por desestruturação | ||
| 2016 | |||
| 2017 | A atribuição por desestruturação é uma forma de extrair rapidamente valores de uma tabela por seu nome ou posição em tabelas baseadas em array. | ||
| 2018 | |||
| 2019 | Tipicamente, quando você vê um literal de tabela, {1,2,3}, ele está no lado direito de uma atribuição porque é um valor. A atribuição por desestruturação troca o papel do literal de tabela e o coloca no lado esquerdo de uma instrução de atribuição. | ||
| 2020 | |||
| 2021 | Isso é melhor explicado com exemplos. Assim você extrairia os dois primeiros valores de uma tabela: | ||
| 2022 | |||
| 2023 | ```yuescript | ||
| 2024 | thing = [1, 2] | ||
| 2025 | |||
| 2026 | [a, b] = thing | ||
| 2027 | print a, b | ||
| 2028 | ``` | ||
| 2029 | |||
| 2030 | <YueDisplay> | ||
| 2031 | |||
| 2032 | ```yue | ||
| 2033 | thing = [1, 2] | ||
| 2034 | |||
| 2035 | [a, b] = thing | ||
| 2036 | print a, b | ||
| 2037 | ``` | ||
| 2038 | |||
| 2039 | </YueDisplay> | ||
| 2040 | |||
| 2041 | No literal de tabela de desestruturação, a chave representa a chave para ler do lado direito, e o valor representa o nome ao qual o valor lido será atribuído. | ||
| 2042 | |||
| 2043 | ```yuescript | ||
| 2044 | obj = { | ||
| 2045 | hello: "world" | ||
| 2046 | day: "tuesday" | ||
| 2047 | length: 20 | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | {hello: hello, day: the_day} = obj | ||
| 2051 | print hello, the_day | ||
| 2052 | |||
| 2053 | :day = obj -- OK fazer desestruturação simples sem chaves | ||
| 2054 | ``` | ||
| 2055 | |||
| 2056 | <YueDisplay> | ||
| 2057 | |||
| 2058 | ```yue | ||
| 2059 | obj = { | ||
| 2060 | hello: "world" | ||
| 2061 | day: "tuesday" | ||
| 2062 | length: 20 | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | {hello: hello, day: the_day} = obj | ||
| 2066 | print hello, the_day | ||
| 2067 | |||
| 2068 | :day = obj -- OK fazer desestruturação simples sem chaves | ||
| 2069 | ``` | ||
| 2070 | |||
| 2071 | </YueDisplay> | ||
| 2072 | |||
| 2073 | Isso também funciona com estruturas de dados aninhadas: | ||
| 2074 | |||
| 2075 | ```yuescript | ||
| 2076 | obj2 = { | ||
| 2077 | numbers: [1, 2, 3, 4] | ||
| 2078 | properties: { | ||
| 2079 | color: "green" | ||
| 2080 | height: 13.5 | ||
| 2081 | } | ||
| 2082 | } | ||
| 2083 | |||
| 2084 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2085 | print first, second, color | ||
| 2086 | ``` | ||
| 2087 | |||
| 2088 | <YueDisplay> | ||
| 2089 | |||
| 2090 | ```yue | ||
| 2091 | obj2 = { | ||
| 2092 | numbers: [1, 2, 3, 4] | ||
| 2093 | properties: { | ||
| 2094 | color: "green" | ||
| 2095 | height: 13.5 | ||
| 2096 | } | ||
| 2097 | } | ||
| 2098 | |||
| 2099 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2100 | print first, second, color | ||
| 2101 | ``` | ||
| 2102 | |||
| 2103 | </YueDisplay> | ||
| 2104 | |||
| 2105 | Se a instrução de desestruturação for complicada, sinta-se à vontade para espalhá-la em várias linhas. Um exemplo um pouco mais complicado: | ||
| 2106 | |||
| 2107 | ```yuescript | ||
| 2108 | { | ||
| 2109 | numbers: [first, second] | ||
| 2110 | properties: { | ||
| 2111 | color: color | ||
| 2112 | } | ||
| 2113 | } = obj2 | ||
| 2114 | ``` | ||
| 2115 | |||
| 2116 | <YueDisplay> | ||
| 2117 | |||
| 2118 | ```yue | ||
| 2119 | { | ||
| 2120 | numbers: [first, second] | ||
| 2121 | properties: { | ||
| 2122 | color: color | ||
| 2123 | } | ||
| 2124 | } = obj2 | ||
| 2125 | ``` | ||
| 2126 | |||
| 2127 | </YueDisplay> | ||
| 2128 | |||
| 2129 | É comum extrair valores de uma tabela e atribuí-los a variáveis locais que têm o mesmo nome da chave. Para evitar repetição, podemos usar o operador de prefixo **:**: | ||
| 2130 | |||
| 2131 | ```yuescript | ||
| 2132 | {:concat, :insert} = table | ||
| 2133 | ``` | ||
| 2134 | |||
| 2135 | <YueDisplay> | ||
| 2136 | |||
| 2137 | ```yue | ||
| 2138 | {:concat, :insert} = table | ||
| 2139 | ``` | ||
| 2140 | |||
| 2141 | </YueDisplay> | ||
| 2142 | |||
| 2143 | Isso é efetivamente o mesmo que import, mas podemos renomear campos que queremos extrair misturando a sintaxe: | ||
| 2144 | |||
| 2145 | ```yuescript | ||
| 2146 | {:mix, :max, random: rand} = math | ||
| 2147 | ``` | ||
| 2148 | |||
| 2149 | <YueDisplay> | ||
| 2150 | |||
| 2151 | ```yue | ||
| 2152 | {:mix, :max, random: rand} = math | ||
| 2153 | ``` | ||
| 2154 | |||
| 2155 | </YueDisplay> | ||
| 2156 | |||
| 2157 | Você pode escrever valores padrão ao fazer desestruturação: | ||
| 2158 | |||
| 2159 | ```yuescript | ||
| 2160 | {:name = "sem nome", :job = "sem emprego"} = person | ||
| 2161 | ``` | ||
| 2162 | |||
| 2163 | <YueDisplay> | ||
| 2164 | |||
| 2165 | ```yue | ||
| 2166 | {:name = "sem nome", :job = "sem emprego"} = person | ||
| 2167 | ``` | ||
| 2168 | |||
| 2169 | </YueDisplay> | ||
| 2170 | |||
| 2171 | Você pode usar `_` como placeholder ao fazer desestruturação de lista: | ||
| 2172 | |||
| 2173 | ```yuescript | ||
| 2174 | [_, two, _, four] = items | ||
| 2175 | ``` | ||
| 2176 | |||
| 2177 | <YueDisplay> | ||
| 2178 | |||
| 2179 | ```yue | ||
| 2180 | [_, two, _, four] = items | ||
| 2181 | ``` | ||
| 2182 | |||
| 2183 | </YueDisplay> | ||
| 2184 | |||
| 2185 | ## Desestruturação por intervalo | ||
| 2186 | |||
| 2187 | Você pode usar o operador spread `...` na desestruturação de lista para capturar um intervalo de valores. Isso é útil quando você quer extrair elementos específicos do início e do fim de uma lista enquanto coleta o restante entre eles. | ||
| 2188 | |||
| 2189 | ```yuescript | ||
| 2190 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2191 | [first, ...bulk, last] = orders | ||
| 2192 | print first -- imprime: first | ||
| 2193 | print bulk -- imprime: {"second", "third", "fourth"} | ||
| 2194 | print last -- imprime: last | ||
| 2195 | ``` | ||
| 2196 | |||
| 2197 | <YueDisplay> | ||
| 2198 | |||
| 2199 | ```yue | ||
| 2200 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2201 | [first, ...bulk, last] = orders | ||
| 2202 | print first -- imprime: first | ||
| 2203 | print bulk -- imprime: {"second", "third", "fourth"} | ||
| 2204 | print last -- imprime: last | ||
| 2205 | ``` | ||
| 2206 | |||
| 2207 | </YueDisplay> | ||
| 2208 | |||
| 2209 | O operador spread pode ser usado em diferentes posições para capturar diferentes intervalos, e você pode usar `_` como placeholder para os valores que não quer capturar: | ||
| 2210 | |||
| 2211 | ```yuescript | ||
| 2212 | -- Capturar tudo após o primeiro elemento | ||
| 2213 | [first, ...rest] = orders | ||
| 2214 | |||
| 2215 | -- Capturar tudo antes do último elemento | ||
| 2216 | [...start, last] = orders | ||
| 2217 | |||
| 2218 | -- Capturar tudo exceto os elementos do meio | ||
| 2219 | [first, ..._, last] = orders | ||
| 2220 | ``` | ||
| 2221 | |||
| 2222 | <YueDisplay> | ||
| 2223 | |||
| 2224 | ```yue | ||
| 2225 | -- Capturar tudo após o primeiro elemento | ||
| 2226 | [first, ...rest] = orders | ||
| 2227 | |||
| 2228 | -- Capturar tudo antes do último elemento | ||
| 2229 | [...start, last] = orders | ||
| 2230 | |||
| 2231 | -- Capturar tudo exceto os elementos do meio | ||
| 2232 | [first, ..._, last] = orders | ||
| 2233 | ``` | ||
| 2234 | |||
| 2235 | </YueDisplay> | ||
| 2236 | |||
| 2237 | ## Desestruturação em outros lugares | ||
| 2238 | |||
| 2239 | A desestruturação também pode aparecer em lugares onde uma atribuição ocorre implicitamente. Um exemplo disso é um loop for: | ||
| 2240 | |||
| 2241 | ```yuescript | ||
| 2242 | tuples = [ | ||
| 2243 | ["hello", "world"] | ||
| 2244 | ["egg", "head"] | ||
| 2245 | ] | ||
| 2246 | |||
| 2247 | for [left, right] in *tuples | ||
| 2248 | print left, right | ||
| 2249 | ``` | ||
| 2250 | |||
| 2251 | <YueDisplay> | ||
| 2252 | |||
| 2253 | ```yue | ||
| 2254 | tuples = [ | ||
| 2255 | ["hello", "world"] | ||
| 2256 | ["egg", "head"] | ||
| 2257 | ] | ||
| 2258 | |||
| 2259 | for [left, right] in *tuples | ||
| 2260 | print left, right | ||
| 2261 | ``` | ||
| 2262 | |||
| 2263 | </YueDisplay> | ||
| 2264 | |||
| 2265 | Sabemos que cada elemento na tabela array é uma tupla de dois itens, então podemos desempacotá-lo diretamente na cláusula de nomes da instrução for usando desestruturação. | ||
| 2266 | |||
| 2267 | # A cláusula Using; controlando atribuição destrutiva | ||
| 2268 | |||
| 2269 | Embora o escopo léxico possa ser uma grande ajuda na redução da complexidade do código que escrevemos, as coisas podem ficar difíceis de gerenciar conforme o tamanho do código aumenta. Considere o seguinte trecho: | ||
| 2270 | |||
| 2271 | ```yuescript | ||
| 2272 | i = 100 | ||
| 2273 | |||
| 2274 | -- muitas linhas de código... | ||
| 2275 | |||
| 2276 | my_func = -> | ||
| 2277 | i = 10 | ||
| 2278 | while i > 0 | ||
| 2279 | print i | ||
| 2280 | i -= 1 | ||
| 2281 | |||
| 2282 | my_func! | ||
| 2283 | |||
| 2284 | print i -- vai imprimir 0 | ||
| 2285 | ``` | ||
| 2286 | |||
| 2287 | <YueDisplay> | ||
| 2288 | |||
| 2289 | ```yue | ||
| 2290 | i = 100 | ||
| 2291 | |||
| 2292 | -- muitas linhas de código... | ||
| 2293 | |||
| 2294 | my_func = -> | ||
| 2295 | i = 10 | ||
| 2296 | while i > 0 | ||
| 2297 | print i | ||
| 2298 | i -= 1 | ||
| 2299 | |||
| 2300 | my_func! | ||
| 2301 | |||
| 2302 | print i -- vai imprimir 0 | ||
| 2303 | ``` | ||
| 2304 | |||
| 2305 | </YueDisplay> | ||
| 2306 | |||
| 2307 | Em my_func, sobrescrevemos o valor de i por engano. Neste exemplo é bem óbvio, mas considere uma base de código grande ou estrangeira onde não está claro quais nomes já foram declarados. | ||
| 2308 | |||
| 2309 | Seria útil dizer quais variáveis do escopo envolvente pretendemos alterar, para evitar que alteremos outras por acidente. | ||
| 2310 | |||
| 2311 | A palavra-chave using nos permite fazer isso. using nil garante que nenhuma variável fechada seja sobrescrita na atribuição. A cláusula using é colocada após a lista de argumentos em uma função, ou no lugar dela se não houver argumentos. | ||
| 2312 | |||
| 2313 | ```yuescript | ||
| 2314 | i = 100 | ||
| 2315 | |||
| 2316 | my_func = (using nil) -> | ||
| 2317 | i = "hello" -- uma nova variável local é criada aqui | ||
| 2318 | |||
| 2319 | my_func! | ||
| 2320 | print i -- imprime 100, i não é afetado | ||
| 2321 | ``` | ||
| 2322 | |||
| 2323 | <YueDisplay> | ||
| 2324 | |||
| 2325 | ```yue | ||
| 2326 | i = 100 | ||
| 2327 | |||
| 2328 | my_func = (using nil) -> | ||
| 2329 | i = "hello" -- uma nova variável local é criada aqui | ||
| 2330 | |||
| 2331 | my_func! | ||
| 2332 | print i -- imprime 100, i não é afetado | ||
| 2333 | ``` | ||
| 2334 | |||
| 2335 | </YueDisplay> | ||
| 2336 | |||
| 2337 | Múltiplos nomes podem ser separados por vírgulas. Os valores do closure ainda podem ser acessados, apenas não podem ser modificados: | ||
| 2338 | |||
| 2339 | ```yuescript | ||
| 2340 | tmp = 1213 | ||
| 2341 | i, k = 100, 50 | ||
| 2342 | |||
| 2343 | my_func = (add using k, i) -> | ||
| 2344 | tmp = tmp + add -- uma nova variável local tmp é criada | ||
| 2345 | i += tmp | ||
| 2346 | k += tmp | ||
| 2347 | |||
| 2348 | my_func(22) | ||
| 2349 | print i, k -- estes foram atualizados | ||
| 2350 | ``` | ||
| 2351 | |||
| 2352 | <YueDisplay> | ||
| 2353 | |||
| 2354 | ```yue | ||
| 2355 | tmp = 1213 | ||
| 2356 | i, k = 100, 50 | ||
| 2357 | |||
| 2358 | my_func = (add using k, i) -> | ||
| 2359 | tmp = tmp + add -- uma nova variável local tmp é criada | ||
| 2360 | i += tmp | ||
| 2361 | k += tmp | ||
| 2362 | |||
| 2363 | my_func(22) | ||
| 2364 | print i, k -- estes foram atualizados | ||
| 2365 | ``` | ||
| 2366 | |||
| 2367 | </YueDisplay> | ||
| 2368 | |||
| 2369 | # Uso | ||
| 2370 | |||
| 2371 | ## Módulo Lua | ||
| 2372 | |||
| 2373 | Use o módulo YueScript em Lua: | ||
| 2374 | |||
| 2375 | - **Caso 1** | ||
| 2376 | |||
| 2377 | Use require em "your_yuescript_entry.yue" no Lua. | ||
| 2378 | |||
| 2379 | ```Lua | ||
| 2380 | require("yue")("your_yuescript_entry") | ||
| 2381 | ``` | ||
| 2382 | |||
| 2383 | E esse código continua funcionando quando você compila "your_yuescript_entry.yue" para "your_yuescript_entry.lua" no mesmo caminho. Nos demais arquivos YueScript, use normalmente o **require** ou **import**. Os números de linha nas mensagens de erro também serão tratados corretamente. | ||
| 2384 | |||
| 2385 | - **Caso 2** | ||
| 2386 | |||
| 2387 | Requerer o módulo YueScript e reescrever a mensagem manualmente. | ||
| 2388 | |||
| 2389 | ```lua | ||
| 2390 | local yue = require("yue") | ||
| 2391 | yue.insert_loader() | ||
| 2392 | local success, result = xpcall(function() | ||
| 2393 | return require("yuescript_module_name") | ||
| 2394 | end, function(err) | ||
| 2395 | return yue.traceback(err) | ||
| 2396 | end) | ||
| 2397 | ``` | ||
| 2398 | |||
| 2399 | - **Caso 3** | ||
| 2400 | |||
| 2401 | Usar a função compiladora do YueScript em Lua. | ||
| 2402 | |||
| 2403 | ```lua | ||
| 2404 | local yue = require("yue") | ||
| 2405 | local codes, err, globals = yue.to_lua([[ | ||
| 2406 | f = -> | ||
| 2407 | print "hello world" | ||
| 2408 | f! | ||
| 2409 | ]],{ | ||
| 2410 | implicit_return_root = true, | ||
| 2411 | reserve_line_number = true, | ||
| 2412 | lint_global = true, | ||
| 2413 | space_over_tab = false, | ||
| 2414 | options = { | ||
| 2415 | target = "5.4", | ||
| 2416 | path = "/script" | ||
| 2417 | } | ||
| 2418 | }) | ||
| 2419 | ``` | ||
| 2420 | |||
| 2421 | ## Ferramenta YueScript | ||
| 2422 | |||
| 2423 | Use a ferramenta YueScript com: | ||
| 2424 | |||
| 2425 | ```shell | ||
| 2426 | > yue -h | ||
| 2427 | Usage: yue | ||
| 2428 | [options] [<file/directory>] ... | ||
| 2429 | yue -e <code_or_file> [args...] | ||
| 2430 | yue -w [<directory>] [options] | ||
| 2431 | yue - | ||
| 2432 | |||
| 2433 | Notas: | ||
| 2434 | - '-' / '--' deve ser o primeiro e único argumento. | ||
| 2435 | - '-o/--output' não pode ser usado com múltiplos arquivos de entrada. | ||
| 2436 | - '-w/--watch' não pode ser usado com entrada de arquivo (apenas diretório). | ||
| 2437 | - com '-e/--execute', os tokens restantes são tratados como argumentos do script. | ||
| 2438 | |||
| 2439 | Opções: | ||
| 2440 | -h, --help Mostrar esta mensagem de ajuda e sair. | ||
| 2441 | -e <str>, --execute <str> Executar um arquivo ou código bruto | ||
| 2442 | -m, --minify Gerar código minificado | ||
| 2443 | -r, --rewrite Reescrever saída para corresponder aos números de linha originais | ||
| 2444 | -t <output_to>, --output-to <output_to> | ||
| 2445 | Especificar onde colocar os arquivos compilados | ||
| 2446 | -o <file>, --output <file> Escrever saída em arquivo | ||
| 2447 | -p, --print Escrever saída na saída padrão | ||
| 2448 | -b, --benchmark Mostrar tempo de compilação (não grava saída) | ||
| 2449 | -g, --globals Listar variáveis globais usadas em NOME LINHA COLUNA | ||
| 2450 | -s, --spaces Usar espaços no código gerado em vez de tabulações | ||
| 2451 | -l, --line-numbers Escrever números de linha do código fonte | ||
| 2452 | -j, --no-implicit-return Desabilitar retorno implícito no final do arquivo | ||
| 2453 | -c, --reserve-comments Preservar comentários antes de instruções do código fonte | ||
| 2454 | -w [<dir>], --watch [<dir>] | ||
| 2455 | Observar alterações e compilar cada arquivo no diretório | ||
| 2456 | -v, --version Imprimir versão | ||
| 2457 | - Ler da entrada padrão, imprimir na saída padrão | ||
| 2458 | (Deve ser o primeiro e único argumento) | ||
| 2459 | -- Igual a '-' (mantido para compatibilidade retroativa) | ||
| 2460 | |||
| 2461 | --target <version> Especificar a versão do Lua para a qual o código será gerado | ||
| 2462 | (a versão pode ser apenas 5.1 a 5.5) | ||
| 2463 | --path <path_str> Adicionar um caminho de busca Lua extra ao package.path | ||
| 2464 | --<key>=<value> Passar opção do compilador no formato key=value (comportamento existente) | ||
| 2465 | |||
| 2466 | Execute sem opções para entrar no REPL, digite o símbolo '$' | ||
| 2467 | em uma única linha para iniciar/parar o modo multilinha | ||
| 2468 | ``` | ||
| 2469 | |||
| 2470 | Casos de uso: | ||
| 2471 | |||
| 2472 | Compilar recursivamente todos os arquivos YueScript com extensão **.yue** no caminho atual: **yue .** | ||
| 2473 | |||
| 2474 | Compilar e salvar resultados em um caminho de destino: **yue -t /target/path/ .** | ||
| 2475 | |||
| 2476 | Compilar e preservar informações de debug: **yue -l .** | ||
| 2477 | |||
| 2478 | Compilar e gerar código minificado: **yue -m .** | ||
| 2479 | |||
| 2480 | Executar código bruto: **yue -e 'print 123'** | ||
| 2481 | |||
| 2482 | Executar um arquivo YueScript: **yue -e main.yue** | ||
| 2483 | |||
| 2484 | # Introdução | ||
| 2485 | |||
| 2486 | YueScript é uma linguagem dinâmica que compila para Lua. É um dialeto do [MoonScript](https://github.com/leafo/moonscript). O código escrito em YueScript é expressivo e extremamente conciso. É adequado para escrever lógica de aplicação variável com código mais manutenível e roda em ambientes Lua embutidos, como jogos ou servidores web. | ||
| 2487 | |||
| 2488 | Yue (月) é o nome da lua em chinês e é pronunciado como [jyɛ]. | ||
| 2489 | |||
| 2490 | ## Uma visão geral do YueScript | ||
| 2491 | |||
| 2492 | ```yuescript | ||
| 2493 | -- sintaxe de importação | ||
| 2494 | import p, to_lua from "yue" | ||
| 2495 | |||
| 2496 | -- literais de objeto | ||
| 2497 | inventory = | ||
| 2498 | equipment: | ||
| 2499 | - "sword" | ||
| 2500 | - "shield" | ||
| 2501 | items: | ||
| 2502 | - name: "potion" | ||
| 2503 | count: 10 | ||
| 2504 | - name: "bread" | ||
| 2505 | count: 3 | ||
| 2506 | |||
| 2507 | -- compreensão de lista | ||
| 2508 | map = (arr, action) -> | ||
| 2509 | [action item for item in *arr] | ||
| 2510 | |||
| 2511 | filter = (arr, cond) -> | ||
| 2512 | [item for item in *arr when cond item] | ||
| 2513 | |||
| 2514 | reduce = (arr, init, action): init -> | ||
| 2515 | init = action init, item for item in *arr | ||
| 2516 | |||
| 2517 | -- operador pipe | ||
| 2518 | [1, 2, 3] | ||
| 2519 | |> map (x) -> x * 2 | ||
| 2520 | |> filter (x) -> x > 4 | ||
| 2521 | |> reduce 0, (a, b) -> a + b | ||
| 2522 | |||
| 2523 | |||
| 2524 | -- manipulação de metatable | ||
| 2525 | apple = | ||
| 2526 | size: 15 | ||
| 2527 | <index>: | ||
| 2528 | color: 0x00ffff | ||
| 2529 | |||
| 2530 | with apple | ||
| 2531 | p .size, .color, .<index> if .<>? | ||
| 2532 | |||
| 2533 | -- sintaxe de exportação estilo js | ||
| 2534 | export 🌛 = "Script da Lua" | ||
| 2535 | ``` | ||
| 2536 | |||
| 2537 | <YueDisplay> | ||
| 2538 | |||
| 2539 | ```yue | ||
| 2540 | -- sintaxe de importação | ||
| 2541 | import p, to_lua from "yue" | ||
| 2542 | |||
| 2543 | -- literais de objeto | ||
| 2544 | inventory = | ||
| 2545 | equipment: | ||
| 2546 | - "sword" | ||
| 2547 | - "shield" | ||
| 2548 | items: | ||
| 2549 | - name: "potion" | ||
| 2550 | count: 10 | ||
| 2551 | - name: "bread" | ||
| 2552 | count: 3 | ||
| 2553 | |||
| 2554 | -- compreensão de lista | ||
| 2555 | map = (arr, action) -> | ||
| 2556 | [action item for item in *arr] | ||
| 2557 | |||
| 2558 | filter = (arr, cond) -> | ||
| 2559 | [item for item in *arr when cond item] | ||
| 2560 | |||
| 2561 | reduce = (arr, init, action): init -> | ||
| 2562 | init = action init, item for item in *arr | ||
| 2563 | |||
| 2564 | -- operador pipe | ||
| 2565 | [1, 2, 3] | ||
| 2566 | |> map (x) -> x * 2 | ||
| 2567 | |> filter (x) -> x > 4 | ||
| 2568 | |> reduce 0, (a, b) -> a + b | ||
| 2569 | |||
| 2570 | |||
| 2571 | -- manipulação de metatable | ||
| 2572 | apple = | ||
| 2573 | size: 15 | ||
| 2574 | <index>: | ||
| 2575 | color: 0x00ffff | ||
| 2576 | |||
| 2577 | with apple | ||
| 2578 | p .size, .color, .<index> if .<>? | ||
| 2579 | |||
| 2580 | -- sintaxe de exportação estilo js | ||
| 2581 | export 🌛 = "Script da Lua" | ||
| 2582 | ``` | ||
| 2583 | |||
| 2584 | </YueDisplay> | ||
| 2585 | |||
| 2586 | ## Sobre o Dora SSR | ||
| 2587 | |||
| 2588 | O YueScript está sendo desenvolvido e mantido em conjunto com o motor de jogo open-source [Dora SSR](https://github.com/Dora-SSR/Dora-SSR). Tem sido usado para criar ferramentas do motor, demonstrações de jogos e protótipos, validando suas capacidades em cenários do mundo real e aprimorando a experiência de desenvolvimento do Dora SSR. | ||
| 2589 | |||
| 2590 | # Instalação | ||
| 2591 | |||
| 2592 | ## Módulo Lua | ||
| 2593 | |||
| 2594 | Instale o [luarocks](https://luarocks.org), um gerenciador de pacotes para módulos Lua. Em seguida, instale-o como módulo Lua e executável com: | ||
| 2595 | |||
| 2596 | ```shell | ||
| 2597 | luarocks install yuescript | ||
| 2598 | ``` | ||
| 2599 | |||
| 2600 | Ou você pode compilar o arquivo `yue.so` com: | ||
| 2601 | |||
| 2602 | ```shell | ||
| 2603 | make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua | ||
| 2604 | ``` | ||
| 2605 | |||
| 2606 | Depois, obtenha o arquivo binário no caminho **bin/shared/yue.so**. | ||
| 2607 | |||
| 2608 | ## Compilar ferramenta binária | ||
| 2609 | |||
| 2610 | Clone este repositório e compile e instale o executável com: | ||
| 2611 | |||
| 2612 | ```shell | ||
| 2613 | make install | ||
| 2614 | ``` | ||
| 2615 | |||
| 2616 | Compilar a ferramenta YueScript sem o recurso de macro: | ||
| 2617 | |||
| 2618 | ```shell | ||
| 2619 | make install NO_MACRO=true | ||
| 2620 | ``` | ||
| 2621 | |||
| 2622 | Compilar a ferramenta YueScript sem o binário Lua embutido: | ||
| 2623 | |||
| 2624 | ```shell | ||
| 2625 | make install NO_LUA=true | ||
| 2626 | ``` | ||
| 2627 | |||
| 2628 | ## Baixar binário pré-compilado | ||
| 2629 | |||
| 2630 | Você pode baixar arquivos binários pré-compilados, incluindo executáveis compatíveis com diferentes versões do Lua e arquivos de biblioteca. | ||
| 2631 | |||
| 2632 | Baixe os arquivos binários pré-compilados [aqui](https://github.com/IppClub/YueScript/releases). | ||
| 2633 | |||
| 2634 | # Condicionais | ||
| 2635 | |||
| 2636 | ```yuescript | ||
| 2637 | have_coins = false | ||
| 2638 | if have_coins | ||
| 2639 | print "Tem moedas" | ||
| 2640 | else | ||
| 2641 | print "Sem moedas" | ||
| 2642 | ``` | ||
| 2643 | |||
| 2644 | <YueDisplay> | ||
| 2645 | |||
| 2646 | ```yue | ||
| 2647 | have_coins = false | ||
| 2648 | if have_coins | ||
| 2649 | print "Tem moedas" | ||
| 2650 | else | ||
| 2651 | print "Sem moedas" | ||
| 2652 | ``` | ||
| 2653 | |||
| 2654 | </YueDisplay> | ||
| 2655 | |||
| 2656 | Uma sintaxe curta para instruções únicas também pode ser usada: | ||
| 2657 | |||
| 2658 | ```yuescript | ||
| 2659 | have_coins = false | ||
| 2660 | if have_coins then print "Tem moedas" else print "Sem moedas" | ||
| 2661 | ``` | ||
| 2662 | |||
| 2663 | <YueDisplay> | ||
| 2664 | |||
| 2665 | ```yue | ||
| 2666 | have_coins = false | ||
| 2667 | if have_coins then print "Tem moedas" else print "Sem moedas" | ||
| 2668 | ``` | ||
| 2669 | |||
| 2670 | </YueDisplay> | ||
| 2671 | |||
| 2672 | Como instruções if podem ser usadas como expressões, isso também pode ser escrito como: | ||
| 2673 | |||
| 2674 | ```yuescript | ||
| 2675 | have_coins = false | ||
| 2676 | print if have_coins then "Tem moedas" else "Sem moedas" | ||
| 2677 | ``` | ||
| 2678 | |||
| 2679 | <YueDisplay> | ||
| 2680 | |||
| 2681 | ```yue | ||
| 2682 | have_coins = false | ||
| 2683 | print if have_coins then "Tem moedas" else "Sem moedas" | ||
| 2684 | ``` | ||
| 2685 | |||
| 2686 | </YueDisplay> | ||
| 2687 | |||
| 2688 | Condicionais também podem ser usados em instruções de retorno e atribuições: | ||
| 2689 | |||
| 2690 | ```yuescript | ||
| 2691 | is_tall = (name) -> | ||
| 2692 | if name == "Rob" | ||
| 2693 | true | ||
| 2694 | else | ||
| 2695 | false | ||
| 2696 | |||
| 2697 | message = if is_tall "Rob" | ||
| 2698 | "Sou muito alto" | ||
| 2699 | else | ||
| 2700 | "Não sou tão alto" | ||
| 2701 | |||
| 2702 | print message -- imprime: Sou muito alto | ||
| 2703 | ``` | ||
| 2704 | |||
| 2705 | <YueDisplay> | ||
| 2706 | |||
| 2707 | ```yue | ||
| 2708 | is_tall = (name) -> | ||
| 2709 | if name == "Rob" | ||
| 2710 | true | ||
| 2711 | else | ||
| 2712 | false | ||
| 2713 | |||
| 2714 | message = if is_tall "Rob" | ||
| 2715 | "Sou muito alto" | ||
| 2716 | else | ||
| 2717 | "Não sou tão alto" | ||
| 2718 | |||
| 2719 | print message -- imprime: Sou muito alto | ||
| 2720 | ``` | ||
| 2721 | |||
| 2722 | </YueDisplay> | ||
| 2723 | |||
| 2724 | O oposto de if é unless: | ||
| 2725 | |||
| 2726 | ```yuescript | ||
| 2727 | unless os.date("%A") == "Monday" | ||
| 2728 | print "não é segunda-feira!" | ||
| 2729 | ``` | ||
| 2730 | |||
| 2731 | <YueDisplay> | ||
| 2732 | |||
| 2733 | ```yue | ||
| 2734 | unless os.date("%A") == "Monday" | ||
| 2735 | print "não é segunda-feira!" | ||
| 2736 | ``` | ||
| 2737 | |||
| 2738 | </YueDisplay> | ||
| 2739 | |||
| 2740 | ```yuescript | ||
| 2741 | print "Você tem sorte!" unless math.random! > 0.1 | ||
| 2742 | ``` | ||
| 2743 | |||
| 2744 | <YueDisplay> | ||
| 2745 | |||
| 2746 | ```yue | ||
| 2747 | print "Você tem sorte!" unless math.random! > 0.1 | ||
| 2748 | ``` | ||
| 2749 | |||
| 2750 | </YueDisplay> | ||
| 2751 | |||
| 2752 | ## Em expressão | ||
| 2753 | |||
| 2754 | Você pode escrever código de verificação de intervalo com uma `in-expression`. | ||
| 2755 | |||
| 2756 | ```yuescript | ||
| 2757 | a = 5 | ||
| 2758 | |||
| 2759 | if a in [1, 3, 5, 7] | ||
| 2760 | print "verificando igualdade com valores discretos" | ||
| 2761 | |||
| 2762 | if a in list | ||
| 2763 | print "verificando se `a` está na lista" | ||
| 2764 | ``` | ||
| 2765 | |||
| 2766 | <YueDisplay> | ||
| 2767 | |||
| 2768 | ```yue | ||
| 2769 | a = 5 | ||
| 2770 | |||
| 2771 | if a in [1, 3, 5, 7] | ||
| 2772 | print "verificando igualdade com valores discretos" | ||
| 2773 | |||
| 2774 | if a in list | ||
| 2775 | print "verificando se `a` está na lista" | ||
| 2776 | ``` | ||
| 2777 | |||
| 2778 | </YueDisplay> | ||
| 2779 | |||
| 2780 | # Loop For | ||
| 2781 | |||
| 2782 | Existem duas formas de loop for, assim como no Lua. Uma numérica e uma genérica: | ||
| 2783 | |||
| 2784 | ```yuescript | ||
| 2785 | for i = 10, 20 | ||
| 2786 | print i | ||
| 2787 | |||
| 2788 | for k = 1, 15, 2 -- um passo opcional fornecido | ||
| 2789 | print k | ||
| 2790 | |||
| 2791 | for key, value in pairs object | ||
| 2792 | print key, value | ||
| 2793 | ``` | ||
| 2794 | |||
| 2795 | <YueDisplay> | ||
| 2796 | |||
| 2797 | ```yue | ||
| 2798 | for i = 10, 20 | ||
| 2799 | print i | ||
| 2800 | |||
| 2801 | for k = 1, 15, 2 -- um passo opcional fornecido | ||
| 2802 | print k | ||
| 2803 | |||
| 2804 | for key, value in pairs object | ||
| 2805 | print key, value | ||
| 2806 | ``` | ||
| 2807 | |||
| 2808 | </YueDisplay> | ||
| 2809 | |||
| 2810 | Os operadores de slicing e **\*** podem ser usados, assim como com compreensões: | ||
| 2811 | |||
| 2812 | ```yuescript | ||
| 2813 | for item in *items[2, 4] | ||
| 2814 | print item | ||
| 2815 | ``` | ||
| 2816 | |||
| 2817 | <YueDisplay> | ||
| 2818 | |||
| 2819 | ```yue | ||
| 2820 | for item in *items[2, 4] | ||
| 2821 | print item | ||
| 2822 | ``` | ||
| 2823 | |||
| 2824 | </YueDisplay> | ||
| 2825 | |||
| 2826 | Uma sintaxe mais curta também está disponível para todas as variações quando o corpo é apenas uma linha: | ||
| 2827 | |||
| 2828 | ```yuescript | ||
| 2829 | for item in *items do print item | ||
| 2830 | |||
| 2831 | for j = 1, 10, 3 do print j | ||
| 2832 | ``` | ||
| 2833 | |||
| 2834 | <YueDisplay> | ||
| 2835 | |||
| 2836 | ```yue | ||
| 2837 | for item in *items do print item | ||
| 2838 | |||
| 2839 | for j = 1, 10, 3 do print j | ||
| 2840 | ``` | ||
| 2841 | |||
| 2842 | </YueDisplay> | ||
| 2843 | |||
| 2844 | Um loop for também pode ser usado como expressão. A última instrução no corpo do loop for é convertida em expressão e anexada a uma tabela array acumuladora. | ||
| 2845 | |||
| 2846 | Dobrando cada número par: | ||
| 2847 | |||
| 2848 | ```yuescript | ||
| 2849 | doubled_evens = for i = 1, 20 | ||
| 2850 | if i % 2 == 0 | ||
| 2851 | i * 2 | ||
| 2852 | else | ||
| 2853 | i | ||
| 2854 | ``` | ||
| 2855 | |||
| 2856 | <YueDisplay> | ||
| 2857 | |||
| 2858 | ```yue | ||
| 2859 | doubled_evens = for i = 1, 20 | ||
| 2860 | if i % 2 == 0 | ||
| 2861 | i * 2 | ||
| 2862 | else | ||
| 2863 | i | ||
| 2864 | ``` | ||
| 2865 | |||
| 2866 | </YueDisplay> | ||
| 2867 | |||
| 2868 | Além disso, os loops for suportam break com valores de retorno, permitindo que o próprio loop seja usado como expressão que sai antecipadamente com um resultado significativo. Expressões `for` suportam `break` com múltiplos valores. | ||
| 2869 | |||
| 2870 | Por exemplo, para encontrar o primeiro número maior que 10: | ||
| 2871 | |||
| 2872 | ```yuescript | ||
| 2873 | first_large = for n in *numbers | ||
| 2874 | break n if n > 10 | ||
| 2875 | ``` | ||
| 2876 | |||
| 2877 | <YueDisplay> | ||
| 2878 | |||
| 2879 | ```yue | ||
| 2880 | first_large = for n in *numbers | ||
| 2881 | break n if n > 10 | ||
| 2882 | ``` | ||
| 2883 | |||
| 2884 | </YueDisplay> | ||
| 2885 | |||
| 2886 | Esta sintaxe de break-com-valor permite padrões concisos e expressivos de busca ou saída antecipada diretamente em expressões de loop. | ||
| 2887 | |||
| 2888 | ```yuescript | ||
| 2889 | key, score = for k, v in pairs data | ||
| 2890 | break k, v * 10 if k == "target" | ||
| 2891 | ``` | ||
| 2892 | |||
| 2893 | <YueDisplay> | ||
| 2894 | |||
| 2895 | ```yue | ||
| 2896 | key, score = for k, v in pairs data | ||
| 2897 | break k, v * 10 if k == "target" | ||
| 2898 | ``` | ||
| 2899 | |||
| 2900 | </YueDisplay> | ||
| 2901 | |||
| 2902 | Você também pode filtrar valores combinando a expressão do loop for com a instrução continue. | ||
| 2903 | |||
| 2904 | Loops for no final do corpo de uma função não são acumulados em uma tabela para valor de retorno (em vez disso, a função retornará nil). Uma instrução return explícita pode ser usada, ou o loop pode ser convertido em compreensão de lista. | ||
| 2905 | |||
| 2906 | ```yuescript | ||
| 2907 | func_a = -> for i = 1, 10 do print i | ||
| 2908 | func_b = -> return for i = 1, 10 do i | ||
| 2909 | |||
| 2910 | print func_a! -- imprime nil | ||
| 2911 | print func_b! -- imprime objeto table | ||
| 2912 | ``` | ||
| 2913 | |||
| 2914 | <YueDisplay> | ||
| 2915 | |||
| 2916 | ```yue | ||
| 2917 | func_a = -> for i = 1, 10 do print i | ||
| 2918 | func_b = -> return for i = 1, 10 do i | ||
| 2919 | |||
| 2920 | print func_a! -- imprime nil | ||
| 2921 | print func_b! -- imprime objeto table | ||
| 2922 | ``` | ||
| 2923 | |||
| 2924 | </YueDisplay> | ||
| 2925 | |||
| 2926 | Isso é feito para evitar a criação desnecessária de tabelas para funções que não precisam retornar os resultados do loop. | ||
| 2927 | |||
| 2928 | # Continue | ||
| 2929 | |||
| 2930 | Uma instrução continue pode ser usada para pular a iteração atual em um loop. | ||
| 2931 | |||
| 2932 | ```yuescript | ||
| 2933 | i = 0 | ||
| 2934 | while i < 10 | ||
| 2935 | i += 1 | ||
| 2936 | continue if i % 2 == 0 | ||
| 2937 | print i | ||
| 2938 | ``` | ||
| 2939 | |||
| 2940 | <YueDisplay> | ||
| 2941 | |||
| 2942 | ```yue | ||
| 2943 | i = 0 | ||
| 2944 | while i < 10 | ||
| 2945 | i += 1 | ||
| 2946 | continue if i % 2 == 0 | ||
| 2947 | print i | ||
| 2948 | ``` | ||
| 2949 | |||
| 2950 | </YueDisplay> | ||
| 2951 | |||
| 2952 | continue também pode ser usado com expressões de loop para impedir que essa iteração seja acumulada no resultado. Este exemplo filtra a tabela array para apenas números pares: | ||
| 2953 | |||
| 2954 | ```yuescript | ||
| 2955 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2956 | odds = for x in *my_numbers | ||
| 2957 | continue if x % 2 == 1 | ||
| 2958 | x | ||
| 2959 | ``` | ||
| 2960 | |||
| 2961 | <YueDisplay> | ||
| 2962 | |||
| 2963 | ```yue | ||
| 2964 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2965 | odds = for x in *my_numbers | ||
| 2966 | continue if x % 2 == 1 | ||
| 2967 | x | ||
| 2968 | ``` | ||
| 2969 | |||
| 2970 | </YueDisplay> | ||
| 2971 | |||
| 2972 | # Switch | ||
| 2973 | |||
| 2974 | A instrução switch é uma forma abreviada de escrever uma série de instruções if que verificam o mesmo valor. Observe que o valor é avaliado apenas uma vez. Como as instruções if, os switches podem ter um bloco else para tratar ausência de correspondências. A comparação é feita com o operador ==. Na instrução switch, você também pode usar expressão de atribuição para armazenar valor de variável temporária. | ||
| 2975 | |||
| 2976 | ```yuescript | ||
| 2977 | switch name := "Dan" | ||
| 2978 | when "Robert" | ||
| 2979 | print "Você é Robert" | ||
| 2980 | when "Dan", "Daniel" | ||
| 2981 | print "Seu nome é Dan" | ||
| 2982 | else | ||
| 2983 | print "Não sei quem você é com o nome #{name}" | ||
| 2984 | ``` | ||
| 2985 | |||
| 2986 | <YueDisplay> | ||
| 2987 | |||
| 2988 | ```yue | ||
| 2989 | switch name := "Dan" | ||
| 2990 | when "Robert" | ||
| 2991 | print "Você é Robert" | ||
| 2992 | when "Dan", "Daniel" | ||
| 2993 | print "Seu nome é Dan" | ||
| 2994 | else | ||
| 2995 | print "Não sei quem você é com o nome #{name}" | ||
| 2996 | ``` | ||
| 2997 | |||
| 2998 | </YueDisplay> | ||
| 2999 | |||
| 3000 | Uma cláusula when de um switch pode corresponder a múltiplos valores listando-os separados por vírgula. | ||
| 3001 | |||
| 3002 | Os switches também podem ser usados como expressões; aqui podemos atribuir o resultado do switch a uma variável: | ||
| 3003 | |||
| 3004 | ```yuescript | ||
| 3005 | b = 1 | ||
| 3006 | next_number = switch b | ||
| 3007 | when 1 | ||
| 3008 | 2 | ||
| 3009 | when 2 | ||
| 3010 | 3 | ||
| 3011 | else | ||
| 3012 | error "não consigo contar tão alto!" | ||
| 3013 | ``` | ||
| 3014 | |||
| 3015 | <YueDisplay> | ||
| 3016 | |||
| 3017 | ```yue | ||
| 3018 | b = 1 | ||
| 3019 | next_number = switch b | ||
| 3020 | when 1 | ||
| 3021 | 2 | ||
| 3022 | when 2 | ||
| 3023 | 3 | ||
| 3024 | else | ||
| 3025 | error "não consigo contar tão alto!" | ||
| 3026 | ``` | ||
| 3027 | |||
| 3028 | </YueDisplay> | ||
| 3029 | |||
| 3030 | Podemos usar a palavra-chave then para escrever o bloco when de um switch em uma única linha. Nenhuma palavra-chave extra é necessária para escrever o bloco else em uma única linha. | ||
| 3031 | |||
| 3032 | ```yuescript | ||
| 3033 | msg = switch math.random(1, 5) | ||
| 3034 | when 1 then "você tem sorte" | ||
| 3035 | when 2 then "você quase tem sorte" | ||
| 3036 | else "não tão sortudo" | ||
| 3037 | ``` | ||
| 3038 | |||
| 3039 | <YueDisplay> | ||
| 3040 | |||
| 3041 | ```yue | ||
| 3042 | msg = switch math.random(1, 5) | ||
| 3043 | when 1 then "você tem sorte" | ||
| 3044 | when 2 then "você quase tem sorte" | ||
| 3045 | else "não tão sortudo" | ||
| 3046 | ``` | ||
| 3047 | |||
| 3048 | </YueDisplay> | ||
| 3049 | |||
| 3050 | Se você quiser escrever código com uma indentação a menos ao escrever uma instrução switch, pode colocar a primeira cláusula when na linha de início da instrução, e então todas as outras cláusulas podem ser escritas com uma indentação a menos. | ||
| 3051 | |||
| 3052 | ```yuescript | ||
| 3053 | switch math.random(1, 5) | ||
| 3054 | when 1 | ||
| 3055 | print "você tem sorte" -- duas indentações | ||
| 3056 | else | ||
| 3057 | print "não tão sortudo" | ||
| 3058 | |||
| 3059 | switch math.random(1, 5) when 1 | ||
| 3060 | print "você tem sorte" -- uma indentação | ||
| 3061 | else | ||
| 3062 | print "não tão sortudo" | ||
| 3063 | ``` | ||
| 3064 | |||
| 3065 | <YueDisplay> | ||
| 3066 | |||
| 3067 | ```yue | ||
| 3068 | switch math.random(1, 5) | ||
| 3069 | when 1 | ||
| 3070 | print "você tem sorte" -- duas indentações | ||
| 3071 | else | ||
| 3072 | print "não tão sortudo" | ||
| 3073 | |||
| 3074 | switch math.random(1, 5) when 1 | ||
| 3075 | print "você tem sorte" -- uma indentação | ||
| 3076 | else | ||
| 3077 | print "não tão sortudo" | ||
| 3078 | ``` | ||
| 3079 | |||
| 3080 | </YueDisplay> | ||
| 3081 | |||
| 3082 | Vale notar a ordem da expressão de comparação do case. A expressão do case está no lado esquerdo. Isso pode ser útil se a expressão do case quiser sobrescrever como a comparação é feita definindo um metamétodo eq. | ||
| 3083 | |||
| 3084 | ## Correspondência de tabela | ||
| 3085 | |||
| 3086 | Você pode fazer correspondência de tabela em uma cláusula when de switch, se a tabela puder ser desestruturada por uma estrutura específica e obter valores não-nil. | ||
| 3087 | |||
| 3088 | ```yuescript | ||
| 3089 | items = | ||
| 3090 | * x: 100 | ||
| 3091 | y: 200 | ||
| 3092 | * width: 300 | ||
| 3093 | height: 400 | ||
| 3094 | |||
| 3095 | for item in *items | ||
| 3096 | switch item | ||
| 3097 | when :x, :y | ||
| 3098 | print "Vec2 #{x}, #{y}" | ||
| 3099 | when :width, :height | ||
| 3100 | print "tamanho #{width}, #{height}" | ||
| 3101 | ``` | ||
| 3102 | |||
| 3103 | <YueDisplay> | ||
| 3104 | |||
| 3105 | ```yue | ||
| 3106 | items = | ||
| 3107 | * x: 100 | ||
| 3108 | y: 200 | ||
| 3109 | * width: 300 | ||
| 3110 | height: 400 | ||
| 3111 | |||
| 3112 | for item in *items | ||
| 3113 | switch item | ||
| 3114 | when :x, :y | ||
| 3115 | print "Vec2 #{x}, #{y}" | ||
| 3116 | when :width, :height | ||
| 3117 | print "tamanho #{width}, #{height}" | ||
| 3118 | ``` | ||
| 3119 | |||
| 3120 | </YueDisplay> | ||
| 3121 | |||
| 3122 | Você pode usar valores padrão para opcionalmente desestruturar a tabela para alguns campos. | ||
| 3123 | |||
| 3124 | ```yuescript | ||
| 3125 | item = {} | ||
| 3126 | |||
| 3127 | {pos: {:x = 50, :y = 200}} = item -- obtém erro: attempt to index a nil value (field 'pos') | ||
| 3128 | |||
| 3129 | switch item | ||
| 3130 | when {pos: {:x = 50, :y = 200}} | ||
| 3131 | print "Vec2 #{x}, #{y}" -- a desestruturação de tabela ainda passará | ||
| 3132 | ``` | ||
| 3133 | |||
| 3134 | <YueDisplay> | ||
| 3135 | |||
| 3136 | ```yue | ||
| 3137 | item = {} | ||
| 3138 | |||
| 3139 | {pos: {:x = 50, :y = 200}} = item -- obtém erro: attempt to index a nil value (field 'pos') | ||
| 3140 | |||
| 3141 | switch item | ||
| 3142 | when {pos: {:x = 50, :y = 200}} | ||
| 3143 | print "Vec2 #{x}, #{y}" -- a desestruturação de tabela ainda passará | ||
| 3144 | ``` | ||
| 3145 | |||
| 3146 | </YueDisplay> | ||
| 3147 | |||
| 3148 | Você também pode corresponder contra elementos de array, campos de tabela, e até estruturas aninhadas com literais de array ou tabela. | ||
| 3149 | |||
| 3150 | Corresponder contra elementos de array. | ||
| 3151 | |||
| 3152 | ```yuescript | ||
| 3153 | switch tb | ||
| 3154 | when [1, 2, 3] | ||
| 3155 | print "1, 2, 3" | ||
| 3156 | when [1, b, 3] | ||
| 3157 | print "1, #{b}, 3" | ||
| 3158 | when [1, 2, b = 3] -- b tem valor padrão | ||
| 3159 | print "1, 2, #{b}" | ||
| 3160 | ``` | ||
| 3161 | |||
| 3162 | <YueDisplay> | ||
| 3163 | |||
| 3164 | ```yue | ||
| 3165 | switch tb | ||
| 3166 | when [1, 2, 3] | ||
| 3167 | print "1, 2, 3" | ||
| 3168 | when [1, b, 3] | ||
| 3169 | print "1, #{b}, 3" | ||
| 3170 | when [1, 2, b = 3] -- b tem valor padrão | ||
| 3171 | print "1, 2, #{b}" | ||
| 3172 | ``` | ||
| 3173 | |||
| 3174 | </YueDisplay> | ||
| 3175 | |||
| 3176 | Corresponder contra campos de tabela com desestruturação. | ||
| 3177 | |||
| 3178 | ```yuescript | ||
| 3179 | switch tb | ||
| 3180 | when success: true, :result | ||
| 3181 | print "sucesso", result | ||
| 3182 | when success: false | ||
| 3183 | print "falhou", result | ||
| 3184 | else | ||
| 3185 | print "inválido" | ||
| 3186 | ``` | ||
| 3187 | |||
| 3188 | <YueDisplay> | ||
| 3189 | |||
| 3190 | ```yue | ||
| 3191 | switch tb | ||
| 3192 | when success: true, :result | ||
| 3193 | print "sucesso", result | ||
| 3194 | when success: false | ||
| 3195 | print "falhou", result | ||
| 3196 | else | ||
| 3197 | print "inválido" | ||
| 3198 | ``` | ||
| 3199 | |||
| 3200 | </YueDisplay> | ||
| 3201 | |||
| 3202 | Corresponder contra estruturas de tabela aninhadas. | ||
| 3203 | |||
| 3204 | ```yuescript | ||
| 3205 | switch tb | ||
| 3206 | when data: {type: "success", :content} | ||
| 3207 | print "sucesso", content | ||
| 3208 | when data: {type: "error", :content} | ||
| 3209 | print "erro", content | ||
| 3210 | else | ||
| 3211 | print "inválido" | ||
| 3212 | ``` | ||
| 3213 | |||
| 3214 | <YueDisplay> | ||
| 3215 | |||
| 3216 | ```yue | ||
| 3217 | switch tb | ||
| 3218 | when data: {type: "success", :content} | ||
| 3219 | print "sucesso", content | ||
| 3220 | when data: {type: "error", :content} | ||
| 3221 | print "erro", content | ||
| 3222 | else | ||
| 3223 | print "inválido" | ||
| 3224 | ``` | ||
| 3225 | |||
| 3226 | </YueDisplay> | ||
| 3227 | |||
| 3228 | Corresponder contra array de tabelas. | ||
| 3229 | |||
| 3230 | ```yuescript | ||
| 3231 | switch tb | ||
| 3232 | when [ | ||
| 3233 | {a: 1, b: 2} | ||
| 3234 | {a: 3, b: 4} | ||
| 3235 | {a: 5, b: 6} | ||
| 3236 | fourth | ||
| 3237 | ] | ||
| 3238 | print "correspondido", fourth | ||
| 3239 | ``` | ||
| 3240 | |||
| 3241 | <YueDisplay> | ||
| 3242 | |||
| 3243 | ```yue | ||
| 3244 | switch tb | ||
| 3245 | when [ | ||
| 3246 | {a: 1, b: 2} | ||
| 3247 | {a: 3, b: 4} | ||
| 3248 | {a: 5, b: 6} | ||
| 3249 | fourth | ||
| 3250 | ] | ||
| 3251 | print "correspondido", fourth | ||
| 3252 | ``` | ||
| 3253 | |||
| 3254 | </YueDisplay> | ||
| 3255 | |||
| 3256 | Corresponder contra uma lista e capturar um intervalo de elementos. | ||
| 3257 | |||
| 3258 | ```yuescript | ||
| 3259 | segments = ["admin", "users", "logs", "view"] | ||
| 3260 | switch segments | ||
| 3261 | when [...groups, resource, action] | ||
| 3262 | print "Grupo:", groups -- imprime: {"admin", "users"} | ||
| 3263 | print "Recurso:", resource -- imprime: "logs" | ||
| 3264 | print "Ação:", action -- imprime: "view" | ||
| 3265 | ``` | ||
| 3266 | |||
| 3267 | <YueDisplay> | ||
| 3268 | |||
| 3269 | ```yue | ||
| 3270 | segments = ["admin", "users", "logs", "view"] | ||
| 3271 | switch segments | ||
| 3272 | when [...groups, resource, action] | ||
| 3273 | print "Grupo:", groups -- imprime: {"admin", "users"} | ||
| 3274 | print "Recurso:", resource -- imprime: "logs" | ||
| 3275 | print "Ação:", action -- imprime: "view" | ||
| 3276 | ``` | ||
| 3277 | |||
| 3278 | </YueDisplay> | ||
| 3279 | |||
| 3280 | # Loop While | ||
| 3281 | |||
| 3282 | O loop while também vem em quatro variações: | ||
| 3283 | |||
| 3284 | ```yuescript | ||
| 3285 | i = 10 | ||
| 3286 | while i > 0 | ||
| 3287 | print i | ||
| 3288 | i -= 1 | ||
| 3289 | |||
| 3290 | while running == true do my_function! | ||
| 3291 | ``` | ||
| 3292 | |||
| 3293 | <YueDisplay> | ||
| 3294 | |||
| 3295 | ```yue | ||
| 3296 | i = 10 | ||
| 3297 | while i > 0 | ||
| 3298 | print i | ||
| 3299 | i -= 1 | ||
| 3300 | |||
| 3301 | while running == true do my_function! | ||
| 3302 | ``` | ||
| 3303 | |||
| 3304 | </YueDisplay> | ||
| 3305 | |||
| 3306 | ```yuescript | ||
| 3307 | i = 10 | ||
| 3308 | until i == 0 | ||
| 3309 | print i | ||
| 3310 | i -= 1 | ||
| 3311 | |||
| 3312 | until running == false do my_function! | ||
| 3313 | ``` | ||
| 3314 | |||
| 3315 | <YueDisplay> | ||
| 3316 | |||
| 3317 | ```yue | ||
| 3318 | i = 10 | ||
| 3319 | until i == 0 | ||
| 3320 | print i | ||
| 3321 | i -= 1 | ||
| 3322 | until running == false do my_function! | ||
| 3323 | ``` | ||
| 3324 | |||
| 3325 | </YueDisplay> | ||
| 3326 | |||
| 3327 | Como os loops for, o loop while também pode ser usado como expressão. Expressões `while` e `until` suportam `break` com múltiplos valores. | ||
| 3328 | |||
| 3329 | ```yuescript | ||
| 3330 | value, doubled = while true | ||
| 3331 | n = get_next! | ||
| 3332 | break n, n * 2 if n > 10 | ||
| 3333 | ``` | ||
| 3334 | |||
| 3335 | <YueDisplay> | ||
| 3336 | |||
| 3337 | ```yue | ||
| 3338 | value, doubled = while true | ||
| 3339 | n = get_next! | ||
| 3340 | break n, n * 2 if n > 10 | ||
| 3341 | ``` | ||
| 3342 | |||
| 3343 | </YueDisplay> | ||
| 3344 | |||
| 3345 | Além disso, para uma função retornar o valor acumulado de um loop while, a instrução deve ser explicitamente retornada. | ||
| 3346 | |||
| 3347 | ## Loop Repeat | ||
| 3348 | |||
| 3349 | O loop repeat vem do Lua: | ||
| 3350 | |||
| 3351 | ```yuescript | ||
| 3352 | i = 10 | ||
| 3353 | repeat | ||
| 3354 | print i | ||
| 3355 | i -= 1 | ||
| 3356 | until i == 0 | ||
| 3357 | ``` | ||
| 3358 | |||
| 3359 | <YueDisplay> | ||
| 3360 | |||
| 3361 | ```yue | ||
| 3362 | i = 10 | ||
| 3363 | repeat | ||
| 3364 | print i | ||
| 3365 | i -= 1 | ||
| 3366 | until i == 0 | ||
| 3367 | ``` | ||
| 3368 | |||
| 3369 | </YueDisplay> | ||
| 3370 | |||
| 3371 | Expressões `repeat` também suportam `break` com múltiplos valores: | ||
| 3372 | |||
| 3373 | ```yuescript | ||
| 3374 | i = 1 | ||
| 3375 | value, scaled = repeat | ||
| 3376 | break i, i * 100 if i > 3 | ||
| 3377 | i += 1 | ||
| 3378 | until false | ||
| 3379 | ``` | ||
| 3380 | |||
| 3381 | <YueDisplay> | ||
| 3382 | |||
| 3383 | ```yue | ||
| 3384 | i = 1 | ||
| 3385 | value, scaled = repeat | ||
| 3386 | break i, i * 100 if i > 3 | ||
| 3387 | i += 1 | ||
| 3388 | until false | ||
| 3389 | ``` | ||
| 3390 | |||
| 3391 | </YueDisplay> | ||
| 3392 | |||
| 3393 | # Stubs de função | ||
| 3394 | |||
| 3395 | É comum passar uma função de um objeto como valor, por exemplo, passando um método de instância para uma função como callback. Se a função espera o objeto em que está operando como primeiro argumento, então você deve de alguma forma empacotar esse objeto com a função para que ela possa ser chamada corretamente. | ||
| 3396 | |||
| 3397 | A sintaxe de function stub é uma forma abreviada de criar uma nova função closure que empacota tanto o objeto quanto a função. Esta nova função chama a função empacotada no contexto correto do objeto. | ||
| 3398 | |||
| 3399 | Sua sintaxe é a mesma que chamar um método de instância com o operador \, mas sem lista de argumentos fornecida. | ||
| 3400 | |||
| 3401 | ```yuescript | ||
| 3402 | my_object = { | ||
| 3403 | value: 1000 | ||
| 3404 | write: => print "the value:", @value | ||
| 3405 | } | ||
| 3406 | |||
| 3407 | run_callback = (func) -> | ||
| 3408 | print "running callback..." | ||
| 3409 | func! | ||
| 3410 | |||
| 3411 | -- isso não funcionará: | ||
| 3412 | -- a função não tem referência a my_object | ||
| 3413 | run_callback my_object.write | ||
| 3414 | |||
| 3415 | -- sintaxe de function stub | ||
| 3416 | -- nos permite empacotar o objeto em uma nova função | ||
| 3417 | run_callback my_object\write | ||
| 3418 | ``` | ||
| 3419 | |||
| 3420 | <YueDisplay> | ||
| 3421 | |||
| 3422 | ```yue | ||
| 3423 | my_object = { | ||
| 3424 | value: 1000 | ||
| 3425 | write: => print "the value:", @value | ||
| 3426 | } | ||
| 3427 | |||
| 3428 | run_callback = (func) -> | ||
| 3429 | print "running callback..." | ||
| 3430 | func! | ||
| 3431 | |||
| 3432 | -- isso não funcionará: | ||
| 3433 | -- a função não tem referência a my_object | ||
| 3434 | run_callback my_object.write | ||
| 3435 | |||
| 3436 | -- sintaxe de function stub | ||
| 3437 | -- nos permite empacotar o objeto em uma nova função | ||
| 3438 | run_callback my_object\write | ||
| 3439 | ``` | ||
| 3440 | |||
| 3441 | </YueDisplay> | ||
| 3442 | |||
| 3443 | # Backcalls | ||
| 3444 | |||
| 3445 | Backcalls são usados para desaninhar callbacks. Eles são definidos usando setas apontando para a esquerda como o último parâmetro, preenchendo por padrão uma chamada de função. Toda a sintaxe é basicamente a mesma das funções seta regulares, exceto que apenas aponta para o outro lado e o corpo da função não requer indentação. | ||
| 3446 | |||
| 3447 | ```yuescript | ||
| 3448 | x <- f | ||
| 3449 | print "hello" .. x | ||
| 3450 | ``` | ||
| 3451 | |||
| 3452 | <YueDisplay> | ||
| 3453 | |||
| 3454 | ```yue | ||
| 3455 | x <- f | ||
| 3456 | print "hello" .. x | ||
| 3457 | ``` | ||
| 3458 | |||
| 3459 | </YueDisplay> | ||
| 3460 | |||
| 3461 | Funções seta "fat" também estão disponíveis. | ||
| 3462 | |||
| 3463 | ```yuescript | ||
| 3464 | <= f | ||
| 3465 | print @value | ||
| 3466 | ``` | ||
| 3467 | |||
| 3468 | <YueDisplay> | ||
| 3469 | |||
| 3470 | ```yue | ||
| 3471 | <= f | ||
| 3472 | print @value | ||
| 3473 | ``` | ||
| 3474 | |||
| 3475 | </YueDisplay> | ||
| 3476 | |||
| 3477 | Você pode especificar um placeholder para onde deseja que a função backcall vá como parâmetro. | ||
| 3478 | |||
| 3479 | ```yuescript | ||
| 3480 | (x) <- map _, [1, 2, 3] | ||
| 3481 | x * 2 | ||
| 3482 | ``` | ||
| 3483 | |||
| 3484 | <YueDisplay> | ||
| 3485 | |||
| 3486 | ```yue | ||
| 3487 | (x) <- map _, [1, 2, 3] | ||
| 3488 | x * 2 | ||
| 3489 | ``` | ||
| 3490 | |||
| 3491 | </YueDisplay> | ||
| 3492 | |||
| 3493 | Se você desejar ter mais código após seus backcalls, pode colocá-los em uma instrução do. E os parênteses podem ser omitidos com funções seta não-fat. | ||
| 3494 | |||
| 3495 | ```yuescript | ||
| 3496 | result, msg = do | ||
| 3497 | data <- readAsync "filename.txt" | ||
| 3498 | print data | ||
| 3499 | info <- processAsync data | ||
| 3500 | check info | ||
| 3501 | print result, msg | ||
| 3502 | ``` | ||
| 3503 | |||
| 3504 | <YueDisplay> | ||
| 3505 | |||
| 3506 | ```yue | ||
| 3507 | result, msg = do | ||
| 3508 | data <- readAsync "filename.txt" | ||
| 3509 | print data | ||
| 3510 | info <- processAsync data | ||
| 3511 | check info | ||
| 3512 | print result, msg | ||
| 3513 | ``` | ||
| 3514 | |||
| 3515 | </YueDisplay> | ||
| 3516 | |||
| 3517 | # Literais de função | ||
| 3518 | |||
| 3519 | Todas as funções são criadas usando uma expressão de função. Uma função simples é denotada usando a seta: **->**. | ||
| 3520 | |||
| 3521 | ```yuescript | ||
| 3522 | my_function = -> | ||
| 3523 | my_function() -- chama a função vazia | ||
| 3524 | ``` | ||
| 3525 | |||
| 3526 | <YueDisplay> | ||
| 3527 | |||
| 3528 | ```yue | ||
| 3529 | my_function = -> | ||
| 3530 | my_function() -- chama a função vazia | ||
| 3531 | ``` | ||
| 3532 | |||
| 3533 | </YueDisplay> | ||
| 3534 | |||
| 3535 | O corpo da função pode ser uma instrução colocada diretamente após a seta, ou pode ser uma série de instruções indentadas nas linhas seguintes: | ||
| 3536 | |||
| 3537 | ```yuescript | ||
| 3538 | func_a = -> print "hello world" | ||
| 3539 | |||
| 3540 | func_b = -> | ||
| 3541 | value = 100 | ||
| 3542 | print "The value:", value | ||
| 3543 | ``` | ||
| 3544 | |||
| 3545 | <YueDisplay> | ||
| 3546 | |||
| 3547 | ```yue | ||
| 3548 | func_a = -> print "hello world" | ||
| 3549 | |||
| 3550 | func_b = -> | ||
| 3551 | value = 100 | ||
| 3552 | print "The value:", value | ||
| 3553 | ``` | ||
| 3554 | |||
| 3555 | </YueDisplay> | ||
| 3556 | |||
| 3557 | Se uma função não tem argumentos, ela pode ser chamada usando o operador !, em vez de parênteses vazios. A invocação ! é a forma preferida de chamar funções sem argumentos. | ||
| 3558 | |||
| 3559 | ```yuescript | ||
| 3560 | func_a! | ||
| 3561 | func_b() | ||
| 3562 | ``` | ||
| 3563 | |||
| 3564 | <YueDisplay> | ||
| 3565 | |||
| 3566 | ```yue | ||
| 3567 | func_a! | ||
| 3568 | func_b() | ||
| 3569 | ``` | ||
| 3570 | |||
| 3571 | </YueDisplay> | ||
| 3572 | |||
| 3573 | Funções com argumentos podem ser criadas precedendo a seta com uma lista de nomes de argumentos entre parênteses: | ||
| 3574 | |||
| 3575 | ```yuescript | ||
| 3576 | sum = (x, y) -> print "sum", x + y | ||
| 3577 | ``` | ||
| 3578 | |||
| 3579 | <YueDisplay> | ||
| 3580 | |||
| 3581 | ```yue | ||
| 3582 | sum = (x, y) -> print "sum", x + y | ||
| 3583 | ``` | ||
| 3584 | |||
| 3585 | </YueDisplay> | ||
| 3586 | |||
| 3587 | Funções podem ser chamadas listando os argumentos após o nome de uma expressão que avalia para uma função. Ao encadear chamadas de função, os argumentos são aplicados à função mais próxima à esquerda. | ||
| 3588 | |||
| 3589 | ```yuescript | ||
| 3590 | sum 10, 20 | ||
| 3591 | print sum 10, 20 | ||
| 3592 | |||
| 3593 | a b c "a", "b", "c" | ||
| 3594 | ``` | ||
| 3595 | |||
| 3596 | <YueDisplay> | ||
| 3597 | |||
| 3598 | ```yue | ||
| 3599 | sum 10, 20 | ||
| 3600 | print sum 10, 20 | ||
| 3601 | |||
| 3602 | a b c "a", "b", "c" | ||
| 3603 | ``` | ||
| 3604 | |||
| 3605 | </YueDisplay> | ||
| 3606 | |||
| 3607 | Para evitar ambiguidade ao chamar funções, parênteses também podem ser usados para envolver os argumentos. Isso é necessário aqui para garantir que os argumentos certos sejam enviados às funções certas. | ||
| 3608 | |||
| 3609 | ```yuescript | ||
| 3610 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3611 | ``` | ||
| 3612 | |||
| 3613 | <YueDisplay> | ||
| 3614 | |||
| 3615 | ```yue | ||
| 3616 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3617 | ``` | ||
| 3618 | |||
| 3619 | </YueDisplay> | ||
| 3620 | |||
| 3621 | Não deve haver espaço entre o parêntese de abertura e a função. | ||
| 3622 | |||
| 3623 | As funções convertem a última instrução em seu corpo em uma instrução de retorno, isso é chamado de retorno implícito: | ||
| 3624 | |||
| 3625 | ```yuescript | ||
| 3626 | sum = (x, y) -> x + y | ||
| 3627 | print "The sum is ", sum 10, 20 | ||
| 3628 | ``` | ||
| 3629 | |||
| 3630 | <YueDisplay> | ||
| 3631 | |||
| 3632 | ```yue | ||
| 3633 | sum = (x, y) -> x + y | ||
| 3634 | print "The sum is ", sum 10, 20 | ||
| 3635 | ``` | ||
| 3636 | |||
| 3637 | </YueDisplay> | ||
| 3638 | |||
| 3639 | E se você precisar retornar explicitamente, pode usar a palavra-chave return: | ||
| 3640 | |||
| 3641 | ```yuescript | ||
| 3642 | sum = (x, y) -> return x + y | ||
| 3643 | ``` | ||
| 3644 | |||
| 3645 | <YueDisplay> | ||
| 3646 | |||
| 3647 | ```yue | ||
| 3648 | sum = (x, y) -> return x + y | ||
| 3649 | ``` | ||
| 3650 | |||
| 3651 | </YueDisplay> | ||
| 3652 | |||
| 3653 | Assim como no Lua, as funções podem retornar múltiplos valores. A última instrução deve ser uma lista de valores separados por vírgulas: | ||
| 3654 | |||
| 3655 | ```yuescript | ||
| 3656 | mystery = (x, y) -> x + y, x - y | ||
| 3657 | a, b = mystery 10, 20 | ||
| 3658 | ``` | ||
| 3659 | |||
| 3660 | <YueDisplay> | ||
| 3661 | |||
| 3662 | ```yue | ||
| 3663 | mystery = (x, y) -> x + y, x - y | ||
| 3664 | a, b = mystery 10, 20 | ||
| 3665 | ``` | ||
| 3666 | |||
| 3667 | </YueDisplay> | ||
| 3668 | |||
| 3669 | ## Setas fat | ||
| 3670 | |||
| 3671 | Como é um idioma em Lua enviar um objeto como primeiro argumento ao chamar um método, uma sintaxe especial é fornecida para criar funções que incluem automaticamente um argumento self. | ||
| 3672 | |||
| 3673 | ```yuescript | ||
| 3674 | func = (num) => @value + num | ||
| 3675 | ``` | ||
| 3676 | |||
| 3677 | <YueDisplay> | ||
| 3678 | |||
| 3679 | ```yue | ||
| 3680 | func = (num) => @value + num | ||
| 3681 | ``` | ||
| 3682 | |||
| 3683 | </YueDisplay> | ||
| 3684 | |||
| 3685 | ## Valores padrão de argumentos | ||
| 3686 | |||
| 3687 | É possível fornecer valores padrão para os argumentos de uma função. Um argumento é determinado como vazio se seu valor for nil. Qualquer argumento nil que tenha valor padrão será substituído antes da execução do corpo da função. | ||
| 3688 | |||
| 3689 | ```yuescript | ||
| 3690 | my_function = (name = "something", height = 100) -> | ||
| 3691 | print "Hello I am", name | ||
| 3692 | print "My height is", height | ||
| 3693 | ``` | ||
| 3694 | |||
| 3695 | <YueDisplay> | ||
| 3696 | |||
| 3697 | ```yue | ||
| 3698 | my_function = (name = "something", height = 100) -> | ||
| 3699 | print "Hello I am", name | ||
| 3700 | print "My height is", height | ||
| 3701 | ``` | ||
| 3702 | |||
| 3703 | </YueDisplay> | ||
| 3704 | |||
| 3705 | Uma expressão de valor padrão de argumento é avaliada no corpo da função na ordem das declarações de argumentos. Por esse motivo, os valores padrão têm acesso aos argumentos declarados anteriormente. | ||
| 3706 | |||
| 3707 | ```yuescript | ||
| 3708 | some_args = (x = 100, y = x + 1000) -> | ||
| 3709 | print x + y | ||
| 3710 | ``` | ||
| 3711 | |||
| 3712 | <YueDisplay> | ||
| 3713 | |||
| 3714 | ```yue | ||
| 3715 | some_args = (x = 100, y = x + 1000) -> | ||
| 3716 | print x + y | ||
| 3717 | ``` | ||
| 3718 | |||
| 3719 | </YueDisplay> | ||
| 3720 | |||
| 3721 | ## Considerações | ||
| 3722 | |||
| 3723 | Devido à forma expressiva de chamar funções sem parênteses, algumas restrições devem ser colocadas para evitar ambiguidade de análise envolvendo espaço em branco. | ||
| 3724 | |||
| 3725 | O sinal de menos desempenha dois papéis: um operador de negação unário e um operador de subtração binário. Considere como os seguintes exemplos compilam: | ||
| 3726 | |||
| 3727 | ```yuescript | ||
| 3728 | a = x - 10 | ||
| 3729 | b = x-10 | ||
| 3730 | c = x -y | ||
| 3731 | d = x- z | ||
| 3732 | ``` | ||
| 3733 | |||
| 3734 | <YueDisplay> | ||
| 3735 | |||
| 3736 | ```yue | ||
| 3737 | a = x - 10 | ||
| 3738 | b = x-10 | ||
| 3739 | c = x -y | ||
| 3740 | d = x- z | ||
| 3741 | ``` | ||
| 3742 | |||
| 3743 | </YueDisplay> | ||
| 3744 | |||
| 3745 | A precedência do primeiro argumento de uma chamada de função pode ser controlada usando espaço em branco se o argumento for um literal de string. Em Lua, é comum omitir parênteses ao chamar uma função com uma única string ou literal de tabela. | ||
| 3746 | |||
| 3747 | Quando não há espaço entre uma variável e um literal de string, a chamada de função tem precedência sobre quaisquer expressões seguintes. Nenhum outro argumento pode ser passado para a função quando ela é chamada dessa forma. | ||
| 3748 | |||
| 3749 | Quando há um espaço após uma variável e um literal de string, a chamada de função age como mostrado acima. O literal de string pertence a quaisquer expressões seguintes (se existirem), que servem como lista de argumentos. | ||
| 3750 | |||
| 3751 | ```yuescript | ||
| 3752 | x = func"hello" + 100 | ||
| 3753 | y = func "hello" + 100 | ||
| 3754 | ``` | ||
| 3755 | |||
| 3756 | <YueDisplay> | ||
| 3757 | |||
| 3758 | ```yue | ||
| 3759 | x = func"hello" + 100 | ||
| 3760 | y = func "hello" + 100 | ||
| 3761 | ``` | ||
| 3762 | |||
| 3763 | </YueDisplay> | ||
| 3764 | |||
| 3765 | ## Argumentos multilinha | ||
| 3766 | |||
| 3767 | Ao chamar funções que recebem um grande número de argumentos, é conveniente dividir a lista de argumentos em várias linhas. Devido à natureza sensível a espaço em branco da linguagem, deve-se ter cuidado ao dividir a lista de argumentos. | ||
| 3768 | |||
| 3769 | Se uma lista de argumentos for continuada na próxima linha, a linha atual deve terminar em vírgula. E a linha seguinte deve estar mais indentada que a indentação atual. Uma vez indentada, todas as outras linhas de argumentos devem estar no mesmo nível de indentação para fazer parte da lista de argumentos. | ||
| 3770 | |||
| 3771 | ```yuescript | ||
| 3772 | my_func 5, 4, 3, | ||
| 3773 | 8, 9, 10 | ||
| 3774 | |||
| 3775 | cool_func 1, 2, | ||
| 3776 | 3, 4, | ||
| 3777 | 5, 6, | ||
| 3778 | 7, 8 | ||
| 3779 | ``` | ||
| 3780 | |||
| 3781 | <YueDisplay> | ||
| 3782 | |||
| 3783 | ```yue | ||
| 3784 | my_func 5, 4, 3, | ||
| 3785 | 8, 9, 10 | ||
| 3786 | |||
| 3787 | cool_func 1, 2, | ||
| 3788 | 3, 4, | ||
| 3789 | 5, 6, | ||
| 3790 | 7, 8 | ||
| 3791 | ``` | ||
| 3792 | |||
| 3793 | </YueDisplay> | ||
| 3794 | |||
| 3795 | Este tipo de invocação pode ser aninhado. O nível de indentação é usado para determinar a qual função os argumentos pertencem. | ||
| 3796 | |||
| 3797 | ```yuescript | ||
| 3798 | my_func 5, 6, 7, | ||
| 3799 | 6, another_func 6, 7, 8, | ||
| 3800 | 9, 1, 2, | ||
| 3801 | 5, 4 | ||
| 3802 | ``` | ||
| 3803 | |||
| 3804 | <YueDisplay> | ||
| 3805 | |||
| 3806 | ```yue | ||
| 3807 | my_func 5, 6, 7, | ||
| 3808 | 6, another_func 6, 7, 8, | ||
| 3809 | 9, 1, 2, | ||
| 3810 | 5, 4 | ||
| 3811 | ``` | ||
| 3812 | |||
| 3813 | </YueDisplay> | ||
| 3814 | |||
| 3815 | Como as tabelas também usam vírgula como delimitador, esta sintaxe de indentação ajuda a deixar os valores fazerem parte da lista de argumentos em vez de fazerem parte da tabela. | ||
| 3816 | |||
| 3817 | ```yuescript | ||
| 3818 | x = [ | ||
| 3819 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3820 | 5, 6, | ||
| 3821 | 8, 9, 10 | ||
| 3822 | ] | ||
| 3823 | ``` | ||
| 3824 | |||
| 3825 | <YueDisplay> | ||
| 3826 | |||
| 3827 | ```yue | ||
| 3828 | x = [ | ||
| 3829 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3830 | 5, 6, | ||
| 3831 | 8, 9, 10 | ||
| 3832 | ] | ||
| 3833 | ``` | ||
| 3834 | |||
| 3835 | </YueDisplay> | ||
| 3836 | |||
| 3837 | Embora incomum, observe como podemos dar uma indentação mais profunda para argumentos de função se soubermos que usaremos uma indentação menor mais adiante. | ||
| 3838 | |||
| 3839 | ```yuescript | ||
| 3840 | y = [ my_func 1, 2, 3, | ||
| 3841 | 4, 5, | ||
| 3842 | 5, 6, 7 | ||
| 3843 | ] | ||
| 3844 | ``` | ||
| 3845 | |||
| 3846 | <YueDisplay> | ||
| 3847 | |||
| 3848 | ```yue | ||
| 3849 | y = [ my_func 1, 2, 3, | ||
| 3850 | 4, 5, | ||
| 3851 | 5, 6, 7 | ||
| 3852 | ] | ||
| 3853 | ``` | ||
| 3854 | |||
| 3855 | </YueDisplay> | ||
| 3856 | |||
| 3857 | A mesma coisa pode ser feita com outras instruções em nível de bloco como condicionais. Podemos usar o nível de indentação para determinar a qual instrução um valor pertence: | ||
| 3858 | |||
| 3859 | ```yuescript | ||
| 3860 | if func 1, 2, 3, | ||
| 3861 | "hello", | ||
| 3862 | "world" | ||
| 3863 | print "hello" | ||
| 3864 | print "I am inside if" | ||
| 3865 | |||
| 3866 | if func 1, 2, 3, | ||
| 3867 | "hello", | ||
| 3868 | "world" | ||
| 3869 | print "hello" | ||
| 3870 | print "I am inside if" | ||
| 3871 | ``` | ||
| 3872 | |||
| 3873 | <YueDisplay> | ||
| 3874 | |||
| 3875 | ```yue | ||
| 3876 | if func 1, 2, 3, | ||
| 3877 | "hello", | ||
| 3878 | "world" | ||
| 3879 | print "hello" | ||
| 3880 | print "I am inside if" | ||
| 3881 | |||
| 3882 | if func 1, 2, 3, | ||
| 3883 | "hello", | ||
| 3884 | "world" | ||
| 3885 | print "hello" | ||
| 3886 | print "I am inside if" | ||
| 3887 | ``` | ||
| 3888 | |||
| 3889 | </YueDisplay> | ||
| 3890 | |||
| 3891 | ## Desestruturação de parâmetros | ||
| 3892 | |||
| 3893 | YueScript agora suporta desestruturação de parâmetros de função quando o argumento é um objeto. Duas formas de literais de tabela de desestruturação estão disponíveis: | ||
| 3894 | |||
| 3895 | - **Literais/parâmetros de objeto envolvidos em chaves**, permitindo valores padrão opcionais quando os campos estão ausentes (ex.: `{:a, :b}`, `{a: a1 = 123}`). | ||
| 3896 | |||
| 3897 | - **Sintaxe de tabela simples não envolvida**, começando com uma sequência de ligações chave-valor ou abreviadas e continuando até outra expressão terminá-la (ex.: `:a, b: b1, :c`). Esta forma extrai múltiplos campos do mesmo objeto. | ||
| 3898 | |||
| 3899 | ```yuescript | ||
| 3900 | f1 = (:a, :b, :c) -> | ||
| 3901 | print a, b, c | ||
| 3902 | |||
| 3903 | f1 a: 1, b: "2", c: {} | ||
| 3904 | |||
| 3905 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3906 | print a1, b, c | ||
| 3907 | |||
| 3908 | arg1 = {a: 0} | ||
| 3909 | f2 arg1, arg2 | ||
| 3910 | ``` | ||
| 3911 | |||
| 3912 | <YueDisplay> | ||
| 3913 | |||
| 3914 | ```yue | ||
| 3915 | f1 = (:a, :b, :c) -> | ||
| 3916 | print a, b, c | ||
| 3917 | |||
| 3918 | f1 a: 1, b: "2", c: {} | ||
| 3919 | |||
| 3920 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3921 | print a1, b, c | ||
| 3922 | |||
| 3923 | arg1 = {a: 0} | ||
| 3924 | f2 arg1, arg2 | ||
| 3925 | ``` | ||
| 3926 | |||
| 3927 | </YueDisplay> | ||
| 3928 | |||
| 3929 | ## Expressão de retorno prefixada | ||
| 3930 | |||
| 3931 | Ao trabalhar com corpos de função profundamente aninhados, pode ser tedioso manter a legibilidade e consistência do valor de retorno. Para resolver isso, YueScript introduz a sintaxe **Expressão de Retorno Prefixada**. Sua forma é a seguinte: | ||
| 3932 | |||
| 3933 | ```yuescript | ||
| 3934 | findFirstEven = (list): nil -> | ||
| 3935 | for item in *list | ||
| 3936 | if type(item) == "table" | ||
| 3937 | for sub in *item | ||
| 3938 | if sub % 2 == 0 | ||
| 3939 | return sub | ||
| 3940 | ``` | ||
| 3941 | |||
| 3942 | <YueDisplay> | ||
| 3943 | |||
| 3944 | ```yue | ||
| 3945 | findFirstEven = (list): nil -> | ||
| 3946 | for item in *list | ||
| 3947 | if type(item) == "table" | ||
| 3948 | for sub in *item | ||
| 3949 | if sub % 2 == 0 | ||
| 3950 | return sub | ||
| 3951 | ``` | ||
| 3952 | |||
| 3953 | </YueDisplay> | ||
| 3954 | |||
| 3955 | Isso é equivalente a: | ||
| 3956 | |||
| 3957 | ```yuescript | ||
| 3958 | findFirstEven = (list) -> | ||
| 3959 | for item in *list | ||
| 3960 | if type(item) == "table" | ||
| 3961 | for sub in *item | ||
| 3962 | if sub % 2 == 0 | ||
| 3963 | return sub | ||
| 3964 | nil | ||
| 3965 | ``` | ||
| 3966 | |||
| 3967 | <YueDisplay> | ||
| 3968 | |||
| 3969 | ```yue | ||
| 3970 | findFirstEven = (list) -> | ||
| 3971 | for item in *list | ||
| 3972 | if type(item) == "table" | ||
| 3973 | for sub in *item | ||
| 3974 | if sub % 2 == 0 | ||
| 3975 | return sub | ||
| 3976 | nil | ||
| 3977 | ``` | ||
| 3978 | |||
| 3979 | </YueDisplay> | ||
| 3980 | |||
| 3981 | A única diferença é que você pode mover a expressão de retorno final antes do token `->` ou `=>` para indicar o valor de retorno implícito da função como última instrução. Dessa forma, mesmo em funções com múltiplos loops aninhados ou ramificações condicionais, você não precisa mais escrever uma expressão de retorno no final do corpo da função, tornando a estrutura lógica mais direta e fácil de seguir. | ||
| 3982 | |||
| 3983 | ## Varargs nomeados | ||
| 3984 | |||
| 3985 | Você pode usar a sintaxe `(...t) ->` para armazenar automaticamente varargs em uma tabela nomeada. Esta tabela conterá todos os argumentos passados (incluindo valores `nil`), e o campo `n` da tabela armazenará o número real de argumentos passados (incluindo valores `nil`). | ||
| 3986 | |||
| 3987 | ```yuescript | ||
| 3988 | f = (...t) -> | ||
| 3989 | print "contagem de argumentos:", t.n | ||
| 3990 | print "comprimento da tabela:", #t | ||
| 3991 | for i = 1, t.n | ||
| 3992 | print t[i] | ||
| 3993 | |||
| 3994 | f 1, 2, 3 | ||
| 3995 | f "a", "b", "c", "d" | ||
| 3996 | f! | ||
| 3997 | |||
| 3998 | -- Tratando casos com valores nil | ||
| 3999 | process = (...args) -> | ||
| 4000 | sum = 0 | ||
| 4001 | for i = 1, args.n | ||
| 4002 | if args[i] != nil and type(args[i]) == "number" | ||
| 4003 | sum += args[i] | ||
| 4004 | sum | ||
| 4005 | |||
| 4006 | process 1, nil, 3, nil, 5 | ||
| 4007 | ``` | ||
| 4008 | |||
| 4009 | <YueDisplay> | ||
| 4010 | |||
| 4011 | ```yue | ||
| 4012 | f = (...t) -> | ||
| 4013 | print "contagem de argumentos:", t.n | ||
| 4014 | print "comprimento da tabela:", #t | ||
| 4015 | for i = 1, t.n | ||
| 4016 | print t[i] | ||
| 4017 | |||
| 4018 | f 1, 2, 3 | ||
| 4019 | f "a", "b", "c", "d" | ||
| 4020 | f! | ||
| 4021 | |||
| 4022 | -- Tratando casos com valores nil | ||
| 4023 | process = (...args) -> | ||
| 4024 | sum = 0 | ||
| 4025 | for i = 1, args.n | ||
| 4026 | if args[i] != nil and type(args[i]) == "number" | ||
| 4027 | sum += args[i] | ||
| 4028 | sum | ||
| 4029 | |||
| 4030 | process 1, nil, 3, nil, 5 | ||
| 4031 | ``` | ||
| 4032 | |||
| 4033 | </YueDisplay> | ||
| 4034 | |||
| 4035 | # Espaço em branco | ||
| 4036 | |||
| 4037 | YueScript é uma linguagem sensível a espaço em branco. Você precisa escrever blocos de código na mesma indentação com espaço **' '** ou tabulação **'\t'**, como corpo de função, lista de valores e alguns blocos de controle. E expressões contendo diferentes espaços em branco podem significar coisas diferentes. Tabulação é tratada como 4 espaços, mas é melhor não misturar o uso de espaços e tabulações. | ||
| 4038 | |||
| 4039 | ## Separador de instrução | ||
| 4040 | |||
| 4041 | Uma instrução normalmente termina em uma quebra de linha. Você também pode usar ponto e vírgula `;` para terminar explicitamente uma instrução, o que permite escrever múltiplas instruções na mesma linha: | ||
| 4042 | |||
| 4043 | ```yuescript | ||
| 4044 | a = 1; b = 2; print a + b | ||
| 4045 | ``` | ||
| 4046 | |||
| 4047 | <YueDisplay> | ||
| 4048 | |||
| 4049 | ```yue | ||
| 4050 | a = 1; b = 2; print a + b | ||
| 4051 | ``` | ||
| 4052 | |||
| 4053 | </YueDisplay> | ||
| 4054 | |||
| 4055 | ## Encadeamento multilinha | ||
| 4056 | |||
| 4057 | Você pode escrever chamadas de função encadeadas em múltiplas linhas com a mesma indentação. | ||
| 4058 | |||
| 4059 | ```yuescript | ||
| 4060 | Rx.Observable | ||
| 4061 | .fromRange 1, 8 | ||
| 4062 | \filter (x) -> x % 2 == 0 | ||
| 4063 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4064 | \map (value) -> value .. '!' | ||
| 4065 | \subscribe print | ||
| 4066 | ``` | ||
| 4067 | |||
| 4068 | <YueDisplay> | ||
| 4069 | |||
| 4070 | ```yue | ||
| 4071 | Rx.Observable | ||
| 4072 | .fromRange 1, 8 | ||
| 4073 | \filter (x) -> x % 2 == 0 | ||
| 4074 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4075 | \map (value) -> value .. '!' | ||
| 4076 | \subscribe print | ||
| 4077 | ``` | ||
| 4078 | |||
| 4079 | </YueDisplay> | ||
| 4080 | |||
| 4081 | # Comentário | ||
| 4082 | |||
| 4083 | ```yuescript | ||
| 4084 | -- Eu sou um comentário | ||
| 4085 | |||
| 4086 | str = --[[ | ||
| 4087 | Este é um comentário multilinha. | ||
| 4088 | Está OK. | ||
| 4089 | ]] strA \ -- comentário 1 | ||
| 4090 | .. strB \ -- comentário 2 | ||
| 4091 | .. strC | ||
| 4092 | |||
| 4093 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4094 | ``` | ||
| 4095 | |||
| 4096 | <YueDisplay> | ||
| 4097 | |||
| 4098 | ```yue | ||
| 4099 | -- Eu sou um comentário | ||
| 4100 | |||
| 4101 | str = --[[ | ||
| 4102 | Este é um comentário multilinha. | ||
| 4103 | Está OK. | ||
| 4104 | ]] strA \ -- comentário 1 | ||
| 4105 | .. strB \ -- comentário 2 | ||
| 4106 | .. strC | ||
| 4107 | |||
| 4108 | func --[[port]] 3000, --[[ip]] "192.168.1.1" | ||
| 4109 | ``` | ||
| 4110 | |||
| 4111 | </YueDisplay> | ||
| 4112 | |||
| 4113 | # Atributos | ||
| 4114 | |||
| 4115 | Suporte de sintaxe para atributos do Lua 5.4. E você ainda pode usar tanto a declaração `const` quanto `close` e obter verificação de constante e callback com escopo funcionando ao direcionar para versões do Lua abaixo da 5.4. | ||
| 4116 | |||
| 4117 | ```yuescript | ||
| 4118 | const a = 123 | ||
| 4119 | close _ = <close>: -> print "Fora do escopo." | ||
| 4120 | ``` | ||
| 4121 | |||
| 4122 | <YueDisplay> | ||
| 4123 | |||
| 4124 | ```yue | ||
| 4125 | const a = 123 | ||
| 4126 | close _ = <close>: -> print "Fora do escopo." | ||
| 4127 | ``` | ||
| 4128 | |||
| 4129 | </YueDisplay> | ||
| 4130 | |||
| 4131 | Você pode fazer desestruturação com variáveis atribuídas como constante. | ||
| 4132 | |||
| 4133 | ```yuescript | ||
| 4134 | const {:a, :b, c, d} = tb | ||
| 4135 | -- a = 1 | ||
| 4136 | ``` | ||
| 4137 | |||
| 4138 | <YueDisplay> | ||
| 4139 | |||
| 4140 | ```yue | ||
| 4141 | const {:a, :b, c, d} = tb | ||
| 4142 | -- a = 1 | ||
| 4143 | ``` | ||
| 4144 | |||
| 4145 | </YueDisplay> | ||
| 4146 | |||
| 4147 | Você também pode declarar uma variável global como `const`. | ||
| 4148 | |||
| 4149 | ```yuescript | ||
| 4150 | global const Constant = 123 | ||
| 4151 | -- Constant = 1 | ||
| 4152 | ``` | ||
| 4153 | |||
| 4154 | <YueDisplay> | ||
| 4155 | |||
| 4156 | ```yue | ||
| 4157 | global const Constant = 123 | ||
| 4158 | -- Constant = 1 | ||
| 4159 | ``` | ||
| 4160 | |||
| 4161 | </YueDisplay> | ||
| 4162 | |||
| 4163 | # Operador | ||
| 4164 | |||
| 4165 | Todos os operadores binários e unários do Lua estão disponíveis. Além disso, **!=** é um alias para **~=**, e **\\** ou **::** podem ser usados para escrever uma chamada de função encadeada como `tb\func!` ou `tb::func!`. E o YueScript oferece alguns outros operadores especiais para escrever códigos mais expressivos. | ||
| 4166 | |||
| 4167 | ```yuescript | ||
| 4168 | tb\func! if tb ~= nil | ||
| 4169 | tb::func! if tb != nil | ||
| 4170 | ``` | ||
| 4171 | |||
| 4172 | <YueDisplay> | ||
| 4173 | |||
| 4174 | ```yue | ||
| 4175 | tb\func! if tb ~= nil | ||
| 4176 | tb::func! if tb != nil | ||
| 4177 | ``` | ||
| 4178 | |||
| 4179 | </YueDisplay> | ||
| 4180 | |||
| 4181 | ## Comparações encadeadas | ||
| 4182 | |||
| 4183 | Comparações podem ser encadeadas arbitrariamente: | ||
| 4184 | |||
| 4185 | ```yuescript | ||
| 4186 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4187 | -- saída: true | ||
| 4188 | |||
| 4189 | a = 5 | ||
| 4190 | print 1 <= a <= 10 | ||
| 4191 | -- saída: true | ||
| 4192 | ``` | ||
| 4193 | |||
| 4194 | <YueDisplay> | ||
| 4195 | |||
| 4196 | ```yue | ||
| 4197 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4198 | -- saída: true | ||
| 4199 | |||
| 4200 | a = 5 | ||
| 4201 | print 1 <= a <= 10 | ||
| 4202 | -- saída: true | ||
| 4203 | ``` | ||
| 4204 | |||
| 4205 | </YueDisplay> | ||
| 4206 | |||
| 4207 | Observe o comportamento de avaliação das comparações encadeadas: | ||
| 4208 | |||
| 4209 | ```yuescript | ||
| 4210 | v = (x) -> | ||
| 4211 | print x | ||
| 4212 | x | ||
| 4213 | |||
| 4214 | print v(1) < v(2) <= v(3) | ||
| 4215 | --[[ | ||
| 4216 | saída: | ||
| 4217 | 2 | ||
| 4218 | 1 | ||
| 4219 | 3 | ||
| 4220 | true | ||
| 4221 | ]] | ||
| 4222 | |||
| 4223 | print v(1) > v(2) <= v(3) | ||
| 4224 | --[[ | ||
| 4225 | saída: | ||
| 4226 | 2 | ||
| 4227 | 1 | ||
| 4228 | false | ||
| 4229 | ]] | ||
| 4230 | ``` | ||
| 4231 | |||
| 4232 | <YueDisplay> | ||
| 4233 | |||
| 4234 | ```yue | ||
| 4235 | v = (x) -> | ||
| 4236 | print x | ||
| 4237 | x | ||
| 4238 | |||
| 4239 | print v(1) < v(2) <= v(3) | ||
| 4240 | --[[ | ||
| 4241 | saída: | ||
| 4242 | 2 | ||
| 4243 | 1 | ||
| 4244 | 3 | ||
| 4245 | true | ||
| 4246 | ]] | ||
| 4247 | |||
| 4248 | print v(1) > v(2) <= v(3) | ||
| 4249 | --[[ | ||
| 4250 | saída: | ||
| 4251 | 2 | ||
| 4252 | 1 | ||
| 4253 | false | ||
| 4254 | ]] | ||
| 4255 | ``` | ||
| 4256 | |||
| 4257 | </YueDisplay> | ||
| 4258 | |||
| 4259 | A expressão do meio é avaliada apenas uma vez, em vez de duas vezes como seria se a expressão fosse escrita como `v(1) < v(2) and v(2) <= v(3)`. No entanto, a ordem das avaliações em uma comparação encadeada é indefinida. É fortemente recomendado não usar expressões com efeitos colaterais (como impressão) em comparações encadeadas. Se efeitos colaterais forem necessários, o operador de curto-circuito `and` deve ser usado explicitamente. | ||
| 4260 | |||
| 4261 | ## Anexar à tabela | ||
| 4262 | |||
| 4263 | O operador **[] =** é usado para anexar valores a tabelas. | ||
| 4264 | |||
| 4265 | ```yuescript | ||
| 4266 | tab = [] | ||
| 4267 | tab[] = "Value" | ||
| 4268 | ``` | ||
| 4269 | |||
| 4270 | <YueDisplay> | ||
| 4271 | |||
| 4272 | ```yue | ||
| 4273 | tab = [] | ||
| 4274 | tab[] = "Value" | ||
| 4275 | ``` | ||
| 4276 | |||
| 4277 | </YueDisplay> | ||
| 4278 | |||
| 4279 | Você também pode usar o operador spread `...` para anexar todos os elementos de uma lista a outra: | ||
| 4280 | |||
| 4281 | ```yuescript | ||
| 4282 | tbA = [1, 2, 3] | ||
| 4283 | tbB = [4, 5, 6] | ||
| 4284 | tbA[] = ...tbB | ||
| 4285 | -- tbA agora é [1, 2, 3, 4, 5, 6] | ||
| 4286 | ``` | ||
| 4287 | |||
| 4288 | <YueDisplay> | ||
| 4289 | |||
| 4290 | ```yue | ||
| 4291 | tbA = [1, 2, 3] | ||
| 4292 | tbB = [4, 5, 6] | ||
| 4293 | tbA[] = ...tbB | ||
| 4294 | -- tbA agora é [1, 2, 3, 4, 5, 6] | ||
| 4295 | ``` | ||
| 4296 | |||
| 4297 | </YueDisplay> | ||
| 4298 | |||
| 4299 | ## Spread de tabela | ||
| 4300 | |||
| 4301 | Você pode concatenar tabelas de array ou tabelas hash usando o operador spread `...` antes de expressões em literais de tabela. | ||
| 4302 | |||
| 4303 | ```yuescript | ||
| 4304 | parts = | ||
| 4305 | * "shoulders" | ||
| 4306 | * "knees" | ||
| 4307 | lyrics = | ||
| 4308 | * "head" | ||
| 4309 | * ...parts | ||
| 4310 | * "and" | ||
| 4311 | * "toes" | ||
| 4312 | |||
| 4313 | copy = {...other} | ||
| 4314 | |||
| 4315 | a = {1, 2, 3, x: 1} | ||
| 4316 | b = {4, 5, y: 1} | ||
| 4317 | merge = {...a, ...b} | ||
| 4318 | ``` | ||
| 4319 | |||
| 4320 | <YueDisplay> | ||
| 4321 | |||
| 4322 | ```yue | ||
| 4323 | parts = | ||
| 4324 | * "shoulders" | ||
| 4325 | * "knees" | ||
| 4326 | lyrics = | ||
| 4327 | * "head" | ||
| 4328 | * ...parts | ||
| 4329 | * "and" | ||
| 4330 | * "toes" | ||
| 4331 | |||
| 4332 | copy = {...other} | ||
| 4333 | |||
| 4334 | a = {1, 2, 3, x: 1} | ||
| 4335 | b = {4, 5, y: 1} | ||
| 4336 | merge = {...a, ...b} | ||
| 4337 | ``` | ||
| 4338 | |||
| 4339 | </YueDisplay> | ||
| 4340 | |||
| 4341 | ## Indexação reversa de tabela | ||
| 4342 | |||
| 4343 | Você pode usar o operador **#** para obter os últimos elementos de uma tabela. | ||
| 4344 | |||
| 4345 | ```yuescript | ||
| 4346 | last = data.items[#] | ||
| 4347 | second_last = data.items[#-1] | ||
| 4348 | data.items[#] = 1 | ||
| 4349 | ``` | ||
| 4350 | |||
| 4351 | <YueDisplay> | ||
| 4352 | |||
| 4353 | ```yue | ||
| 4354 | last = data.items[#] | ||
| 4355 | second_last = data.items[#-1] | ||
| 4356 | data.items[#] = 1 | ||
| 4357 | ``` | ||
| 4358 | |||
| 4359 | </YueDisplay> | ||
| 4360 | |||
| 4361 | ## Metatable | ||
| 4362 | |||
| 4363 | O operador **<>** pode ser usado como atalho para manipulação de metatable. | ||
| 4364 | |||
| 4365 | ### Criação de metatable | ||
| 4366 | |||
| 4367 | Crie tabela normal com chaves vazias **<>** ou chave de metamétodo cercada por **<>**. | ||
| 4368 | |||
| 4369 | ```yuescript | ||
| 4370 | mt = {} | ||
| 4371 | add = (right) => <>: mt, value: @value + right.value | ||
| 4372 | mt.__add = add | ||
| 4373 | |||
| 4374 | a = <>: mt, value: 1 | ||
| 4375 | -- definir campo com variável de mesmo nome | ||
| 4376 | b = :<add>, value: 2 | ||
| 4377 | c = <add>: mt.__add, value: 3 | ||
| 4378 | |||
| 4379 | d = a + b + c | ||
| 4380 | print d.value | ||
| 4381 | |||
| 4382 | close _ = <close>: -> print "fora do escopo" | ||
| 4383 | ``` | ||
| 4384 | |||
| 4385 | <YueDisplay> | ||
| 4386 | |||
| 4387 | ```yue | ||
| 4388 | mt = {} | ||
| 4389 | add = (right) => <>: mt, value: @value + right.value | ||
| 4390 | mt.__add = add | ||
| 4391 | |||
| 4392 | a = <>: mt, value: 1 | ||
| 4393 | -- definir campo com variável de mesmo nome | ||
| 4394 | b = :<add>, value: 2 | ||
| 4395 | c = <add>: mt.__add, value: 3 | ||
| 4396 | |||
| 4397 | d = a + b + c | ||
| 4398 | print d.value | ||
| 4399 | |||
| 4400 | close _ = <close>: -> print "fora do escopo" | ||
| 4401 | ``` | ||
| 4402 | |||
| 4403 | </YueDisplay> | ||
| 4404 | |||
| 4405 | ### Acesso à metatable | ||
| 4406 | |||
| 4407 | Acesse a metatable com **<>** ou nome do metamétodo cercado por **<>** ou escrevendo alguma expressão em **<>**. | ||
| 4408 | |||
| 4409 | ```yuescript | ||
| 4410 | -- criar com metatable contendo campo "value" | ||
| 4411 | tb = <"value">: 123 | ||
| 4412 | tb.<index> = tb.<> | ||
| 4413 | print tb.value | ||
| 4414 | |||
| 4415 | tb.<> = __index: {item: "hello"} | ||
| 4416 | print tb.item | ||
| 4417 | ``` | ||
| 4418 | |||
| 4419 | <YueDisplay> | ||
| 4420 | |||
| 4421 | ```yue | ||
| 4422 | -- criar com metatable contendo campo "value" | ||
| 4423 | tb = <"value">: 123 | ||
| 4424 | tb.<index> = tb.<> | ||
| 4425 | print tb.value | ||
| 4426 | tb.<> = __index: {item: "hello"} | ||
| 4427 | print tb.item | ||
| 4428 | ``` | ||
| 4429 | |||
| 4430 | </YueDisplay> | ||
| 4431 | |||
| 4432 | ### Desestruturação de metatable | ||
| 4433 | |||
| 4434 | Desestruture a metatable com chave de metamétodo cercada por **<>**. | ||
| 4435 | |||
| 4436 | ```yuescript | ||
| 4437 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4438 | print item, new, close, getter | ||
| 4439 | ``` | ||
| 4440 | |||
| 4441 | <YueDisplay> | ||
| 4442 | |||
| 4443 | ```yue | ||
| 4444 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4445 | print item, new, close, getter | ||
| 4446 | ``` | ||
| 4447 | |||
| 4448 | </YueDisplay> | ||
| 4449 | |||
| 4450 | ## Existência | ||
| 4451 | |||
| 4452 | O operador **?** pode ser usado em diversos contextos para verificar existência. | ||
| 4453 | |||
| 4454 | ```yuescript | ||
| 4455 | func?! | ||
| 4456 | print abc?["hello world"]?.xyz | ||
| 4457 | |||
| 4458 | x = tab?.value | ||
| 4459 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4460 | |||
| 4461 | if print and x? | ||
| 4462 | print x | ||
| 4463 | |||
| 4464 | with? io.open "test.txt", "w" | ||
| 4465 | \write "hello" | ||
| 4466 | \close! | ||
| 4467 | ``` | ||
| 4468 | |||
| 4469 | <YueDisplay> | ||
| 4470 | |||
| 4471 | ```yue | ||
| 4472 | func?! | ||
| 4473 | print abc?["hello world"]?.xyz | ||
| 4474 | |||
| 4475 | x = tab?.value | ||
| 4476 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4477 | |||
| 4478 | if print and x? | ||
| 4479 | print x | ||
| 4480 | |||
| 4481 | with? io.open "test.txt", "w" | ||
| 4482 | \write "hello" | ||
| 4483 | \close! | ||
| 4484 | ``` | ||
| 4485 | |||
| 4486 | </YueDisplay> | ||
| 4487 | |||
| 4488 | ## Pipe | ||
| 4489 | |||
| 4490 | Em vez de uma série de chamadas de função aninhadas, você pode encaminhar valores com o operador **|>**. | ||
| 4491 | |||
| 4492 | ```yuescript | ||
| 4493 | "hello" |> print | ||
| 4494 | 1 |> print 2 -- insere o item do pipe como primeiro argumento | ||
| 4495 | 2 |> print 1, _, 3 -- pipe com um placeholder | ||
| 4496 | |||
| 4497 | -- expressão pipe em multilinha | ||
| 4498 | readFile "example.txt" | ||
| 4499 | |> extract language, {} | ||
| 4500 | |> parse language | ||
| 4501 | |> emit | ||
| 4502 | |> render | ||
| 4503 | |||
| 4504 | ``` | ||
| 4505 | |||
| 4506 | <YueDisplay> | ||
| 4507 | |||
| 4508 | ```yue | ||
| 4509 | "hello" |> print | ||
| 4510 | 1 |> print 2 -- insere o item do pipe como primeiro argumento | ||
| 4511 | 2 |> print 1, _, 3 -- pipe com um placeholder | ||
| 4512 | -- expressão pipe em multilinha | ||
| 4513 | readFile "example.txt" | ||
| 4514 | |> extract language, {} | ||
| 4515 | |> parse language | ||
| 4516 | |> emit | ||
| 4517 | |> render | ||
| 4518 | |||
| 4519 | ``` | ||
| 4520 | |||
| 4521 | </YueDisplay> | ||
| 4522 | |||
| 4523 | ## Coalescência de nil | ||
| 4524 | |||
| 4525 | O operador de coalescência de nil **??** retorna o valor do operando esquerdo se não for **nil**; caso contrário, avalia o operando direito e retorna seu resultado. O operador **??** não avalia seu operando direito se o operando esquerdo avaliar para não-nil. | ||
| 4526 | |||
| 4527 | ```yuescript | ||
| 4528 | local a, b, c, d | ||
| 4529 | a = b ?? c ?? d | ||
| 4530 | func a ?? {} | ||
| 4531 | |||
| 4532 | a ??= false | ||
| 4533 | ``` | ||
| 4534 | |||
| 4535 | <YueDisplay> | ||
| 4536 | |||
| 4537 | ```yue | ||
| 4538 | local a, b, c, d | ||
| 4539 | a = b ?? c ?? d | ||
| 4540 | func a ?? {} | ||
| 4541 | a ??= false | ||
| 4542 | ``` | ||
| 4543 | |||
| 4544 | </YueDisplay> | ||
| 4545 | |||
| 4546 | ## Objeto implícito | ||
| 4547 | |||
| 4548 | Você pode escrever uma lista de estruturas implícitas que começa com o símbolo **\*** ou **-** dentro de um bloco de tabela. Se você está criando objeto implícito, os campos do objeto devem estar com a mesma indentação. | ||
| 4549 | |||
| 4550 | ```yuescript | ||
| 4551 | -- atribuição com objeto implícito | ||
| 4552 | list = | ||
| 4553 | * 1 | ||
| 4554 | * 2 | ||
| 4555 | * 3 | ||
| 4556 | |||
| 4557 | -- chamada de função com objeto implícito | ||
| 4558 | func | ||
| 4559 | * 1 | ||
| 4560 | * 2 | ||
| 4561 | * 3 | ||
| 4562 | |||
| 4563 | -- retorno com objeto implícito | ||
| 4564 | f = -> | ||
| 4565 | return | ||
| 4566 | * 1 | ||
| 4567 | * 2 | ||
| 4568 | * 3 | ||
| 4569 | |||
| 4570 | -- tabela com objeto implícito | ||
| 4571 | tb = | ||
| 4572 | name: "abc" | ||
| 4573 | |||
| 4574 | values: | ||
| 4575 | - "a" | ||
| 4576 | - "b" | ||
| 4577 | - "c" | ||
| 4578 | |||
| 4579 | objects: | ||
| 4580 | - name: "a" | ||
| 4581 | value: 1 | ||
| 4582 | func: => @value + 1 | ||
| 4583 | tb: | ||
| 4584 | fieldA: 1 | ||
| 4585 | |||
| 4586 | - name: "b" | ||
| 4587 | value: 2 | ||
| 4588 | func: => @value + 2 | ||
| 4589 | tb: { } | ||
| 4590 | |||
| 4591 | ``` | ||
| 4592 | |||
| 4593 | <YueDisplay> | ||
| 4594 | |||
| 4595 | ```yue | ||
| 4596 | -- atribuição com objeto implícito | ||
| 4597 | list = | ||
| 4598 | * 1 | ||
| 4599 | * 2 | ||
| 4600 | * 3 | ||
| 4601 | |||
| 4602 | -- chamada de função com objeto implícito | ||
| 4603 | func | ||
| 4604 | * 1 | ||
| 4605 | * 2 | ||
| 4606 | * 3 | ||
| 4607 | |||
| 4608 | -- retorno com objeto implícito | ||
| 4609 | f = -> | ||
| 4610 | return | ||
| 4611 | * 1 | ||
| 4612 | * 2 | ||
| 4613 | * 3 | ||
| 4614 | |||
| 4615 | -- tabela com objeto implícito | ||
| 4616 | tb = | ||
| 4617 | name: "abc" | ||
| 4618 | |||
| 4619 | values: | ||
| 4620 | - "a" | ||
| 4621 | - "b" | ||
| 4622 | - "c" | ||
| 4623 | |||
| 4624 | objects: | ||
| 4625 | - name: "a" | ||
| 4626 | value: 1 | ||
| 4627 | func: => @value + 1 | ||
| 4628 | tb: | ||
| 4629 | fieldA: 1 | ||
| 4630 | |||
| 4631 | - name: "b" | ||
| 4632 | value: 2 | ||
| 4633 | func: => @value + 2 | ||
| 4634 | tb: { } | ||
| 4635 | ``` | ||
| 4636 | |||
| 4637 | </YueDisplay> | ||
| 4638 | |||
| 4639 | # Literais | ||
| 4640 | |||
| 4641 | Todos os literais primitivos do Lua podem ser usados. Isso se aplica a números, strings, booleanos e **nil**. | ||
| 4642 | |||
| 4643 | Diferente do Lua, quebras de linha são permitidas dentro de strings com aspas simples e duplas sem sequência de escape: | ||
| 4644 | |||
| 4645 | ```yuescript | ||
| 4646 | some_string = "Aqui está uma string | ||
| 4647 | que tem uma quebra de linha." | ||
| 4648 | |||
| 4649 | -- Você pode misturar expressões em literais de string usando a sintaxe #{}. | ||
| 4650 | -- Interpolação de string está disponível apenas em strings com aspas duplas. | ||
| 4651 | print "Tenho #{math.random! * 100}% de certeza." | ||
| 4652 | ``` | ||
| 4653 | |||
| 4654 | <YueDisplay> | ||
| 4655 | |||
| 4656 | ```yue | ||
| 4657 | some_string = "Aqui está uma string | ||
| 4658 | que tem uma quebra de linha." | ||
| 4659 | |||
| 4660 | -- Você pode misturar expressões em literais de string usando a sintaxe #{}. | ||
| 4661 | -- Interpolação de string está disponível apenas em strings com aspas duplas. | ||
| 4662 | print "Tenho #{math.random! * 100}% de certeza." | ||
| 4663 | ``` | ||
| 4664 | |||
| 4665 | </YueDisplay> | ||
| 4666 | |||
| 4667 | ## Literais numéricos | ||
| 4668 | |||
| 4669 | Você pode usar underscores em um literal numérico para aumentar a legibilidade. | ||
| 4670 | |||
| 4671 | ```yuescript | ||
| 4672 | integer = 1_000_000 | ||
| 4673 | hex = 0xEF_BB_BF | ||
| 4674 | binary = 0B10011 | ||
| 4675 | ``` | ||
| 4676 | |||
| 4677 | <YueDisplay> | ||
| 4678 | |||
| 4679 | ```yue | ||
| 4680 | integer = 1_000_000 | ||
| 4681 | hex = 0xEF_BB_BF | ||
| 4682 | binary = 0B10011 | ||
| 4683 | ``` | ||
| 4684 | |||
| 4685 | </YueDisplay> | ||
| 4686 | |||
| 4687 | ## String multilinha estilo YAML | ||
| 4688 | |||
| 4689 | O prefixo `|` introduz um literal de string multilinha no estilo YAML: | ||
| 4690 | |||
| 4691 | ```yuescript | ||
| 4692 | str = | | ||
| 4693 | key: value | ||
| 4694 | list: | ||
| 4695 | - item1 | ||
| 4696 | - #{expr} | ||
| 4697 | ``` | ||
| 4698 | |||
| 4699 | <YueDisplay> | ||
| 4700 | |||
| 4701 | ```yue | ||
| 4702 | str = | | ||
| 4703 | key: value | ||
| 4704 | list: | ||
| 4705 | - item1 | ||
| 4706 | - #{expr} | ||
| 4707 | ``` | ||
| 4708 | |||
| 4709 | </YueDisplay> | ||
| 4710 | |||
| 4711 | Isso permite escrever texto estruturado multilinha convenientemente. Todas as quebras de linha e indentação são preservadas em relação à primeira linha não vazia, e expressões dentro de `#{...}` são interpoladas automaticamente como `tostring(expr)`. | ||
| 4712 | |||
| 4713 | A string multilinha YAML detecta automaticamente o prefixo comum de espaço em branco à esquerda (indentação mínima em todas as linhas não vazias) e remove-o de todas as linhas. Isso facilita a indentação visual do seu código sem afetar o conteúdo da string resultante. | ||
| 4714 | |||
| 4715 | ```yuescript | ||
| 4716 | fn = -> | ||
| 4717 | str = | | ||
| 4718 | foo: | ||
| 4719 | bar: baz | ||
| 4720 | return str | ||
| 4721 | ``` | ||
| 4722 | |||
| 4723 | <YueDisplay> | ||
| 4724 | |||
| 4725 | ```yue | ||
| 4726 | fn = -> | ||
| 4727 | str = | | ||
| 4728 | foo: | ||
| 4729 | bar: baz | ||
| 4730 | return str | ||
| 4731 | ``` | ||
| 4732 | |||
| 4733 | </YueDisplay> | ||
| 4734 | |||
| 4735 | A indentação interna é preservada em relação ao prefixo comum removido, permitindo estruturas aninhadas limpas. | ||
| 4736 | |||
| 4737 | Todos os caracteres especiais como aspas (`"`) e barras invertidas (`\`) no bloco YAML Multiline são escapados automaticamente para que a string Lua gerada seja sintaticamente válida e se comporte como esperado. | ||
| 4738 | |||
| 4739 | ```yuescript | ||
| 4740 | str = | | ||
| 4741 | path: "C:\Program Files\App" | ||
| 4742 | note: 'Ele disse: "#{Hello}!"' | ||
| 4743 | ``` | ||
| 4744 | |||
| 4745 | <YueDisplay> | ||
| 4746 | |||
| 4747 | ```yue | ||
| 4748 | str = | | ||
| 4749 | path: "C:\Program Files\App" | ||
| 4750 | note: 'Ele disse: "#{Hello}!"' | ||
| 4751 | ``` | ||
| 4752 | |||
| 4753 | </YueDisplay> | ||
| 4754 | |||
| 4755 | # Módulo | ||
| 4756 | |||
| 4757 | ## Import | ||
| 4758 | |||
| 4759 | A instrução import é um açúcar sintático para requerer um módulo ou ajudar a extrair itens de um módulo importado. Os itens importados são const por padrão. | ||
| 4760 | |||
| 4761 | ```yuescript | ||
| 4762 | -- usado como desestruturação de tabela | ||
| 4763 | do | ||
| 4764 | import insert, concat from table | ||
| 4765 | -- reporta erro ao atribuir a insert, concat | ||
| 4766 | import C, Ct, Cmt from require "lpeg" | ||
| 4767 | -- atalho para require implícito | ||
| 4768 | import x, y, z from 'mymodule' | ||
| 4769 | -- import com estilo Python | ||
| 4770 | from 'module' import a, b, c | ||
| 4771 | |||
| 4772 | -- atalho para requerer um módulo | ||
| 4773 | do | ||
| 4774 | import 'module' | ||
| 4775 | import 'module_x' | ||
| 4776 | import "d-a-s-h-e-s" | ||
| 4777 | import "module.part" | ||
| 4778 | |||
| 4779 | -- requerer módulo com aliasing ou desestruturação de tabela | ||
| 4780 | do | ||
| 4781 | import "player" as PlayerModule | ||
| 4782 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4783 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4784 | ``` | ||
| 4785 | |||
| 4786 | <YueDisplay> | ||
| 4787 | |||
| 4788 | ```yue | ||
| 4789 | -- usado como desestruturação de tabela | ||
| 4790 | do | ||
| 4791 | import insert, concat from table | ||
| 4792 | -- reporta erro ao atribuir a insert, concat | ||
| 4793 | import C, Ct, Cmt from require "lpeg" | ||
| 4794 | -- atalho para require implícito | ||
| 4795 | import x, y, z from 'mymodule' | ||
| 4796 | -- import com estilo Python | ||
| 4797 | from 'module' import a, b, c | ||
| 4798 | |||
| 4799 | -- atalho para requerer um módulo | ||
| 4800 | do | ||
| 4801 | import 'module' | ||
| 4802 | import 'module_x' | ||
| 4803 | import "d-a-s-h-e-s" | ||
| 4804 | import "module.part" | ||
| 4805 | |||
| 4806 | -- requerer módulo com aliasing ou desestruturação de tabela | ||
| 4807 | do | ||
| 4808 | import "player" as PlayerModule | ||
| 4809 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4810 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4811 | ``` | ||
| 4812 | |||
| 4813 | </YueDisplay> | ||
| 4814 | |||
| 4815 | ## Import Global | ||
| 4816 | |||
| 4817 | Você pode importar globais específicos para variáveis locais com `import`. Ao importar uma cadeia de acessos a variáveis globais, o último campo será atribuído à variável local. | ||
| 4818 | |||
| 4819 | ```yuescript | ||
| 4820 | do | ||
| 4821 | import tostring | ||
| 4822 | import table.concat | ||
| 4823 | print concat ["a", tostring 1] | ||
| 4824 | ``` | ||
| 4825 | |||
| 4826 | <YueDisplay> | ||
| 4827 | |||
| 4828 | ```yue | ||
| 4829 | do | ||
| 4830 | import tostring | ||
| 4831 | import table.concat | ||
| 4832 | print concat ["a", tostring 1] | ||
| 4833 | ``` | ||
| 4834 | |||
| 4835 | </YueDisplay> | ||
| 4836 | |||
| 4837 | ### Importação automática de variável global | ||
| 4838 | |||
| 4839 | Você pode colocar `import global` no topo de um bloco para importar automaticamente todos os nomes que não foram explicitamente declarados ou atribuídos no escopo atual como globais. Essas importações implícitas são tratadas como consts locais que referenciam os globais correspondentes na posição da instrução. | ||
| 4840 | |||
| 4841 | Nomes que foram explicitamente declarados como globais no mesmo escopo não serão importados, então você ainda pode atribuir a eles. | ||
| 4842 | |||
| 4843 | ```yuescript | ||
| 4844 | do | ||
| 4845 | import global | ||
| 4846 | print "hello" | ||
| 4847 | math.random 3 | ||
| 4848 | -- print = nil -- erro: globais importados são const | ||
| 4849 | |||
| 4850 | do | ||
| 4851 | -- variável global explícita não será importada | ||
| 4852 | import global | ||
| 4853 | global FLAG | ||
| 4854 | print FLAG | ||
| 4855 | FLAG = 123 | ||
| 4856 | ``` | ||
| 4857 | |||
| 4858 | <YueDisplay> | ||
| 4859 | |||
| 4860 | ```yue | ||
| 4861 | do | ||
| 4862 | import global | ||
| 4863 | print "hello" | ||
| 4864 | math.random 3 | ||
| 4865 | -- print = nil -- erro: globais importados são const | ||
| 4866 | |||
| 4867 | do | ||
| 4868 | -- variável global explícita não será importada | ||
| 4869 | import global | ||
| 4870 | global FLAG | ||
| 4871 | print FLAG | ||
| 4872 | FLAG = 123 | ||
| 4873 | ``` | ||
| 4874 | |||
| 4875 | </YueDisplay> | ||
| 4876 | |||
| 4877 | ## Export | ||
| 4878 | |||
| 4879 | A instrução export oferece uma forma concisa de definir módulos. | ||
| 4880 | |||
| 4881 | ### Export nomeado | ||
| 4882 | |||
| 4883 | Export nomeado definirá uma variável local e também adicionará um campo na tabela exportada. | ||
| 4884 | |||
| 4885 | ```yuescript | ||
| 4886 | export a, b, c = 1, 2, 3 | ||
| 4887 | export cool = "cat" | ||
| 4888 | |||
| 4889 | export What = if this | ||
| 4890 | "abc" | ||
| 4891 | else | ||
| 4892 | "def" | ||
| 4893 | |||
| 4894 | export y = -> | ||
| 4895 | hallo = 3434 | ||
| 4896 | |||
| 4897 | export class Something | ||
| 4898 | umm: "cool" | ||
| 4899 | ``` | ||
| 4900 | |||
| 4901 | <YueDisplay> | ||
| 4902 | |||
| 4903 | ```yue | ||
| 4904 | export a, b, c = 1, 2, 3 | ||
| 4905 | export cool = "cat" | ||
| 4906 | |||
| 4907 | export What = if this | ||
| 4908 | "abc" | ||
| 4909 | else | ||
| 4910 | "def" | ||
| 4911 | |||
| 4912 | export y = -> | ||
| 4913 | hallo = 3434 | ||
| 4914 | |||
| 4915 | export class Something | ||
| 4916 | umm: "cool" | ||
| 4917 | ``` | ||
| 4918 | |||
| 4919 | </YueDisplay> | ||
| 4920 | |||
| 4921 | Fazendo export nomeado com desestruturação. | ||
| 4922 | |||
| 4923 | ```yuescript | ||
| 4924 | export :loadstring, to_lua: tolua = yue | ||
| 4925 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4926 | ``` | ||
| 4927 | |||
| 4928 | <YueDisplay> | ||
| 4929 | |||
| 4930 | ```yue | ||
| 4931 | export :loadstring, to_lua: tolua = yue | ||
| 4932 | export {itemA: {:fieldA = 'default'}} = tb | ||
| 4933 | ``` | ||
| 4934 | |||
| 4935 | </YueDisplay> | ||
| 4936 | |||
| 4937 | Exportar itens nomeados do módulo sem criar variáveis locais. | ||
| 4938 | |||
| 4939 | ```yuescript | ||
| 4940 | export.itemA = tb | ||
| 4941 | export.<index> = items | ||
| 4942 | export["a-b-c"] = 123 | ||
| 4943 | ``` | ||
| 4944 | |||
| 4945 | <YueDisplay> | ||
| 4946 | |||
| 4947 | ```yue | ||
| 4948 | export.itemA = tb | ||
| 4949 | export.<index> = items | ||
| 4950 | export["a-b-c"] = 123 | ||
| 4951 | ``` | ||
| 4952 | |||
| 4953 | </YueDisplay> | ||
| 4954 | |||
| 4955 | ### Export sem nome | ||
| 4956 | |||
| 4957 | Export sem nome adicionará o item alvo na parte array da tabela exportada. | ||
| 4958 | |||
| 4959 | ```yuescript | ||
| 4960 | d, e, f = 3, 2, 1 | ||
| 4961 | export d, e, f | ||
| 4962 | |||
| 4963 | export if this | ||
| 4964 | 123 | ||
| 4965 | else | ||
| 4966 | 456 | ||
| 4967 | |||
| 4968 | export with tmp | ||
| 4969 | j = 2000 | ||
| 4970 | ``` | ||
| 4971 | |||
| 4972 | <YueDisplay> | ||
| 4973 | |||
| 4974 | ```yue | ||
| 4975 | d, e, f = 3, 2, 1 | ||
| 4976 | export d, e, f | ||
| 4977 | |||
| 4978 | export if this | ||
| 4979 | 123 | ||
| 4980 | else | ||
| 4981 | 456 | ||
| 4982 | |||
| 4983 | export with tmp | ||
| 4984 | j = 2000 | ||
| 4985 | ``` | ||
| 4986 | |||
| 4987 | </YueDisplay> | ||
| 4988 | |||
| 4989 | ### Export padrão | ||
| 4990 | |||
| 4991 | Usar a palavra-chave **default** na instrução export para substituir a tabela exportada por qualquer coisa. | ||
| 4992 | |||
| 4993 | ```yuescript | ||
| 4994 | export default -> | ||
| 4995 | print "hello" | ||
| 4996 | 123 | ||
| 4997 | ``` | ||
| 4998 | |||
| 4999 | <YueDisplay> | ||
| 5000 | |||
| 5001 | ```yue | ||
| 5002 | export default -> | ||
| 5003 | print "hello" | ||
| 5004 | 123 | ||
| 5005 | ``` | ||
| 5006 | |||
| 5007 | </YueDisplay> | ||
| 5008 | |||
| 5009 | # Licença: MIT | ||
| 5010 | |||
| 5011 | Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\> | ||
| 5012 | |||
| 5013 | A permissão é concedida, gratuitamente, a qualquer pessoa que obtenha uma cópia | ||
| 5014 | deste software e dos arquivos de documentação associados (o "Software"), para negociar | ||
| 5015 | o Software sem restrições, incluindo, sem limitação, os direitos de usar, copiar, | ||
| 5016 | modificar, mesclar, publicar, distribuir, sublicenciar e/ou vender | ||
| 5017 | cópias do Software, e permitir que pessoas a quem o Software seja fornecido o façam, | ||
| 5018 | sujeito às seguintes condições: | ||
| 5019 | |||
| 5020 | O aviso de direitos autorais acima e este aviso de permissão devem ser incluídos em todas as | ||
| 5021 | cópias ou partes substanciais do Software. | ||
| 5022 | |||
| 5023 | O SOFTWARE É FORNECIDO "NO ESTADO EM QUE SE ENCONTRA", SEM GARANTIA DE QUALQUER TIPO, | ||
| 5024 | EXPRESSA OU IMPLÍCITA, INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, | ||
| 5025 | ADEQUAÇÃO A UM DETERMINADO FIM E NÃO VIOLAÇÃO. EM NENHUMA HIPÓTESE OS AUTORES OU | ||
| 5026 | DETENTORES DOS DIREITOS AUTORAIS SERÃO RESPONSÁVEIS POR QUAISQUER REIVINDICAÇÕES, | ||
| 5027 | DANOS OU OUTRAS RESPONSABILIDADES, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU OUTRA, | ||
| 5028 | DECORRENTES DE, FORA DE OU RELACIONADAS COM O SOFTWARE OU O USO OU OUTRAS NEGOCIAÇÕES | ||
| 5029 | NO SOFTWARE. | ||
| 5030 | |||
| 5031 | # A biblioteca YueScript | ||
| 5032 | |||
| 5033 | Acesse com `local yue = require("yue")` no Lua. | ||
| 5034 | |||
| 5035 | ## yue | ||
| 5036 | |||
| 5037 | **Descrição:** | ||
| 5038 | |||
| 5039 | A biblioteca da linguagem YueScript. | ||
| 5040 | |||
| 5041 | ### version | ||
| 5042 | |||
| 5043 | **Tipo:** Campo. | ||
| 5044 | |||
| 5045 | **Descrição:** | ||
| 5046 | |||
| 5047 | A versão do YueScript. | ||
| 5048 | |||
| 5049 | **Assinatura:** | ||
| 5050 | |||
| 5051 | ```lua | ||
| 5052 | version: string | ||
| 5053 | ``` | ||
| 5054 | |||
| 5055 | ### dirsep | ||
| 5056 | |||
| 5057 | **Tipo:** Campo. | ||
| 5058 | |||
| 5059 | **Descrição:** | ||
| 5060 | |||
| 5061 | O separador de arquivos da plataforma atual. | ||
| 5062 | |||
| 5063 | **Assinatura:** | ||
| 5064 | |||
| 5065 | ```lua | ||
| 5066 | dirsep: string | ||
| 5067 | ``` | ||
| 5068 | |||
| 5069 | ### yue_compiled | ||
| 5070 | |||
| 5071 | **Tipo:** Campo. | ||
| 5072 | |||
| 5073 | **Descrição:** | ||
| 5074 | |||
| 5075 | O cache de código de módulo compilado. | ||
| 5076 | |||
| 5077 | **Assinatura:** | ||
| 5078 | |||
| 5079 | ```lua | ||
| 5080 | yue_compiled: {string: string} | ||
| 5081 | ``` | ||
| 5082 | |||
| 5083 | ### to_lua | ||
| 5084 | |||
| 5085 | **Tipo:** Função. | ||
| 5086 | |||
| 5087 | **Descrição:** | ||
| 5088 | |||
| 5089 | A função de compilação do YueScript. Compila o código YueScript para código Lua. | ||
| 5090 | |||
| 5091 | **Assinatura:** | ||
| 5092 | |||
| 5093 | ```lua | ||
| 5094 | to_lua: function(code: string, config?: Config): | ||
| 5095 | --[[codes]] string | nil, | ||
| 5096 | --[[error]] string | nil, | ||
| 5097 | --[[globals]] {{string, integer, integer}} | nil | ||
| 5098 | ``` | ||
| 5099 | |||
| 5100 | **Parâmetros:** | ||
| 5101 | |||
| 5102 | | Parâmetro | Tipo | Descrição | | ||
| 5103 | | --------- | ------ | ----------------------------------- | | ||
| 5104 | | code | string | O código YueScript. | | ||
| 5105 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5106 | |||
| 5107 | **Retorna:** | ||
| 5108 | |||
| 5109 | | Tipo de Retorno | Descrição | | ||
| 5110 | | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5111 | | string \| nil | O código Lua compilado, ou nil se a compilação falhou. | | ||
| 5112 | | string \| nil | A mensagem de erro, ou nil se a compilação foi bem-sucedida. | | ||
| 5113 | | {{string, integer, integer}} \| nil | As variáveis globais que aparecem no código (com nome, linha e coluna), ou nil se a opção do compilador `lint_global` for false. | | ||
| 5114 | |||
| 5115 | ### file_exist | ||
| 5116 | |||
| 5117 | **Tipo:** Função. | ||
| 5118 | |||
| 5119 | **Descrição:** | ||
| 5120 | |||
| 5121 | Função de verificação de existência do arquivo fonte. Pode ser sobrescrita para personalizar o comportamento. | ||
| 5122 | |||
| 5123 | **Assinatura:** | ||
| 5124 | |||
| 5125 | ```lua | ||
| 5126 | file_exist: function(filename: string): boolean | ||
| 5127 | ``` | ||
| 5128 | |||
| 5129 | **Parâmetros:** | ||
| 5130 | |||
| 5131 | | Parâmetro | Tipo | Descrição | | ||
| 5132 | | --------- | ------ | ------------------ | | ||
| 5133 | | filename | string | O nome do arquivo. | | ||
| 5134 | |||
| 5135 | **Retorna:** | ||
| 5136 | |||
| 5137 | | Tipo de Retorno | Descrição | | ||
| 5138 | | --------------- | -------------------- | | ||
| 5139 | | boolean | Se o arquivo existe. | | ||
| 5140 | |||
| 5141 | ### read_file | ||
| 5142 | |||
| 5143 | **Tipo:** Função. | ||
| 5144 | |||
| 5145 | **Descrição:** | ||
| 5146 | |||
| 5147 | Função de leitura do arquivo fonte. Pode ser sobrescrita para personalizar o comportamento. | ||
| 5148 | |||
| 5149 | **Assinatura:** | ||
| 5150 | |||
| 5151 | ```lua | ||
| 5152 | read_file: function(filename: string): string | ||
| 5153 | ``` | ||
| 5154 | |||
| 5155 | **Parâmetros:** | ||
| 5156 | |||
| 5157 | | Parâmetro | Tipo | Descrição | | ||
| 5158 | | --------- | ------ | ------------------ | | ||
| 5159 | | filename | string | O nome do arquivo. | | ||
| 5160 | |||
| 5161 | **Retorna:** | ||
| 5162 | |||
| 5163 | | Tipo de Retorno | Descrição | | ||
| 5164 | | --------------- | ---------------------- | | ||
| 5165 | | string | O conteúdo do arquivo. | | ||
| 5166 | |||
| 5167 | ### insert_loader | ||
| 5168 | |||
| 5169 | **Tipo:** Função. | ||
| 5170 | |||
| 5171 | **Descrição:** | ||
| 5172 | |||
| 5173 | Insere o carregador YueScript nos carregadores de pacote (searchers). | ||
| 5174 | |||
| 5175 | **Assinatura:** | ||
| 5176 | |||
| 5177 | ```lua | ||
| 5178 | insert_loader: function(pos?: integer): boolean | ||
| 5179 | ``` | ||
| 5180 | |||
| 5181 | **Parâmetros:** | ||
| 5182 | |||
| 5183 | | Parâmetro | Tipo | Descrição | | ||
| 5184 | | --------- | ------- | ----------------------------------------------------------- | | ||
| 5185 | | pos | integer | [Opcional] A posição para inserir o carregador. Padrão é 3. | | ||
| 5186 | |||
| 5187 | **Retorna:** | ||
| 5188 | |||
| 5189 | | Tipo de Retorno | Descrição | | ||
| 5190 | | --------------- | -------------------------------------------------------------------------------------- | | ||
| 5191 | | boolean | Se o carregador foi inserido com sucesso. Falhará se o carregador já estiver inserido. | | ||
| 5192 | |||
| 5193 | ### remove_loader | ||
| 5194 | |||
| 5195 | **Tipo:** Função. | ||
| 5196 | |||
| 5197 | **Descrição:** | ||
| 5198 | |||
| 5199 | Remove o carregador YueScript dos carregadores de pacote (searchers). | ||
| 5200 | |||
| 5201 | **Assinatura:** | ||
| 5202 | |||
| 5203 | ```lua | ||
| 5204 | remove_loader: function(): boolean | ||
| 5205 | ``` | ||
| 5206 | |||
| 5207 | **Retorna:** | ||
| 5208 | |||
| 5209 | | Tipo de Retorno | Descrição | | ||
| 5210 | | --------------- | --------------------------------------------------------------------------------------- | | ||
| 5211 | | boolean | Se o carregador foi removido com sucesso. Falhará se o carregador não estiver inserido. | | ||
| 5212 | |||
| 5213 | ### loadstring | ||
| 5214 | |||
| 5215 | **Tipo:** Função. | ||
| 5216 | |||
| 5217 | **Descrição:** | ||
| 5218 | |||
| 5219 | Carrega código YueScript de uma string em uma função. | ||
| 5220 | |||
| 5221 | **Assinatura:** | ||
| 5222 | |||
| 5223 | ```lua | ||
| 5224 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | ||
| 5225 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5226 | --[[error]] string | nil | ||
| 5227 | ``` | ||
| 5228 | |||
| 5229 | **Parâmetros:** | ||
| 5230 | |||
| 5231 | | Parâmetro | Tipo | Descrição | | ||
| 5232 | | --------- | ------ | ----------------------------------- | | ||
| 5233 | | input | string | O código YueScript. | | ||
| 5234 | | chunkname | string | O nome do chunk de código. | | ||
| 5235 | | env | table | A tabela de ambiente. | | ||
| 5236 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5237 | |||
| 5238 | **Retorna:** | ||
| 5239 | |||
| 5240 | | Tipo de Retorno | Descrição | | ||
| 5241 | | --------------- | -------------------------------------------------------------- | | ||
| 5242 | | function \| nil | A função carregada, ou nil se o carregamento falhou. | | ||
| 5243 | | string \| nil | A mensagem de erro, ou nil se o carregamento foi bem-sucedido. | | ||
| 5244 | |||
| 5245 | ### loadstring | ||
| 5246 | |||
| 5247 | **Tipo:** Função. | ||
| 5248 | |||
| 5249 | **Descrição:** | ||
| 5250 | |||
| 5251 | Carrega código YueScript de uma string em uma função. | ||
| 5252 | |||
| 5253 | **Assinatura:** | ||
| 5254 | |||
| 5255 | ```lua | ||
| 5256 | loadstring: function(input: string, chunkname: string, config?: Config): | ||
| 5257 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5258 | --[[error]] string | nil | ||
| 5259 | ``` | ||
| 5260 | |||
| 5261 | **Parâmetros:** | ||
| 5262 | |||
| 5263 | | Parâmetro | Tipo | Descrição | | ||
| 5264 | | --------- | ------ | ----------------------------------- | | ||
| 5265 | | input | string | O código YueScript. | | ||
| 5266 | | chunkname | string | O nome do chunk de código. | | ||
| 5267 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5268 | |||
| 5269 | **Retorna:** | ||
| 5270 | |||
| 5271 | | Tipo de Retorno | Descrição | | ||
| 5272 | | --------------- | -------------------------------------------------------------- | | ||
| 5273 | | function \| nil | A função carregada, ou nil se o carregamento falhou. | | ||
| 5274 | | string \| nil | A mensagem de erro, ou nil se o carregamento foi bem-sucedido. | | ||
| 5275 | |||
| 5276 | ### loadstring | ||
| 5277 | |||
| 5278 | **Tipo:** Função. | ||
| 5279 | |||
| 5280 | **Descrição:** | ||
| 5281 | |||
| 5282 | Carrega código YueScript de uma string em uma função. | ||
| 5283 | |||
| 5284 | **Assinatura:** | ||
| 5285 | |||
| 5286 | ```lua | ||
| 5287 | loadstring: function(input: string, config?: Config): | ||
| 5288 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5289 | --[[error]] string | nil | ||
| 5290 | ``` | ||
| 5291 | |||
| 5292 | **Parâmetros:** | ||
| 5293 | |||
| 5294 | | Parâmetro | Tipo | Descrição | | ||
| 5295 | | --------- | ------ | ----------------------------------- | | ||
| 5296 | | input | string | O código YueScript. | | ||
| 5297 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5298 | |||
| 5299 | **Retorna:** | ||
| 5300 | |||
| 5301 | | Tipo de Retorno | Descrição | | ||
| 5302 | | --------------- | -------------------------------------------------------------- | | ||
| 5303 | | function \| nil | A função carregada, ou nil se o carregamento falhou. | | ||
| 5304 | | string \| nil | A mensagem de erro, ou nil se o carregamento foi bem-sucedido. | | ||
| 5305 | |||
| 5306 | ### loadfile | ||
| 5307 | |||
| 5308 | **Tipo:** Função. | ||
| 5309 | |||
| 5310 | **Descrição:** | ||
| 5311 | |||
| 5312 | Carrega código YueScript de um arquivo em uma função. | ||
| 5313 | |||
| 5314 | **Assinatura:** | ||
| 5315 | |||
| 5316 | ```lua | ||
| 5317 | loadfile: function(filename: string, env: table, config?: Config): | ||
| 5318 | nil | function(...: any): (any...), | ||
| 5319 | string | nil | ||
| 5320 | ``` | ||
| 5321 | |||
| 5322 | **Parâmetros:** | ||
| 5323 | |||
| 5324 | | Parâmetro | Tipo | Descrição | | ||
| 5325 | | --------- | ------ | ----------------------------------- | | ||
| 5326 | | filename | string | O nome do arquivo. | | ||
| 5327 | | env | table | A tabela de ambiente. | | ||
| 5328 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5329 | |||
| 5330 | **Retorna:** | ||
| 5331 | |||
| 5332 | | Tipo de Retorno | Descrição | | ||
| 5333 | | --------------- | -------------------------------------------------------------- | | ||
| 5334 | | function \| nil | A função carregada, ou nil se o carregamento falhou. | | ||
| 5335 | | string \| nil | A mensagem de erro, ou nil se o carregamento foi bem-sucedido. | | ||
| 5336 | |||
| 5337 | ### loadfile | ||
| 5338 | |||
| 5339 | **Tipo:** Função. | ||
| 5340 | |||
| 5341 | **Descrição:** | ||
| 5342 | |||
| 5343 | Carrega código YueScript de um arquivo em uma função. | ||
| 5344 | |||
| 5345 | **Assinatura:** | ||
| 5346 | |||
| 5347 | ```lua | ||
| 5348 | loadfile: function(filename: string, config?: Config): | ||
| 5349 | nil | function(...: any): (any...), | ||
| 5350 | string | nil | ||
| 5351 | ``` | ||
| 5352 | |||
| 5353 | **Parâmetros:** | ||
| 5354 | |||
| 5355 | | Parâmetro | Tipo | Descrição | | ||
| 5356 | | --------- | ------ | ----------------------------------- | | ||
| 5357 | | filename | string | O nome do arquivo. | | ||
| 5358 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5359 | |||
| 5360 | **Retorna:** | ||
| 5361 | |||
| 5362 | | Tipo de Retorno | Descrição | | ||
| 5363 | | --------------- | -------------------------------------------------------------- | | ||
| 5364 | | function \| nil | A função carregada, ou nil se o carregamento falhou. | | ||
| 5365 | | string \| nil | A mensagem de erro, ou nil se o carregamento foi bem-sucedido. | | ||
| 5366 | |||
| 5367 | ### dofile | ||
| 5368 | |||
| 5369 | **Tipo:** Função. | ||
| 5370 | |||
| 5371 | **Descrição:** | ||
| 5372 | |||
| 5373 | Carrega código YueScript de um arquivo em uma função e o executa. | ||
| 5374 | |||
| 5375 | **Assinatura:** | ||
| 5376 | |||
| 5377 | ```lua | ||
| 5378 | dofile: function(filename: string, env: table, config?: Config): any... | ||
| 5379 | ``` | ||
| 5380 | |||
| 5381 | **Parâmetros:** | ||
| 5382 | |||
| 5383 | | Parâmetro | Tipo | Descrição | | ||
| 5384 | | --------- | ------ | ----------------------------------- | | ||
| 5385 | | filename | string | O nome do arquivo. | | ||
| 5386 | | env | table | A tabela de ambiente. | | ||
| 5387 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5388 | |||
| 5389 | **Retorna:** | ||
| 5390 | |||
| 5391 | | Tipo de Retorno | Descrição | | ||
| 5392 | | --------------- | ------------------------------------------ | | ||
| 5393 | | any... | Os valores de retorno da função carregada. | | ||
| 5394 | |||
| 5395 | ### dofile | ||
| 5396 | |||
| 5397 | **Tipo:** Função. | ||
| 5398 | |||
| 5399 | **Descrição:** | ||
| 5400 | |||
| 5401 | Carrega código YueScript de um arquivo em uma função e o executa. | ||
| 5402 | |||
| 5403 | **Assinatura:** | ||
| 5404 | |||
| 5405 | ```lua | ||
| 5406 | dofile: function(filename: string, config?: Config): any... | ||
| 5407 | ``` | ||
| 5408 | |||
| 5409 | **Parâmetros:** | ||
| 5410 | |||
| 5411 | | Parâmetro | Tipo | Descrição | | ||
| 5412 | | --------- | ------ | ----------------------------------- | | ||
| 5413 | | filename | string | O nome do arquivo. | | ||
| 5414 | | config | Config | [Opcional] As opções do compilador. | | ||
| 5415 | |||
| 5416 | **Retorna:** | ||
| 5417 | |||
| 5418 | | Tipo de Retorno | Descrição | | ||
| 5419 | | --------------- | ------------------------------------------ | | ||
| 5420 | | any... | Os valores de retorno da função carregada. | | ||
| 5421 | |||
| 5422 | ### find_modulepath | ||
| 5423 | |||
| 5424 | **Tipo:** Função. | ||
| 5425 | |||
| 5426 | **Descrição:** | ||
| 5427 | |||
| 5428 | Resolve o nome do módulo YueScript para o caminho do arquivo. | ||
| 5429 | |||
| 5430 | **Assinatura:** | ||
| 5431 | |||
| 5432 | ```lua | ||
| 5433 | find_modulepath: function(name: string): string | ||
| 5434 | ``` | ||
| 5435 | |||
| 5436 | **Parâmetros:** | ||
| 5437 | |||
| 5438 | | Parâmetro | Tipo | Descrição | | ||
| 5439 | | --------- | ------ | ----------------- | | ||
| 5440 | | name | string | O nome do módulo. | | ||
| 5441 | |||
| 5442 | **Retorna:** | ||
| 5443 | |||
| 5444 | | Tipo de Retorno | Descrição | | ||
| 5445 | | --------------- | --------------------- | | ||
| 5446 | | string | O caminho do arquivo. | | ||
| 5447 | |||
| 5448 | ### pcall | ||
| 5449 | |||
| 5450 | **Tipo:** Função. | ||
| 5451 | |||
| 5452 | **Descrição:** | ||
| 5453 | |||
| 5454 | Chama uma função em modo protegido. | ||
| 5455 | Captura quaisquer erros e retorna um código de status e resultados ou objeto de erro. | ||
| 5456 | Reescreve o número da linha do erro para o número da linha original no código YueScript quando ocorrem erros. | ||
| 5457 | |||
| 5458 | **Assinatura:** | ||
| 5459 | |||
| 5460 | ```lua | ||
| 5461 | pcall: function(f: function, ...: any): boolean, any... | ||
| 5462 | ``` | ||
| 5463 | |||
| 5464 | **Parâmetros:** | ||
| 5465 | |||
| 5466 | | Parâmetro | Tipo | Descrição | | ||
| 5467 | | --------- | -------- | ---------------------------------- | | ||
| 5468 | | f | function | A função a chamar. | | ||
| 5469 | | ... | any | Argumentos a passar para a função. | | ||
| 5470 | |||
| 5471 | **Retorna:** | ||
| 5472 | |||
| 5473 | | Tipo de Retorno | Descrição | | ||
| 5474 | | --------------- | ---------------------------------------------------------- | | ||
| 5475 | | boolean, ... | Código de status e resultados da função ou objeto de erro. | | ||
| 5476 | |||
| 5477 | ### require | ||
| 5478 | |||
| 5479 | **Tipo:** Função. | ||
| 5480 | |||
| 5481 | **Descrição:** | ||
| 5482 | |||
| 5483 | Carrega um módulo dado. Pode ser um módulo Lua ou um módulo YueScript. | ||
| 5484 | Reescreve o número da linha do erro para o número da linha original no código YueScript se o módulo for um módulo YueScript e o carregamento falhar. | ||
| 5485 | |||
| 5486 | **Assinatura:** | ||
| 5487 | |||
| 5488 | ```lua | ||
| 5489 | require: function(name: string): any... | ||
| 5490 | ``` | ||
| 5491 | |||
| 5492 | **Parâmetros:** | ||
| 5493 | |||
| 5494 | | Parâmetro | Tipo | Descrição | | ||
| 5495 | | --------- | ------ | ---------------------------- | | ||
| 5496 | | modname | string | O nome do módulo a carregar. | | ||
| 5497 | |||
| 5498 | **Retorna:** | ||
| 5499 | |||
| 5500 | | Tipo de Retorno | Descrição | | ||
| 5501 | | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5502 | | any | O valor armazenado em package.loaded[modname] se o módulo já estiver carregado. Caso contrário, tenta encontrar um carregador e retorna o valor final de package.loaded[modname] e os dados do carregador como segundo resultado. | | ||
| 5503 | |||
| 5504 | ### p | ||
| 5505 | |||
| 5506 | **Tipo:** Função. | ||
| 5507 | |||
| 5508 | **Descrição:** | ||
| 5509 | |||
| 5510 | Inspeciona as estruturas dos valores passados e imprime representações em string. | ||
| 5511 | |||
| 5512 | **Assinatura:** | ||
| 5513 | |||
| 5514 | ```lua | ||
| 5515 | p: function(...: any) | ||
| 5516 | ``` | ||
| 5517 | |||
| 5518 | **Parâmetros:** | ||
| 5519 | |||
| 5520 | | Parâmetro | Tipo | Descrição | | ||
| 5521 | | --------- | ---- | ------------------------- | | ||
| 5522 | | ... | any | Os valores a inspecionar. | | ||
| 5523 | |||
| 5524 | ### options | ||
| 5525 | |||
| 5526 | **Tipo:** Campo. | ||
| 5527 | |||
| 5528 | **Descrição:** | ||
| 5529 | |||
| 5530 | As opções atuais do compilador. | ||
| 5531 | |||
| 5532 | **Assinatura:** | ||
| 5533 | |||
| 5534 | ```lua | ||
| 5535 | options: Config.Options | ||
| 5536 | ``` | ||
| 5537 | |||
| 5538 | ### traceback | ||
| 5539 | |||
| 5540 | **Tipo:** Função. | ||
| 5541 | |||
| 5542 | **Descrição:** | ||
| 5543 | |||
| 5544 | A função traceback que reescreve os números das linhas do stack trace para os números das linhas originais no código YueScript. | ||
| 5545 | |||
| 5546 | **Assinatura:** | ||
| 5547 | |||
| 5548 | ```lua | ||
| 5549 | traceback: function(message: string): string | ||
| 5550 | ``` | ||
| 5551 | |||
| 5552 | **Parâmetros:** | ||
| 5553 | |||
| 5554 | | Parâmetro | Tipo | Descrição | | ||
| 5555 | | --------- | ------ | ------------------------ | | ||
| 5556 | | message | string | A mensagem de traceback. | | ||
| 5557 | |||
| 5558 | **Retorna:** | ||
| 5559 | |||
| 5560 | | Tipo de Retorno | Descrição | | ||
| 5561 | | --------------- | ---------------------------------- | | ||
| 5562 | | string | A mensagem de traceback reescrita. | | ||
| 5563 | |||
| 5564 | ### is_ast | ||
| 5565 | |||
| 5566 | **Tipo:** Função. | ||
| 5567 | |||
| 5568 | **Descrição:** | ||
| 5569 | |||
| 5570 | Verifica se o código corresponde ao AST especificado. | ||
| 5571 | |||
| 5572 | **Assinatura:** | ||
| 5573 | |||
| 5574 | ```lua | ||
| 5575 | is_ast: function(astName: string, code: string): boolean | ||
| 5576 | ``` | ||
| 5577 | |||
| 5578 | **Parâmetros:** | ||
| 5579 | |||
| 5580 | | Parâmetro | Tipo | Descrição | | ||
| 5581 | | --------- | ------ | -------------- | | ||
| 5582 | | astName | string | O nome do AST. | | ||
| 5583 | | code | string | O código. | | ||
| 5584 | |||
| 5585 | **Retorna:** | ||
| 5586 | |||
| 5587 | | Tipo de Retorno | Descrição | | ||
| 5588 | | --------------- | ------------------------------- | | ||
| 5589 | | boolean | Se o código corresponde ao AST. | | ||
| 5590 | |||
| 5591 | ### AST | ||
| 5592 | |||
| 5593 | **Tipo:** Campo. | ||
| 5594 | |||
| 5595 | **Descrição:** | ||
| 5596 | |||
| 5597 | A definição do tipo AST com nome, linha, coluna e subnós. | ||
| 5598 | |||
| 5599 | **Assinatura:** | ||
| 5600 | |||
| 5601 | ```lua | ||
| 5602 | type AST = {string, integer, integer, any} | ||
| 5603 | ``` | ||
| 5604 | |||
| 5605 | ### to_ast | ||
| 5606 | |||
| 5607 | **Tipo:** Função. | ||
| 5608 | |||
| 5609 | **Descrição:** | ||
| 5610 | |||
| 5611 | Converte o código para o AST. | ||
| 5612 | |||
| 5613 | **Assinatura:** | ||
| 5614 | |||
| 5615 | ```lua | ||
| 5616 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): | ||
| 5617 | --[[AST]] AST | nil, | ||
| 5618 | --[[error]] nil | string | ||
| 5619 | ``` | ||
| 5620 | |||
| 5621 | **Parâmetros:** | ||
| 5622 | |||
| 5623 | | Parâmetro | Tipo | Descrição | | ||
| 5624 | | -------------- | ------- | ------------------------------------------------------------------------------------------------------ | | ||
| 5625 | | code | string | O código. | | ||
| 5626 | | flattenLevel | integer | [Opcional] O nível de achatamento. Nível mais alto significa mais achatamento. Padrão é 0. Máximo é 2. | | ||
| 5627 | | astName | string | [Opcional] O nome do AST. Padrão é "File". | | ||
| 5628 | | reserveComment | boolean | [Opcional] Se deve preservar os comentários originais. Padrão é false. | | ||
| 5629 | |||
| 5630 | **Retorna:** | ||
| 5631 | |||
| 5632 | | Tipo de Retorno | Descrição | | ||
| 5633 | | --------------- | ----------------------------------------------------------- | | ||
| 5634 | | AST \| nil | O AST, ou nil se a conversão falhou. | | ||
| 5635 | | string \| nil | A mensagem de erro, ou nil se a conversão foi bem-sucedida. | | ||
| 5636 | |||
| 5637 | ### format | ||
| 5638 | |||
| 5639 | **Tipo:** Função. | ||
| 5640 | |||
| 5641 | **Descrição:** | ||
| 5642 | |||
| 5643 | Formata o código YueScript. | ||
| 5644 | |||
| 5645 | **Assinatura:** | ||
| 5646 | |||
| 5647 | ```lua | ||
| 5648 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 5649 | ``` | ||
| 5650 | |||
| 5651 | **Parâmetros:** | ||
| 5652 | |||
| 5653 | | Parâmetro | Tipo | Descrição | | ||
| 5654 | | -------------- | ------- | --------------------------------------------------------------------- | | ||
| 5655 | | code | string | O código. | | ||
| 5656 | | tabSize | integer | [Opcional] O tamanho da tabulação. Padrão é 4. | | ||
| 5657 | | reserveComment | boolean | [Opcional] Se deve preservar os comentários originais. Padrão é true. | | ||
| 5658 | |||
| 5659 | **Retorna:** | ||
| 5660 | |||
| 5661 | | Tipo de Retorno | Descrição | | ||
| 5662 | | --------------- | ------------------- | | ||
| 5663 | | string | O código formatado. | | ||
| 5664 | |||
| 5665 | ### \_\_call | ||
| 5666 | |||
| 5667 | **Tipo:** Metamétodo. | ||
| 5668 | |||
| 5669 | **Descrição:** | ||
| 5670 | |||
| 5671 | Requer o módulo YueScript. | ||
| 5672 | Reescreve o número da linha do erro para o número da linha original no código YueScript quando o carregamento falha. | ||
| 5673 | |||
| 5674 | **Assinatura:** | ||
| 5675 | |||
| 5676 | ```lua | ||
| 5677 | metamethod __call: function(self: yue, module: string): any... | ||
| 5678 | ``` | ||
| 5679 | |||
| 5680 | **Parâmetros:** | ||
| 5681 | |||
| 5682 | | Parâmetro | Tipo | Descrição | | ||
| 5683 | | --------- | ------ | ----------------- | | ||
| 5684 | | module | string | O nome do módulo. | | ||
| 5685 | |||
| 5686 | **Retorna:** | ||
| 5687 | |||
| 5688 | | Tipo de Retorno | Descrição | | ||
| 5689 | | --------------- | ------------------ | | ||
| 5690 | | any | O valor do módulo. | | ||
| 5691 | |||
| 5692 | ## Config | ||
| 5693 | |||
| 5694 | **Descrição:** | ||
| 5695 | |||
| 5696 | As opções de compilação do compilador. | ||
| 5697 | |||
| 5698 | ### lint_global | ||
| 5699 | |||
| 5700 | **Tipo:** Campo. | ||
| 5701 | |||
| 5702 | **Descrição:** | ||
| 5703 | |||
| 5704 | Se o compilador deve coletar as variáveis globais que aparecem no código. | ||
| 5705 | |||
| 5706 | **Assinatura:** | ||
| 5707 | |||
| 5708 | ```lua | ||
| 5709 | lint_global: boolean | ||
| 5710 | ``` | ||
| 5711 | |||
| 5712 | ### implicit_return_root | ||
| 5713 | |||
| 5714 | **Tipo:** Campo. | ||
| 5715 | |||
| 5716 | **Descrição:** | ||
| 5717 | |||
| 5718 | Se o compilador deve fazer retorno implícito para o bloco de código raiz. | ||
| 5719 | |||
| 5720 | **Assinatura:** | ||
| 5721 | |||
| 5722 | ```lua | ||
| 5723 | implicit_return_root: boolean | ||
| 5724 | ``` | ||
| 5725 | |||
| 5726 | ### reserve_line_number | ||
| 5727 | |||
| 5728 | **Tipo:** Campo. | ||
| 5729 | |||
| 5730 | **Descrição:** | ||
| 5731 | |||
| 5732 | Se o compilador deve preservar o número da linha original no código compilado. | ||
| 5733 | |||
| 5734 | **Assinatura:** | ||
| 5735 | |||
| 5736 | ```lua | ||
| 5737 | reserve_line_number: boolean | ||
| 5738 | ``` | ||
| 5739 | |||
| 5740 | ### reserve_comment | ||
| 5741 | |||
| 5742 | **Tipo:** Campo. | ||
| 5743 | |||
| 5744 | **Descrição:** | ||
| 5745 | |||
| 5746 | Se o compilador deve preservar os comentários originais no código compilado. | ||
| 5747 | |||
| 5748 | **Assinatura:** | ||
| 5749 | |||
| 5750 | ```lua | ||
| 5751 | reserve_comment: boolean | ||
| 5752 | ``` | ||
| 5753 | |||
| 5754 | ### space_over_tab | ||
| 5755 | |||
| 5756 | **Tipo:** Campo. | ||
| 5757 | |||
| 5758 | **Descrição:** | ||
| 5759 | |||
| 5760 | Se o compilador deve usar o caractere de espaço em vez do caractere de tabulação no código compilado. | ||
| 5761 | |||
| 5762 | **Assinatura:** | ||
| 5763 | |||
| 5764 | ```lua | ||
| 5765 | space_over_tab: boolean | ||
| 5766 | ``` | ||
| 5767 | |||
| 5768 | ### same_module | ||
| 5769 | |||
| 5770 | **Tipo:** Campo. | ||
| 5771 | |||
| 5772 | **Descrição:** | ||
| 5773 | |||
| 5774 | Se o compilador deve tratar o código a ser compilado como o mesmo módulo que está sendo compilado atualmente. Apenas para uso interno. | ||
| 5775 | |||
| 5776 | **Assinatura:** | ||
| 5777 | |||
| 5778 | ```lua | ||
| 5779 | same_module: boolean | ||
| 5780 | ``` | ||
| 5781 | |||
| 5782 | ### line_offset | ||
| 5783 | |||
| 5784 | **Tipo:** Campo. | ||
| 5785 | |||
| 5786 | **Descrição:** | ||
| 5787 | |||
| 5788 | Se a mensagem de erro do compilador deve incluir o deslocamento do número da linha. Apenas para uso interno. | ||
| 5789 | |||
| 5790 | **Assinatura:** | ||
| 5791 | |||
| 5792 | ```lua | ||
| 5793 | line_offset: integer | ||
| 5794 | ``` | ||
| 5795 | |||
| 5796 | ### yue.Config.LuaTarget | ||
| 5797 | |||
| 5798 | **Tipo:** Enumeração. | ||
| 5799 | |||
| 5800 | **Descrição:** | ||
| 5801 | |||
| 5802 | A enumeração da versão alvo do Lua. | ||
| 5803 | |||
| 5804 | **Assinatura:** | ||
| 5805 | |||
| 5806 | ```lua | ||
| 5807 | enum LuaTarget | ||
| 5808 | "5.1" | ||
| 5809 | "5.2" | ||
| 5810 | "5.3" | ||
| 5811 | "5.4" | ||
| 5812 | "5.5" | ||
| 5813 | end | ||
| 5814 | ``` | ||
| 5815 | |||
| 5816 | ### options | ||
| 5817 | |||
| 5818 | **Tipo:** Campo. | ||
| 5819 | |||
| 5820 | **Descrição:** | ||
| 5821 | |||
| 5822 | As opções extras a serem passadas para a função de compilação. | ||
| 5823 | |||
| 5824 | **Assinatura:** | ||
| 5825 | |||
| 5826 | ```lua | ||
| 5827 | options: Options | ||
| 5828 | ``` | ||
| 5829 | |||
| 5830 | ## Options | ||
| 5831 | |||
| 5832 | **Descrição:** | ||
| 5833 | |||
| 5834 | A definição das opções extras do compilador. | ||
| 5835 | |||
| 5836 | ### target | ||
| 5837 | |||
| 5838 | **Tipo:** Campo. | ||
| 5839 | |||
| 5840 | **Descrição:** | ||
| 5841 | |||
| 5842 | A versão alvo do Lua para a compilação. | ||
| 5843 | |||
| 5844 | **Assinatura:** | ||
| 5845 | |||
| 5846 | ```lua | ||
| 5847 | target: LuaTarget | ||
| 5848 | ``` | ||
| 5849 | |||
| 5850 | ### path | ||
| 5851 | |||
| 5852 | **Tipo:** Campo. | ||
| 5853 | |||
| 5854 | **Descrição:** | ||
| 5855 | |||
| 5856 | O caminho de busca de módulo extra. | ||
| 5857 | |||
| 5858 | **Assinatura:** | ||
| 5859 | |||
| 5860 | ```lua | ||
| 5861 | path: string | ||
| 5862 | ``` | ||
| 5863 | |||
| 5864 | ### dump_locals | ||
| 5865 | |||
| 5866 | **Tipo:** Campo. | ||
| 5867 | |||
| 5868 | **Descrição:** | ||
| 5869 | |||
| 5870 | Se deve incluir as variáveis locais na mensagem de erro do traceback. Padrão é false. | ||
| 5871 | |||
| 5872 | **Assinatura:** | ||
| 5873 | |||
| 5874 | ```lua | ||
| 5875 | dump_locals: boolean | ||
| 5876 | ``` | ||
| 5877 | |||
| 5878 | ### simplified | ||
| 5879 | |||
| 5880 | **Tipo:** Campo. | ||
| 5881 | |||
| 5882 | **Descrição:** | ||
| 5883 | |||
| 5884 | Se deve simplificar a mensagem de erro. Padrão é true. | ||
| 5885 | |||
| 5886 | **Assinatura:** | ||
| 5887 | |||
| 5888 | ```lua | ||
| 5889 | simplified: boolean | ||
| 5890 | ``` | ||
diff --git a/doc/yue-zh.md b/doc/yue-zh.md new file mode 100644 index 0000000..7454eab --- /dev/null +++ b/doc/yue-zh.md | |||
| @@ -0,0 +1,5866 @@ | |||
| 1 | --- | ||
| 2 | title: 参考手册 | ||
| 3 | --- | ||
| 4 | |||
| 5 | # 月之脚本文档 | ||
| 6 | |||
| 7 | <img src="/image/yuescript.svg" width="250px" height="250px" alt="logo" style="padding-top: 3em;padding-bottom: 2em;"/> | ||
| 8 | |||
| 9 | 欢迎来到 <b>月之脚本(YueScript)</b> 官方文档!<br/> | ||
| 10 | 这里收录了语言特性、用法、参考示例和资源。<br/> | ||
| 11 | 请选择左侧的章节索引或目录,开启你的月之脚本之旅 ☽ | ||
| 12 | |||
| 13 | # do 语句 | ||
| 14 | |||
| 15 |   当用作语句时,do 语句的作用就像在 Lua 中差不多。 | ||
| 16 | |||
| 17 | ```yuescript | ||
| 18 | do | ||
| 19 | var = "hello" | ||
| 20 | print var | ||
| 21 | print var -- 这里是nil | ||
| 22 | ``` | ||
| 23 | |||
| 24 | <YueDisplay> | ||
| 25 | |||
| 26 | ```yue | ||
| 27 | do | ||
| 28 | var = "hello" | ||
| 29 | print var | ||
| 30 | print var -- 这里是nil | ||
| 31 | ``` | ||
| 32 | |||
| 33 | </YueDisplay> | ||
| 34 | |||
| 35 |   月之脚本的 **do** 也可以用作表达式。允许你将多行代码的处理合并为一个表达式,并将 do 语句代码块的最后一个语句作为表达式返回的结果。`do` 表达式支持通过 `break` 打断执行流并提前返回多个值。 | ||
| 36 | |||
| 37 | ```yuescript | ||
| 38 | status, value = do | ||
| 39 | n = 12 | ||
| 40 | if n > 10 | ||
| 41 | break "large", n | ||
| 42 | break "small", n | ||
| 43 | ``` | ||
| 44 | |||
| 45 | <YueDisplay> | ||
| 46 | |||
| 47 | ```yue | ||
| 48 | status, value = do | ||
| 49 | n = 12 | ||
| 50 | if n > 10 | ||
| 51 | break "large", n | ||
| 52 | break "small", n | ||
| 53 | ``` | ||
| 54 | |||
| 55 | </YueDisplay> | ||
| 56 | |||
| 57 | ```yuescript | ||
| 58 | counter = do | ||
| 59 | i = 0 | ||
| 60 | -> | ||
| 61 | i += 1 | ||
| 62 | i | ||
| 63 | |||
| 64 | print counter! | ||
| 65 | print counter! | ||
| 66 | ``` | ||
| 67 | |||
| 68 | <YueDisplay> | ||
| 69 | |||
| 70 | ```yue | ||
| 71 | counter = do | ||
| 72 | i = 0 | ||
| 73 | -> | ||
| 74 | i += 1 | ||
| 75 | i | ||
| 76 | |||
| 77 | print counter! | ||
| 78 | print counter! | ||
| 79 | ``` | ||
| 80 | |||
| 81 | </YueDisplay> | ||
| 82 | |||
| 83 | ```yuescript | ||
| 84 | tbl = { | ||
| 85 | key: do | ||
| 86 | print "分配键值!" | ||
| 87 | 1234 | ||
| 88 | } | ||
| 89 | ``` | ||
| 90 | |||
| 91 | <YueDisplay> | ||
| 92 | |||
| 93 | ```yue | ||
| 94 | tbl = { | ||
| 95 | key: do | ||
| 96 | print "分配键值!" | ||
| 97 | 1234 | ||
| 98 | } | ||
| 99 | ``` | ||
| 100 | |||
| 101 | </YueDisplay> | ||
| 102 | |||
| 103 | # 代码行修饰 | ||
| 104 | |||
| 105 |   为了方便编写代码,循环语句和 if 语句可以应用于单行代码语句的末尾: | ||
| 106 | |||
| 107 | ```yuescript | ||
| 108 | print "你好,世界" if name == "Rob" | ||
| 109 | ``` | ||
| 110 | |||
| 111 | <YueDisplay> | ||
| 112 | |||
| 113 | ```yue | ||
| 114 | print "你好,世界" if name == "Rob" | ||
| 115 | ``` | ||
| 116 | |||
| 117 | </YueDisplay> | ||
| 118 | |||
| 119 |   修饰 for 循环的示例: | ||
| 120 | |||
| 121 | ```yuescript | ||
| 122 | print "项目: ", item for item in *items | ||
| 123 | ``` | ||
| 124 | |||
| 125 | <YueDisplay> | ||
| 126 | |||
| 127 | ```yue | ||
| 128 | print "项目: ", item for item in *items | ||
| 129 | ``` | ||
| 130 | |||
| 131 | </YueDisplay> | ||
| 132 | |||
| 133 |   修饰 while 循环的示例: | ||
| 134 | |||
| 135 | ```yuescript | ||
| 136 | game\update! while game\isRunning! | ||
| 137 | |||
| 138 | reader\parse_line! until reader\eof! | ||
| 139 | ``` | ||
| 140 | |||
| 141 | <YueDisplay> | ||
| 142 | |||
| 143 | ```yue | ||
| 144 | game\update! while game\isRunning! | ||
| 145 | |||
| 146 | reader\parse_line! until reader\eof! | ||
| 147 | ``` | ||
| 148 | |||
| 149 | </YueDisplay> | ||
| 150 | |||
| 151 | # 宏 | ||
| 152 | |||
| 153 | ## 常见用法 | ||
| 154 | |||
| 155 |   宏函数用于在编译时执行一段代码来生成新的代码,并将生成的代码插入到最终编译结果中。 | ||
| 156 | |||
| 157 | ```yuescript | ||
| 158 | macro PI2 = -> math.pi * 2 | ||
| 159 | area = $PI2 * 5 | ||
| 160 | |||
| 161 | macro HELLO = -> "'你好 世界'" | ||
| 162 | print $HELLO | ||
| 163 | |||
| 164 | macro config = (debugging) -> | ||
| 165 | global debugMode = debugging == "true" | ||
| 166 | "" | ||
| 167 | |||
| 168 | macro asserts = (cond) -> | ||
| 169 | debugMode and "assert #{cond}" or "" | ||
| 170 | |||
| 171 | macro assert = (cond) -> | ||
| 172 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 173 | |||
| 174 | $config true | ||
| 175 | $asserts item ~= nil | ||
| 176 | |||
| 177 | $config false | ||
| 178 | value = $assert item | ||
| 179 | |||
| 180 | -- 宏函数参数传递的表达式会被转换为字符串 | ||
| 181 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 182 | if $and f1!, f2!, f3! | ||
| 183 | print "OK" | ||
| 184 | ``` | ||
| 185 | |||
| 186 | <YueDisplay> | ||
| 187 | |||
| 188 | ```yue | ||
| 189 | macro PI2 = -> math.pi * 2 | ||
| 190 | area = $PI2 * 5 | ||
| 191 | |||
| 192 | macro HELLO = -> "'你好 世界'" | ||
| 193 | print $HELLO | ||
| 194 | |||
| 195 | macro config = (debugging) -> | ||
| 196 | global debugMode = debugging == "true" | ||
| 197 | "" | ||
| 198 | |||
| 199 | macro asserts = (cond) -> | ||
| 200 | debugMode and "assert #{cond}" or "" | ||
| 201 | |||
| 202 | macro assert = (cond) -> | ||
| 203 | debugMode and "assert #{cond}" or "#{cond}" | ||
| 204 | |||
| 205 | $config true | ||
| 206 | $asserts item ~= nil | ||
| 207 | |||
| 208 | $config false | ||
| 209 | value = $assert item | ||
| 210 | |||
| 211 | -- 宏函数参数传递的表达式会被转换为字符串 | ||
| 212 | macro and = (...) -> "#{ table.concat {...}, ' and ' }" | ||
| 213 | if $and f1!, f2!, f3! | ||
| 214 | print "OK" | ||
| 215 | ``` | ||
| 216 | |||
| 217 | </YueDisplay> | ||
| 218 | |||
| 219 | ## 直接插入代码 | ||
| 220 | |||
| 221 |   宏函数可以返回一个包含月之脚本代码的字符串,或是一个包含 Lua 代码字符串的配置表。 | ||
| 222 | |||
| 223 | ```yuescript | ||
| 224 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 225 | $yueFunc funcA | ||
| 226 | funcA = -> "无法访问宏生成月之脚本里定义的变量" | ||
| 227 | |||
| 228 | macro luaFunc = (var) -> { | ||
| 229 | code: "local function #{var}() end" | ||
| 230 | type: "lua" | ||
| 231 | } | ||
| 232 | $luaFunc funcB | ||
| 233 | funcB = -> "无法访问宏生成 Lua 代码里定义的变量" | ||
| 234 | |||
| 235 | macro lua = (code) -> { | ||
| 236 | :code | ||
| 237 | type: "lua" | ||
| 238 | } | ||
| 239 | |||
| 240 | -- raw字符串的开始和结束符号会自动被去除了再传入宏函数 | ||
| 241 | $lua[==[ | ||
| 242 | -- 插入原始Lua代码 | ||
| 243 | if cond then | ||
| 244 | print("输出") | ||
| 245 | end | ||
| 246 | ]==] | ||
| 247 | ``` | ||
| 248 | |||
| 249 | <YueDisplay> | ||
| 250 | |||
| 251 | ```yue | ||
| 252 | macro yueFunc = (var) -> "local #{var} = ->" | ||
| 253 | $yueFunc funcA | ||
| 254 | funcA = -> "无法访问宏生成月之脚本里定义的变量" | ||
| 255 | |||
| 256 | macro luaFunc = (var) -> { | ||
| 257 | code: "local function #{var}() end" | ||
| 258 | type: "lua" | ||
| 259 | } | ||
| 260 | $luaFunc funcB | ||
| 261 | funcB = -> "无法访问宏生成 Lua 代码里定义的变量" | ||
| 262 | |||
| 263 | macro lua = (code) -> { | ||
| 264 | :code | ||
| 265 | type: "lua" | ||
| 266 | } | ||
| 267 | |||
| 268 | -- raw字符串的开始和结束符号会自动被去除了再传入宏函数 | ||
| 269 | $lua[==[ | ||
| 270 | -- 插入原始Lua代码 | ||
| 271 | if cond then | ||
| 272 | print("输出") | ||
| 273 | end | ||
| 274 | ]==] | ||
| 275 | ``` | ||
| 276 | |||
| 277 | </YueDisplay> | ||
| 278 | |||
| 279 | ## 导出宏 | ||
| 280 | |||
| 281 |   宏函数可以从一个模块中导出,并在另一个模块中导入。你必须将导出的宏函数放在一个单独的文件中使用,而且只有宏定义、宏导入和宏展开可以放入这个宏导出模块中。 | ||
| 282 | |||
| 283 | ```yuescript | ||
| 284 | -- 文件: utils.yue | ||
| 285 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 286 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 287 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 288 | #{action}" | ||
| 289 | |||
| 290 | -- 文件 main.yue | ||
| 291 | import "utils" as { | ||
| 292 | $, -- 表示导入所有宏的符号 | ||
| 293 | $foreach: $each -- 重命名宏 $foreach 为 $each | ||
| 294 | } | ||
| 295 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 296 | ``` | ||
| 297 | |||
| 298 | <YueDisplay> | ||
| 299 | |||
| 300 | ```yue | ||
| 301 | -- 文件: utils.yue | ||
| 302 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | ||
| 303 | export macro filter = (items, action) -> "[_ for _ in *#{items} when #{action}]" | ||
| 304 | export macro foreach = (items, action) -> "for _ in *#{items} | ||
| 305 | #{action}" | ||
| 306 | |||
| 307 | -- 文件 main.yue | ||
| 308 | -- 在浏览器中不支持import函数,请在真实环境中尝试 | ||
| 309 | --[[ | ||
| 310 | import "utils" as { | ||
| 311 | $, -- 表示导入所有宏的符号 | ||
| 312 | $foreach: $each -- 重命名宏 $foreach 为 $each | ||
| 313 | } | ||
| 314 | [1, 2, 3] |> $map(_ * 2) |> $filter(_ > 4) |> $each print _ | ||
| 315 | ]] | ||
| 316 | ``` | ||
| 317 | |||
| 318 | </YueDisplay> | ||
| 319 | |||
| 320 | ## 内置宏 | ||
| 321 | |||
| 322 |   月之脚本中有一些内置可以直接使用的宏,但你可以通过声明相同名称的宏来覆盖它们。 | ||
| 323 | |||
| 324 | ```yuescript | ||
| 325 | print $FILE -- 获取当前模块名称的字符串 | ||
| 326 | print $LINE -- 获取当前代码行数:2 | ||
| 327 | ``` | ||
| 328 | |||
| 329 | <YueDisplay> | ||
| 330 | |||
| 331 | ```yue | ||
| 332 | print $FILE -- 获取当前模块名称的字符串 | ||
| 333 | print $LINE -- 获取当前代码行数:2 | ||
| 334 | ``` | ||
| 335 | |||
| 336 | </YueDisplay> | ||
| 337 | |||
| 338 | ## 用宏生成宏 | ||
| 339 | |||
| 340 |   在月之脚本中,宏函数允许你在编译时生成代码。通过嵌套的宏函数,你可以创建更复杂的生成模式。这个特性允许你定义一个宏函数,用它来生成另一个宏函数,从而实现更加动态的代码生成。 | ||
| 341 | |||
| 342 | ```yuescript | ||
| 343 | macro Enum = (...) -> | ||
| 344 | items = {...} | ||
| 345 | itemSet = {item, true for item in *items} | ||
| 346 | (item) -> | ||
| 347 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 348 | "\"#{item}\"" | ||
| 349 | |||
| 350 | macro BodyType = $Enum( | ||
| 351 | Static | ||
| 352 | Dynamic | ||
| 353 | Kinematic | ||
| 354 | ) | ||
| 355 | |||
| 356 | print "有效的枚举类型:", $BodyType Static | ||
| 357 | -- print "编译报错的枚举类型:", $BodyType Unknown | ||
| 358 | ``` | ||
| 359 | |||
| 360 | <YueDisplay> | ||
| 361 | |||
| 362 | ```yue | ||
| 363 | macro Enum = (...) -> | ||
| 364 | items = {...} | ||
| 365 | itemSet = {item, true for item in *items} | ||
| 366 | (item) -> | ||
| 367 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | ||
| 368 | "\"#{item}\"" | ||
| 369 | |||
| 370 | macro BodyType = $Enum( | ||
| 371 | Static | ||
| 372 | Dynamic | ||
| 373 | Kinematic | ||
| 374 | ) | ||
| 375 | |||
| 376 | print "有效的枚举类型:", $BodyType Static | ||
| 377 | -- print "编译报错的枚举类型:", $BodyType Unknown | ||
| 378 | ``` | ||
| 379 | |||
| 380 | </YueDisplay> | ||
| 381 | |||
| 382 | ## 宏参数检查 | ||
| 383 | |||
| 384 |   可以直接在参数列表中声明期望的 AST 节点类型,并在编译时检查传入的宏参数是否符合预期。 | ||
| 385 | |||
| 386 | ```yuescript | ||
| 387 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 388 | print( | ||
| 389 | #{num} | ||
| 390 | #{str} | ||
| 391 | ) | ||
| 392 | |||
| 393 | $printNumAndStr 123, "hello" | ||
| 394 | ``` | ||
| 395 | |||
| 396 | <YueDisplay> | ||
| 397 | |||
| 398 | ```yue | ||
| 399 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 400 | print( | ||
| 401 | #{num} | ||
| 402 | #{str} | ||
| 403 | ) | ||
| 404 | |||
| 405 | $printNumAndStr 123, "hello" | ||
| 406 | ``` | ||
| 407 | |||
| 408 | </YueDisplay> | ||
| 409 | |||
| 410 |   如果需要做更加灵活的参数检查操作,可以使用内置的 `$is_ast` 宏函数在合适的位置进行手动检查。 | ||
| 411 | |||
| 412 | ```yuescript | ||
| 413 | macro printNumAndStr = (num, str) -> | ||
| 414 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 415 | error "expected String as second argument" unless $is_ast String, str | ||
| 416 | "print(#{num}, #{str})" | ||
| 417 | |||
| 418 | $printNumAndStr 123, "hello" | ||
| 419 | ``` | ||
| 420 | |||
| 421 | <YueDisplay> | ||
| 422 | |||
| 423 | ```yue | ||
| 424 | macro printNumAndStr = (num, str) -> | ||
| 425 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 426 | error "expected String as second argument" unless $is_ast String, str | ||
| 427 | "print(#{num}, #{str})" | ||
| 428 | |||
| 429 | $printNumAndStr 123, "hello" | ||
| 430 | ``` | ||
| 431 | |||
| 432 | </YueDisplay> | ||
| 433 | |||
| 434 |   更多关于可用 AST 节点的详细信息,请参考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) 中大写的规则定义。 | ||
| 435 | |||
| 436 | # 错误处理 | ||
| 437 | |||
| 438 |   用于统一进行 Lua 错误处理的便捷语法。 | ||
| 439 | |||
| 440 | ```yuescript | ||
| 441 | try | ||
| 442 | func 1, 2, 3 | ||
| 443 | catch err | ||
| 444 | print yue.traceback err | ||
| 445 | |||
| 446 | success, result = try | ||
| 447 | func 1, 2, 3 | ||
| 448 | catch err | ||
| 449 | yue.traceback err | ||
| 450 | |||
| 451 | try func 1, 2, 3 | ||
| 452 | catch err | ||
| 453 | print yue.traceback err | ||
| 454 | |||
| 455 | success, result = try func 1, 2, 3 | ||
| 456 | |||
| 457 | try | ||
| 458 | print "尝试中" | ||
| 459 | func 1, 2, 3 | ||
| 460 | |||
| 461 | -- 使用if赋值模式 | ||
| 462 | if success, result := try func 1, 2, 3 | ||
| 463 | catch err | ||
| 464 | print yue.traceback err | ||
| 465 | print result | ||
| 466 | ``` | ||
| 467 | |||
| 468 | <YueDisplay> | ||
| 469 | |||
| 470 | ```yue | ||
| 471 | try | ||
| 472 | func 1, 2, 3 | ||
| 473 | catch err | ||
| 474 | print yue.traceback err | ||
| 475 | |||
| 476 | success, result = try | ||
| 477 | func 1, 2, 3 | ||
| 478 | catch err | ||
| 479 | yue.traceback err | ||
| 480 | |||
| 481 | try func 1, 2, 3 | ||
| 482 | catch err | ||
| 483 | print yue.traceback err | ||
| 484 | |||
| 485 | success, result = try func 1, 2, 3 | ||
| 486 | |||
| 487 | try | ||
| 488 | print "尝试中" | ||
| 489 | func 1, 2, 3 | ||
| 490 | |||
| 491 | -- 使用if赋值模式 | ||
| 492 | if success, result := try func 1, 2, 3 | ||
| 493 | catch err | ||
| 494 | print yue.traceback err | ||
| 495 | print result | ||
| 496 | ``` | ||
| 497 | |||
| 498 | </YueDisplay> | ||
| 499 | |||
| 500 | ## 错误处理简化 | ||
| 501 | |||
| 502 |   `try?` 是 `try` 的功能简化语法,它不再返回 `try` 语句的布尔状态,并在成功时直接返回 `try` 代码块的结果,失败时返回 `nil` 值而非错误对象。 | ||
| 503 | |||
| 504 | ```yuescript | ||
| 505 | a, b, c = try? func! | ||
| 506 | |||
| 507 | -- 与空值合并运算符一起使用 | ||
| 508 | a = (try? func!) ?? "default" | ||
| 509 | |||
| 510 | -- 作为函数参数 | ||
| 511 | f try? func! | ||
| 512 | |||
| 513 | -- 带 catch 块的 try! | ||
| 514 | f try? | ||
| 515 | print 123 | ||
| 516 | func! | ||
| 517 | catch e | ||
| 518 | print e | ||
| 519 | e | ||
| 520 | ``` | ||
| 521 | |||
| 522 | <YueDisplay> | ||
| 523 | |||
| 524 | ```yue | ||
| 525 | a, b, c = try? func! | ||
| 526 | |||
| 527 | -- 与空值合并运算符一起使用 | ||
| 528 | a = (try? func!) ?? "default" | ||
| 529 | |||
| 530 | -- 作为函数参数 | ||
| 531 | f try? func! | ||
| 532 | |||
| 533 | -- 带 catch 块的 try! | ||
| 534 | f try? | ||
| 535 | print 123 | ||
| 536 | func! | ||
| 537 | catch e | ||
| 538 | print e | ||
| 539 | e | ||
| 540 | ``` | ||
| 541 | |||
| 542 | </YueDisplay> | ||
| 543 | |||
| 544 | # 表格字面量 | ||
| 545 | |||
| 546 |   和 Lua 一样,表格可以通过花括号进行定义。 | ||
| 547 | |||
| 548 | ```yuescript | ||
| 549 | some_values = [1, 2, 3, 4] | ||
| 550 | ``` | ||
| 551 | |||
| 552 | <YueDisplay> | ||
| 553 | |||
| 554 | ```yue | ||
| 555 | some_values = [1, 2, 3, 4] | ||
| 556 | ``` | ||
| 557 | |||
| 558 | </YueDisplay> | ||
| 559 | |||
| 560 |   但与Lua不同的是,给表格中的键赋值是用 **:**(而不是 **=**)。 | ||
| 561 | |||
| 562 | ```yuescript | ||
| 563 | some_values = { | ||
| 564 | name: "Bill", | ||
| 565 | age: 200, | ||
| 566 | ["favorite food"]: "rice" | ||
| 567 | } | ||
| 568 | ``` | ||
| 569 | |||
| 570 | <YueDisplay> | ||
| 571 | |||
| 572 | ```yue | ||
| 573 | some_values = { | ||
| 574 | name: "Bill", | ||
| 575 | age: 200, | ||
| 576 | ["favorite food"]: "rice" | ||
| 577 | } | ||
| 578 | ``` | ||
| 579 | |||
| 580 | </YueDisplay> | ||
| 581 | |||
| 582 |   如果只分配一个键值对的表格,可以省略花括号。 | ||
| 583 | |||
| 584 | ```yuescript | ||
| 585 | profile = | ||
| 586 | height: "4英尺", | ||
| 587 | shoe_size: 13, | ||
| 588 | favorite_foods: ["冰淇淋", "甜甜圈"] | ||
| 589 | ``` | ||
| 590 | |||
| 591 | <YueDisplay> | ||
| 592 | |||
| 593 | ```yue | ||
| 594 | profile = | ||
| 595 | height: "4英尺", | ||
| 596 | shoe_size: 13, | ||
| 597 | favorite_foods: ["冰淇淋", "甜甜圈"] | ||
| 598 | ``` | ||
| 599 | |||
| 600 | </YueDisplay> | ||
| 601 | |||
| 602 |   可以使用换行符而不使用逗号(或两者都用)来分隔表格中的值: | ||
| 603 | |||
| 604 | ```yuescript | ||
| 605 | values = { | ||
| 606 | 1, 2, 3, 4 | ||
| 607 | 5, 6, 7, 8 | ||
| 608 | name: "超人" | ||
| 609 | occupation: "打击犯罪" | ||
| 610 | } | ||
| 611 | ``` | ||
| 612 | |||
| 613 | <YueDisplay> | ||
| 614 | |||
| 615 | ```yue | ||
| 616 | values = { | ||
| 617 | 1, 2, 3, 4 | ||
| 618 | 5, 6, 7, 8 | ||
| 619 | name: "超人" | ||
| 620 | occupation: "打击犯罪" | ||
| 621 | } | ||
| 622 | ``` | ||
| 623 | |||
| 624 | </YueDisplay> | ||
| 625 | |||
| 626 |   创建单行表格字面量时,也可以省略花括号: | ||
| 627 | |||
| 628 | ```yuescript | ||
| 629 | my_function dance: "探戈", partner: "无" | ||
| 630 | |||
| 631 | y = type: "狗", legs: 4, tails: 1 | ||
| 632 | ``` | ||
| 633 | |||
| 634 | <YueDisplay> | ||
| 635 | |||
| 636 | ```yue | ||
| 637 | my_function dance: "探戈", partner: "无" | ||
| 638 | |||
| 639 | y = type: "狗", legs: 4, tails: 1 | ||
| 640 | ``` | ||
| 641 | |||
| 642 | </YueDisplay> | ||
| 643 | |||
| 644 |   表格字面量的键可以使用 Lua 语言的关键字,而无需转义: | ||
| 645 | |||
| 646 | ```yuescript | ||
| 647 | tbl = { | ||
| 648 | do: "某事" | ||
| 649 | end: "饥饿" | ||
| 650 | } | ||
| 651 | ``` | ||
| 652 | |||
| 653 | <YueDisplay> | ||
| 654 | |||
| 655 | ```yue | ||
| 656 | tbl = { | ||
| 657 | do: "某事" | ||
| 658 | end: "饥饿" | ||
| 659 | } | ||
| 660 | ``` | ||
| 661 | |||
| 662 | </YueDisplay> | ||
| 663 | |||
| 664 |   如果你要构造一个由变量组成的表,并希望键与变量名相同,那么可以使用 **:** 前缀操作符: | ||
| 665 | |||
| 666 | ```yuescript | ||
| 667 | hair = "金色" | ||
| 668 | height = 200 | ||
| 669 | person = { :hair, :height, shoe_size: 40 } | ||
| 670 | |||
| 671 | print_table :hair, :height | ||
| 672 | ``` | ||
| 673 | |||
| 674 | <YueDisplay> | ||
| 675 | |||
| 676 | ```yue | ||
| 677 | hair = "金色" | ||
| 678 | height = 200 | ||
| 679 | person = { :hair, :height, shoe_size: 40 } | ||
| 680 | |||
| 681 | print_table :hair, :height | ||
| 682 | ``` | ||
| 683 | |||
| 684 | </YueDisplay> | ||
| 685 | |||
| 686 |   如果你希望表中字段的键是某个表达式的结果,那么可以用 **[ ]** 包裹它,就像在 Lua 中一样。如果键中有任何特殊字符,也可以直接使用字符串字面量作为键,省略方括号。 | ||
| 687 | |||
| 688 | ```yuescript | ||
| 689 | t = { | ||
| 690 | [1 + 2]: "你好" | ||
| 691 | "你好 世界": true | ||
| 692 | } | ||
| 693 | ``` | ||
| 694 | |||
| 695 | <YueDisplay> | ||
| 696 | |||
| 697 | ```yue | ||
| 698 | t = { | ||
| 699 | [1 + 2]: "你好" | ||
| 700 | "你好 世界": true | ||
| 701 | } | ||
| 702 | ``` | ||
| 703 | |||
| 704 | </YueDisplay> | ||
| 705 | |||
| 706 |   Lua 的表同时具有数组部分和哈希部分,但有时候你会希望在书写 Lua 表时,对 Lua 表做数组和哈希不同用法的语义区分。然后你可以用 **[ ]** 而不是 **{ }** 来编写表示数组的 Lua 表,并且不允许在数组 Lua 表中写入任何键值对。 | ||
| 707 | |||
| 708 | ```yuescript | ||
| 709 | some_values = [ 1, 2, 3, 4 ] | ||
| 710 | list_with_one_element = [ 1, ] | ||
| 711 | ``` | ||
| 712 | |||
| 713 | <YueDisplay> | ||
| 714 | |||
| 715 | ```yue | ||
| 716 | some_values = [ 1, 2, 3, 4 ] | ||
| 717 | list_with_one_element = [ 1, ] | ||
| 718 | ``` | ||
| 719 | |||
| 720 | </YueDisplay> | ||
| 721 | |||
| 722 | # 推导式 | ||
| 723 | |||
| 724 |   推导式为我们提供了一种便捷的语法,通过遍历现有对象并对其值应用表达式来构造出新的表格。月之脚本有两种推导式:列表推导式和表格推导式。它们最终都是产生 Lua 表格;列表推导式将值累积到类似数组的表格中,而表格推导式允许你在每次遍历时设置新表格的键和值。 | ||
| 725 | |||
| 726 | ## 列表推导式 | ||
| 727 | |||
| 728 |   以下操作创建了一个 items 表的副本,但所有包含的值都翻倍了。 | ||
| 729 | |||
| 730 | ```yuescript | ||
| 731 | items = [1, 2, 3, 4] | ||
| 732 | doubled = [item * 2 for i, item in ipairs items] | ||
| 733 | ``` | ||
| 734 | |||
| 735 | <YueDisplay> | ||
| 736 | |||
| 737 | ```yue | ||
| 738 | items = [1, 2, 3, 4] | ||
| 739 | doubled = [item * 2 for i, item in ipairs items] | ||
| 740 | ``` | ||
| 741 | |||
| 742 | </YueDisplay> | ||
| 743 | |||
| 744 |   可以使用 `when` 子句筛选新表中包含的项目: | ||
| 745 | |||
| 746 | ```yuescript | ||
| 747 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 748 | ``` | ||
| 749 | |||
| 750 | <YueDisplay> | ||
| 751 | |||
| 752 | ```yue | ||
| 753 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | ||
| 754 | ``` | ||
| 755 | |||
| 756 | </YueDisplay> | ||
| 757 | |||
| 758 |   因为我们常常需要迭代数值索引表的值,所以引入了 **\*** 操作符来做语法简化。doubled 示例可以重写为: | ||
| 759 | |||
| 760 | ```yuescript | ||
| 761 | doubled = [item * 2 for item in *items] | ||
| 762 | ``` | ||
| 763 | |||
| 764 | <YueDisplay> | ||
| 765 | |||
| 766 | ```yue | ||
| 767 | doubled = [item * 2 for item in *items] | ||
| 768 | ``` | ||
| 769 | |||
| 770 | </YueDisplay> | ||
| 771 | |||
| 772 |   在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理: | ||
| 773 | |||
| 774 | ```yuescript | ||
| 775 | data = | ||
| 776 | a: [1, 2, 3] | ||
| 777 | b: [4, 5, 6] | ||
| 778 | |||
| 779 | flat = [...v for k,v in pairs data] | ||
| 780 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 781 | ``` | ||
| 782 | |||
| 783 | <YueDisplay> | ||
| 784 | |||
| 785 | ```yue | ||
| 786 | data = | ||
| 787 | a: [1, 2, 3] | ||
| 788 | b: [4, 5, 6] | ||
| 789 | |||
| 790 | flat = [...v for k,v in pairs data] | ||
| 791 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 792 | ``` | ||
| 793 | |||
| 794 | </YueDisplay> | ||
| 795 | |||
| 796 |   for 和 when 子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个 for 子句。 | ||
| 797 | |||
| 798 |   使用多个 for 子句与使用多重循环的效果相同: | ||
| 799 | |||
| 800 | ```yuescript | ||
| 801 | x_coords = [4, 5, 6, 7] | ||
| 802 | y_coords = [9, 2, 3] | ||
| 803 | |||
| 804 | points = [ [x, y] for x in *x_coords \ | ||
| 805 | for y in *y_coords] | ||
| 806 | ``` | ||
| 807 | |||
| 808 | <YueDisplay> | ||
| 809 | |||
| 810 | ```yue | ||
| 811 | x_coords = [4, 5, 6, 7] | ||
| 812 | y_coords = [9, 2, 3] | ||
| 813 | |||
| 814 | points = [ [x, y] for x in *x_coords \ | ||
| 815 | for y in *y_coords] | ||
| 816 | ``` | ||
| 817 | |||
| 818 | </YueDisplay> | ||
| 819 | |||
| 820 |   在推导式中也可以使用简单的数值 for 循环: | ||
| 821 | |||
| 822 | ```yuescript | ||
| 823 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 824 | ``` | ||
| 825 | |||
| 826 | <YueDisplay> | ||
| 827 | |||
| 828 | ```yue | ||
| 829 | evens = [i for i = 1, 100 when i % 2 == 0] | ||
| 830 | ``` | ||
| 831 | |||
| 832 | </YueDisplay> | ||
| 833 | |||
| 834 | ## 表格推导式 | ||
| 835 | |||
| 836 |   表格推导式和列表推导式的语法非常相似,只是要使用 **{** 和 **}** 并从每次迭代中取两个值。 | ||
| 837 | |||
| 838 |   以下示例生成了表格 thing 的副本: | ||
| 839 | |||
| 840 | ```yuescript | ||
| 841 | thing = { | ||
| 842 | color: "red" | ||
| 843 | name: "fast" | ||
| 844 | width: 123 | ||
| 845 | } | ||
| 846 | |||
| 847 | thing_copy = {k, v for k, v in pairs thing} | ||
| 848 | ``` | ||
| 849 | |||
| 850 | <YueDisplay> | ||
| 851 | |||
| 852 | ```yue | ||
| 853 | thing = { | ||
| 854 | color: "red" | ||
| 855 | name: "fast" | ||
| 856 | width: 123 | ||
| 857 | } | ||
| 858 | |||
| 859 | thing_copy = {k, v for k, v in pairs thing} | ||
| 860 | ``` | ||
| 861 | |||
| 862 | </YueDisplay> | ||
| 863 | |||
| 864 | ```yuescript | ||
| 865 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 866 | ``` | ||
| 867 | |||
| 868 | <YueDisplay> | ||
| 869 | |||
| 870 | ```yue | ||
| 871 | no_color = {k, v for k, v in pairs thing when k != "color"} | ||
| 872 | ``` | ||
| 873 | |||
| 874 | </YueDisplay> | ||
| 875 | |||
| 876 |   **\*** 操作符在表格推导式中能使用。在下面的例子里,我们为几个数字创建了一个平方根查找表。 | ||
| 877 | |||
| 878 | ```yuescript | ||
| 879 | numbers = [1, 2, 3, 4] | ||
| 880 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 881 | ``` | ||
| 882 | |||
| 883 | <YueDisplay> | ||
| 884 | |||
| 885 | ```yue | ||
| 886 | numbers = [1, 2, 3, 4] | ||
| 887 | sqrts = {i, math.sqrt i for i in *numbers} | ||
| 888 | ``` | ||
| 889 | |||
| 890 | </YueDisplay> | ||
| 891 | |||
| 892 |   表格推导式中的键值元组也可以来自单个表达式,在这种情况下,表达式在计算后应返回两个值。第一个用作键,第二个用作值: | ||
| 893 | |||
| 894 |   在下面的示例中,我们将一些数组转换为一个表,其中每个数组里的第一项是键,第二项是值。 | ||
| 895 | |||
| 896 | ```yuescript | ||
| 897 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 898 | tbl = {unpack tuple for tuple in *tuples} | ||
| 899 | ``` | ||
| 900 | |||
| 901 | <YueDisplay> | ||
| 902 | |||
| 903 | ```yue | ||
| 904 | tuples = [ ["hello", "world"], ["foo", "bar"]] | ||
| 905 | tbl = {unpack tuple for tuple in *tuples} | ||
| 906 | ``` | ||
| 907 | |||
| 908 | </YueDisplay> | ||
| 909 | |||
| 910 | ## 切片 | ||
| 911 | |||
| 912 |   当使用 **\*** 操作符时,月之脚本还提供了一种特殊的语法来限制要遍历的列表范围。这个语法也相当于在 for 循环中设置迭代边界和步长。 | ||
| 913 | |||
| 914 |   下面的案例中,我们在切片中设置最小和最大边界,取索引在 1 到 5 之间(包括 1 和 5)的所有项目: | ||
| 915 | |||
| 916 | ```yuescript | ||
| 917 | slice = [item for item in *items[1, 5]] | ||
| 918 | ``` | ||
| 919 | |||
| 920 | <YueDisplay> | ||
| 921 | |||
| 922 | ```yue | ||
| 923 | slice = [item for item in *items[1, 5]] | ||
| 924 | ``` | ||
| 925 | |||
| 926 | </YueDisplay> | ||
| 927 | |||
| 928 |   切片的任意参数都可以省略,并会使用默认值。在如下示例中,如果省略了最大索引边界,它默认为表的长度。使下面的代码取除第一个元素之外的所有元素: | ||
| 929 | |||
| 930 | ```yuescript | ||
| 931 | slice = [item for item in *items[2,]] | ||
| 932 | ``` | ||
| 933 | |||
| 934 | <YueDisplay> | ||
| 935 | |||
| 936 | ```yue | ||
| 937 | slice = [item for item in *items[2,]] | ||
| 938 | ``` | ||
| 939 | |||
| 940 | </YueDisplay> | ||
| 941 | |||
| 942 |   如果省略了最小边界,便默认会设置为 1。这里我们只提供一个步长,并留下其他边界为空。这样会使得代码取出所有奇数索引的项目:(1, 3, 5, …) | ||
| 943 | |||
| 944 | ```yuescript | ||
| 945 | slice = [item for item in *items[,,2]] | ||
| 946 | ``` | ||
| 947 | |||
| 948 | <YueDisplay> | ||
| 949 | |||
| 950 | ```yue | ||
| 951 | slice = [item for item in *items[,,2]] | ||
| 952 | ``` | ||
| 953 | |||
| 954 | </YueDisplay> | ||
| 955 | |||
| 956 |   最小和最大边界都可以是负数,使用负数意味着边界是从表的末尾开始计算的。 | ||
| 957 | |||
| 958 | ```yuescript | ||
| 959 | -- 取最后4个元素 | ||
| 960 | slice = [item for item in *items[-4,-1]] | ||
| 961 | ``` | ||
| 962 | |||
| 963 | <YueDisplay> | ||
| 964 | |||
| 965 | ```yue | ||
| 966 | -- 取最后4个元素 | ||
| 967 | slice = [item for item in *items[-4,-1]] | ||
| 968 | ``` | ||
| 969 | |||
| 970 | </YueDisplay> | ||
| 971 | |||
| 972 |   切片的步长也可以是负数,这意味着元素会以相反的顺序被取出。 | ||
| 973 | |||
| 974 | ```yuescript | ||
| 975 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 976 | ``` | ||
| 977 | |||
| 978 | <YueDisplay> | ||
| 979 | |||
| 980 | ```yue | ||
| 981 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 982 | ``` | ||
| 983 | |||
| 984 | </YueDisplay> | ||
| 985 | |||
| 986 | ### 切片表达式 | ||
| 987 | |||
| 988 |   切片也可以作为表达式来使用。可以用于获取一个表包含的子列表。 | ||
| 989 | |||
| 990 | ```yuescript | ||
| 991 | -- 取第2和第4个元素作为新的列表 | ||
| 992 | sub_list = items[2, 4] | ||
| 993 | |||
| 994 | -- 取最后4个元素作为新的列表 | ||
| 995 | last_four_items = items[-4, -1] | ||
| 996 | ``` | ||
| 997 | |||
| 998 | <YueDisplay> | ||
| 999 | |||
| 1000 | ```yue | ||
| 1001 | -- 取第2和第4个元素作为新的列表 | ||
| 1002 | sub_list = items[2, 4] | ||
| 1003 | |||
| 1004 | -- 取最后4个元素作为新的列表 | ||
| 1005 | last_four_items = items[-4, -1] | ||
| 1006 | ``` | ||
| 1007 | |||
| 1008 | </YueDisplay> | ||
| 1009 | |||
| 1010 | # 面向对象编程 | ||
| 1011 | |||
| 1012 |   在以下的示例中,月之脚本生成的 Lua 代码可能看起来会很复杂。所以最好主要关注月之脚本代码层面的意义,然后如果你想知道关于面向对象功能的实现细节,再查看 Lua 代码。 | ||
| 1013 | |||
| 1014 |   一个简单的类: | ||
| 1015 | |||
| 1016 | ```yuescript | ||
| 1017 | class Inventory | ||
| 1018 | new: => | ||
| 1019 | @items = {} | ||
| 1020 | |||
| 1021 | add_item: (name) => | ||
| 1022 | if @items[name] | ||
| 1023 | @items[name] += 1 | ||
| 1024 | else | ||
| 1025 | @items[name] = 1 | ||
| 1026 | ``` | ||
| 1027 | |||
| 1028 | <YueDisplay> | ||
| 1029 | |||
| 1030 | ```yue | ||
| 1031 | class Inventory | ||
| 1032 | new: => | ||
| 1033 | @items = {} | ||
| 1034 | |||
| 1035 | add_item: (name) => | ||
| 1036 | if @items[name] | ||
| 1037 | @items[name] += 1 | ||
| 1038 | else | ||
| 1039 | @items[name] = 1 | ||
| 1040 | ``` | ||
| 1041 | |||
| 1042 | </YueDisplay> | ||
| 1043 | |||
| 1044 |   在月之脚本中采用面向对象的编程方式时,通常会使用类声明语句结合 Lua 表格字面量来做类定义。这个类的定义包含了它的所有方法和属性。在这种结构中,键名为 “new” 的成员扮演了一个重要的角色,是作为构造函数来使用。 | ||
| 1045 | |||
| 1046 |   值得注意的是,类中的方法都采用了粗箭头函数语法。当在类的实例上调用方法时,该实例会自动作为第一个参数被传入,因此粗箭头函数用于生成一个名为 “self” 的参数。 | ||
| 1047 | |||
| 1048 |   此外,“@” 前缀在变量名上起到了简化作用,代表 “self”。例如,`@items` 就等同于 `self.items`。 | ||
| 1049 | |||
| 1050 |   为了创建类的一个新实例,可以将类名当作一个函数来调用,这样就可以生成并返回一个新的实例。 | ||
| 1051 | |||
| 1052 | ```yuescript | ||
| 1053 | inv = Inventory! | ||
| 1054 | inv\add_item "t-shirt" | ||
| 1055 | inv\add_item "pants" | ||
| 1056 | ``` | ||
| 1057 | |||
| 1058 | <YueDisplay> | ||
| 1059 | |||
| 1060 | ```yue | ||
| 1061 | inv = Inventory! | ||
| 1062 | inv\add_item "t-shirt" | ||
| 1063 | inv\add_item "pants" | ||
| 1064 | ``` | ||
| 1065 | |||
| 1066 | </YueDisplay> | ||
| 1067 | |||
| 1068 |   在月之脚本的类中,由于需要将类的实例作为参数传入到调用的方法中,因此使用了 **\\** 操作符做类的成员函数调用。 | ||
| 1069 | |||
| 1070 |   需要特别注意的是,类的所有属性在其实例之间是共享的。这对于函数类型的成员属性通常不会造成问题,但对于其他类型的属性,可能会导致意外的结果。 | ||
| 1071 | |||
| 1072 |   例如,在下面的示例中,clothes 属性在所有实例之间共享。因此,对这个属性在一个实例中的修改,将会影响到其他所有实例。 | ||
| 1073 | |||
| 1074 | ```yuescript | ||
| 1075 | class Person | ||
| 1076 | clothes: [] | ||
| 1077 | give_item: (name) => | ||
| 1078 | table.insert @clothes, name | ||
| 1079 | |||
| 1080 | a = Person! | ||
| 1081 | b = Person! | ||
| 1082 | |||
| 1083 | a\give_item "pants" | ||
| 1084 | b\give_item "shirt" | ||
| 1085 | |||
| 1086 | -- 会同时打印出裤子和衬衫 | ||
| 1087 | print item for item in *a.clothes | ||
| 1088 | ``` | ||
| 1089 | |||
| 1090 | <YueDisplay> | ||
| 1091 | |||
| 1092 | ```yue | ||
| 1093 | class Person | ||
| 1094 | clothes: [] | ||
| 1095 | give_item: (name) => | ||
| 1096 | table.insert @clothes, name | ||
| 1097 | |||
| 1098 | a = Person! | ||
| 1099 | b = Person! | ||
| 1100 | |||
| 1101 | a\give_item "pants" | ||
| 1102 | b\give_item "shirt" | ||
| 1103 | |||
| 1104 | -- 会同时打印出裤子和衬衫 | ||
| 1105 | print item for item in *a.clothes | ||
| 1106 | ``` | ||
| 1107 | |||
| 1108 | </YueDisplay> | ||
| 1109 | |||
| 1110 |   避免这个问题的正确方法是在构造函数中创建对象的可变状态: | ||
| 1111 | |||
| 1112 | ```yuescript | ||
| 1113 | class Person | ||
| 1114 | new: => | ||
| 1115 | @clothes = [] | ||
| 1116 | ``` | ||
| 1117 | |||
| 1118 | <YueDisplay> | ||
| 1119 | |||
| 1120 | ```yue | ||
| 1121 | class Person | ||
| 1122 | new: => | ||
| 1123 | @clothes = [] | ||
| 1124 | ``` | ||
| 1125 | |||
| 1126 | </YueDisplay> | ||
| 1127 | |||
| 1128 | ## 继承 | ||
| 1129 | |||
| 1130 |   `extends` 关键字可以在类声明中使用,以继承另一个类的属性和方法。 | ||
| 1131 | |||
| 1132 | ```yuescript | ||
| 1133 | class BackPack extends Inventory | ||
| 1134 | size: 10 | ||
| 1135 | add_item: (name) => | ||
| 1136 | if #@items > size then error "背包已满" | ||
| 1137 | super name | ||
| 1138 | ``` | ||
| 1139 | |||
| 1140 | <YueDisplay> | ||
| 1141 | |||
| 1142 | ```yue | ||
| 1143 | class BackPack extends Inventory | ||
| 1144 | size: 10 | ||
| 1145 | add_item: (name) => | ||
| 1146 | if #@items > size then error "背包已满" | ||
| 1147 | super name | ||
| 1148 | ``` | ||
| 1149 | |||
| 1150 | </YueDisplay> | ||
| 1151 | |||
| 1152 |   在这一部分,我们对月之脚本中的 `Inventory` 类进行了扩展,加入了对可以携带物品数量的限制。 | ||
| 1153 | |||
| 1154 |   在这个特定的例子中,子类并没有定义自己的构造函数。因此,当创建一个新的实例时,系统会默认调用父类的构造函数。但如果我们在子类中定义了构造函数,我们可以利用 `super` 方法来调用并执行父类的构造函数。 | ||
| 1155 | |||
| 1156 |   此外,当一个类继承自另一个类时,它会尝试调用父类上的 `__inherited` 方法(如果这个方法存在的话),以此来向父类发送通知。这个 `__inherited` 函数接受两个参数:被继承的父类和继承的子类。 | ||
| 1157 | |||
| 1158 | ```yuescript | ||
| 1159 | class Shelf | ||
| 1160 | @__inherited: (child) => | ||
| 1161 | print @__name, "被", child.__name, "继承" | ||
| 1162 | |||
| 1163 | -- 将打印: Shelf 被 Cupboard 继承 | ||
| 1164 | class Cupboard extends Shelf | ||
| 1165 | ``` | ||
| 1166 | |||
| 1167 | <YueDisplay> | ||
| 1168 | |||
| 1169 | ```yue | ||
| 1170 | class Shelf | ||
| 1171 | @__inherited: (child) => | ||
| 1172 | print @__name, "被", child.__name, "继承" | ||
| 1173 | |||
| 1174 | -- 将打印: Shelf 被 Cupboard 继承 | ||
| 1175 | class Cupboard extends Shelf | ||
| 1176 | ``` | ||
| 1177 | |||
| 1178 | </YueDisplay> | ||
| 1179 | |||
| 1180 | ## super 关键字 | ||
| 1181 | |||
| 1182 |   `super` 是一个特别的关键字,它有两种不同的使用方式:既可以当作一个对象来看待,也可以像调用函数那样使用。它仅在类的内部使用时具有特殊的功能。 | ||
| 1183 | |||
| 1184 |   当 `super` 被作为一个函数调用时,它将调用父类中与之同名的函数。此时,当前的 `self` 会自动作为第一个参数传递,正如上面提到的继承示例所展示的那样。 | ||
| 1185 | |||
| 1186 |   在将 `super` 当作普通值使用时,它实际上是对父类对象的引用。通过这种方式,我们可以访问父类中可能被子类覆盖的值,就像访问任何普通对象一样。 | ||
| 1187 | |||
| 1188 |   此外,当使用 `\` 操作符与 `super` 一起使用时,`self`将被插入为第一个参数,而不是使用 `super` 本身的值。而在使用`.`操作符来检索函数时,则会返回父类中的原始函数。 | ||
| 1189 | |||
| 1190 |   下面是一些使用 `super` 的不同方法的示例: | ||
| 1191 | |||
| 1192 | ```yuescript | ||
| 1193 | class MyClass extends ParentClass | ||
| 1194 | a_method: => | ||
| 1195 | -- 以下效果相同: | ||
| 1196 | super "你好", "世界" | ||
| 1197 | super\a_method "你好", "世界" | ||
| 1198 | super.a_method self, "你好", "世界" | ||
| 1199 | |||
| 1200 | -- super 作为值等于父类: | ||
| 1201 | assert super == ParentClass | ||
| 1202 | ``` | ||
| 1203 | |||
| 1204 | <YueDisplay> | ||
| 1205 | |||
| 1206 | ```yue | ||
| 1207 | class MyClass extends ParentClass | ||
| 1208 | a_method: => | ||
| 1209 | -- 以下效果相同: | ||
| 1210 | super "你好", "世界" | ||
| 1211 | super\a_method "你好", "世界" | ||
| 1212 | super.a_method self, "你好", "世界" | ||
| 1213 | |||
| 1214 | -- super 作为值等于父类: | ||
| 1215 | assert super == ParentClass | ||
| 1216 | ``` | ||
| 1217 | |||
| 1218 | </YueDisplay> | ||
| 1219 | |||
| 1220 |   **super** 也可以用在函数存根的左侧。唯一的主要区别是,生成的函数不是绑定到 super 的值,而是绑定到 self。 | ||
| 1221 | |||
| 1222 | ## 类型 | ||
| 1223 | |||
| 1224 |   每个类的实例都带有它的类型。这存储在特殊的 \_\_class 属性中。此属性会保存类对象。类对象是我们用来构建新实例的对象。我们还可以索引类对象以检索类方法和属性。 | ||
| 1225 | |||
| 1226 | ```yuescript | ||
| 1227 | b = BackPack! | ||
| 1228 | assert b.__class == BackPack | ||
| 1229 | |||
| 1230 | print BackPack.size -- 打印 10 | ||
| 1231 | ``` | ||
| 1232 | |||
| 1233 | <YueDisplay> | ||
| 1234 | |||
| 1235 | ```yue | ||
| 1236 | b = BackPack! | ||
| 1237 | assert b.__class == BackPack | ||
| 1238 | |||
| 1239 | print BackPack.size -- 打印 10 | ||
| 1240 | ``` | ||
| 1241 | |||
| 1242 | </YueDisplay> | ||
| 1243 | |||
| 1244 | ## 类对象 | ||
| 1245 | |||
| 1246 |   在月之脚本中,当我们编写类的定义语句时,实际上是在创建一个类对象。这个类对象被保存在一个与该类同名的变量中。 | ||
| 1247 | |||
| 1248 |   类对象具有函数的特性,可以被调用来创建新的实例。这正是我们在之前示例中所展示的创建类实例的方式。 | ||
| 1249 | |||
| 1250 |   一个类由两个表构成:类表本身和一个基表。基表作为所有实例的元表。在类声明中列出的所有属性都存放在基表中。 | ||
| 1251 | |||
| 1252 |   如果在类对象的元表中找不到某个属性,系统会从基表中检索该属性。这就意味着我们可以直接从类本身访问到其方法和属性。 | ||
| 1253 | |||
| 1254 |   需要特别注意的是,对类对象的赋值并不会影响到基表,因此这不是向实例添加新方法的正确方式。相反,需要直接修改基表。关于这点,可以参考下面的 “\_\_base” 字段。 | ||
| 1255 | |||
| 1256 |   此外,类对象包含几个特殊的属性:当类被声明时,类的名称会作为一个字符串存储在类对象的 “\_\_name” 字段中。 | ||
| 1257 | |||
| 1258 | ```yuescript | ||
| 1259 | print BackPack.__name -- 打印 Backpack | ||
| 1260 | ``` | ||
| 1261 | |||
| 1262 | <YueDisplay> | ||
| 1263 | |||
| 1264 | ```yue | ||
| 1265 | print BackPack.__name -- 打印 Backpack | ||
| 1266 | ``` | ||
| 1267 | |||
| 1268 | </YueDisplay> | ||
| 1269 | |||
| 1270 |   基础对象被保存在一个名为 `__base` 的特殊表中。我们可以编辑这个表,以便为那些已经创建出来的实例和还未创建的实例增加新的功能。 | ||
| 1271 | |||
| 1272 |   另外,如果一个类是从另一个类派生而来的,那么其父类对象则会被存储在名为 `__parent` 的地方。这种机制允许在类之间实现继承和功能扩展。 | ||
| 1273 | |||
| 1274 | ## 类变量 | ||
| 1275 | |||
| 1276 |   我们可以直接在类对象中创建变量,而不是在类的基对象中,通过在类声明中的属性名前使用 @。 | ||
| 1277 | |||
| 1278 | ```yuescript | ||
| 1279 | class Things | ||
| 1280 | @some_func: => print "Hello from", @__name | ||
| 1281 | |||
| 1282 | Things\some_func! | ||
| 1283 | |||
| 1284 | -- 类变量在实例中不可见 | ||
| 1285 | assert Things().some_func == nil | ||
| 1286 | ``` | ||
| 1287 | |||
| 1288 | <YueDisplay> | ||
| 1289 | |||
| 1290 | ```yue | ||
| 1291 | class Things | ||
| 1292 | @some_func: => print "Hello from", @__name | ||
| 1293 | |||
| 1294 | Things\some_func! | ||
| 1295 | |||
| 1296 | -- 类变量在实例中不可见 | ||
| 1297 | assert Things().some_func == nil | ||
| 1298 | ``` | ||
| 1299 | |||
| 1300 | </YueDisplay> | ||
| 1301 | |||
| 1302 |   在表达式中,我们可以使用 @@ 来访问存储在 `self.__class` 中的值。因此,`@@hello` 是 `self.__class.hello` 的简写。 | ||
| 1303 | |||
| 1304 | ```yuescript | ||
| 1305 | class Counter | ||
| 1306 | @count: 0 | ||
| 1307 | |||
| 1308 | new: => | ||
| 1309 | @@count += 1 | ||
| 1310 | |||
| 1311 | Counter! | ||
| 1312 | Counter! | ||
| 1313 | |||
| 1314 | print Counter.count -- 输出 2 | ||
| 1315 | ``` | ||
| 1316 | |||
| 1317 | <YueDisplay> | ||
| 1318 | |||
| 1319 | ```yue | ||
| 1320 | class Counter | ||
| 1321 | @count: 0 | ||
| 1322 | |||
| 1323 | new: => | ||
| 1324 | @@count += 1 | ||
| 1325 | |||
| 1326 | Counter! | ||
| 1327 | Counter! | ||
| 1328 | |||
| 1329 | print Counter.count -- 输出 2 | ||
| 1330 | ``` | ||
| 1331 | |||
| 1332 | </YueDisplay> | ||
| 1333 | |||
| 1334 |   @@ 的调用语义与 @ 类似。调用 @@ 时,会使用 Lua 的冒号语法将类作为第一个参数传入。 | ||
| 1335 | |||
| 1336 | ```yuescript | ||
| 1337 | @@hello 1,2,3,4 | ||
| 1338 | ``` | ||
| 1339 | |||
| 1340 | <YueDisplay> | ||
| 1341 | |||
| 1342 | ```yue | ||
| 1343 | @@hello 1,2,3,4 | ||
| 1344 | ``` | ||
| 1345 | |||
| 1346 | </YueDisplay> | ||
| 1347 | |||
| 1348 | ## 类声明语句 | ||
| 1349 | |||
| 1350 |   在类声明的主体中,除了键/值对外,我们还可以编写普通的表达式。在这种类声明体中的普通代码的上下文中,self 等于类对象,而不是实例对象。 | ||
| 1351 | |||
| 1352 |   以下是创建类变量的另一种方法: | ||
| 1353 | |||
| 1354 | ```yuescript | ||
| 1355 | class Things | ||
| 1356 | @class_var = "hello world" | ||
| 1357 | ``` | ||
| 1358 | |||
| 1359 | <YueDisplay> | ||
| 1360 | |||
| 1361 | ```yue | ||
| 1362 | class Things | ||
| 1363 | @class_var = "hello world" | ||
| 1364 | ``` | ||
| 1365 | |||
| 1366 | </YueDisplay> | ||
| 1367 | |||
| 1368 |   这些表达式会在所有属性被添加到类的基对象后执行。 | ||
| 1369 | |||
| 1370 |   在类的主体中声明的所有变量都会限制作用域只在类声明的范围。这对于放置只有类方法可以访问的私有值或辅助函数很方便: | ||
| 1371 | |||
| 1372 | ```yuescript | ||
| 1373 | class MoreThings | ||
| 1374 | secret = 123 | ||
| 1375 | log = (msg) -> print "LOG:", msg | ||
| 1376 | |||
| 1377 | some_method: => | ||
| 1378 | log "hello world: " .. secret | ||
| 1379 | ``` | ||
| 1380 | |||
| 1381 | <YueDisplay> | ||
| 1382 | |||
| 1383 | ```yue | ||
| 1384 | class MoreThings | ||
| 1385 | secret = 123 | ||
| 1386 | log = (msg) -> print "LOG:", msg | ||
| 1387 | |||
| 1388 | some_method: => | ||
| 1389 | log "hello world: " .. secret | ||
| 1390 | ``` | ||
| 1391 | |||
| 1392 | </YueDisplay> | ||
| 1393 | |||
| 1394 | ## @ 和 @@ 值 | ||
| 1395 | |||
| 1396 |   当 @ 和 @@ 前缀在一个名字前时,它们分别代表在 self 和 self.\_\_class 中访问的那个名字。 | ||
| 1397 | |||
| 1398 |   如果它们单独使用,它们是 self 和 self.\_\_class 的别名。 | ||
| 1399 | |||
| 1400 | ```yuescript | ||
| 1401 | assert @ == self | ||
| 1402 | assert @@ == self.__class | ||
| 1403 | ``` | ||
| 1404 | |||
| 1405 | <YueDisplay> | ||
| 1406 | |||
| 1407 | ```yue | ||
| 1408 | assert @ == self | ||
| 1409 | assert @@ == self.__class | ||
| 1410 | ``` | ||
| 1411 | |||
| 1412 | </YueDisplay> | ||
| 1413 | |||
| 1414 |   例如,使用 @@ 从实例方法快速创建同一类的新实例的方法: | ||
| 1415 | |||
| 1416 | ```yuescript | ||
| 1417 | some_instance_method = (...) => @@ ... | ||
| 1418 | ``` | ||
| 1419 | |||
| 1420 | <YueDisplay> | ||
| 1421 | |||
| 1422 | ```yue | ||
| 1423 | some_instance_method = (...) => @@ ... | ||
| 1424 | ``` | ||
| 1425 | |||
| 1426 | </YueDisplay> | ||
| 1427 | |||
| 1428 | ## 构造属性提升 | ||
| 1429 | |||
| 1430 |   为了减少编写简单值对象定义的代码。你可以这样简单写一个类: | ||
| 1431 | |||
| 1432 | ```yuescript | ||
| 1433 | class Something | ||
| 1434 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1435 | |||
| 1436 | -- 这是以下声明的简写形式 | ||
| 1437 | |||
| 1438 | class Something | ||
| 1439 | new: (foo, bar, biz, baz) => | ||
| 1440 | @foo = foo | ||
| 1441 | @bar = bar | ||
| 1442 | @@biz = biz | ||
| 1443 | @@baz = baz | ||
| 1444 | ``` | ||
| 1445 | |||
| 1446 | <YueDisplay> | ||
| 1447 | |||
| 1448 | ```yue | ||
| 1449 | class Something | ||
| 1450 | new: (@foo, @bar, @@biz, @@baz) => | ||
| 1451 | |||
| 1452 | -- 这是以下声明的简写形式 | ||
| 1453 | |||
| 1454 | class Something | ||
| 1455 | new: (foo, bar, biz, baz) => | ||
| 1456 | @foo = foo | ||
| 1457 | @bar = bar | ||
| 1458 | @@biz = biz | ||
| 1459 | @@baz = baz | ||
| 1460 | ``` | ||
| 1461 | |||
| 1462 | </YueDisplay> | ||
| 1463 | |||
| 1464 |   你也可以使用这种语法为一个函数初始化传入对象的字段。 | ||
| 1465 | |||
| 1466 | ```yuescript | ||
| 1467 | new = (@fieldA, @fieldB) => @ | ||
| 1468 | obj = new {}, 123, "abc" | ||
| 1469 | print obj | ||
| 1470 | ``` | ||
| 1471 | |||
| 1472 | <YueDisplay> | ||
| 1473 | |||
| 1474 | ```yue | ||
| 1475 | new = (@fieldA, @fieldB) => @ | ||
| 1476 | obj = new {}, 123, "abc" | ||
| 1477 | print obj | ||
| 1478 | ``` | ||
| 1479 | |||
| 1480 | </YueDisplay> | ||
| 1481 | |||
| 1482 | ## 类表达式 | ||
| 1483 | |||
| 1484 |   类声明的语法也可以作为一个表达式使用,可以赋值给一个变量或者被返回语句返回。 | ||
| 1485 | |||
| 1486 | ```yuescript | ||
| 1487 | x = class Bucket | ||
| 1488 | drops: 0 | ||
| 1489 | add_drop: => @drops += 1 | ||
| 1490 | ``` | ||
| 1491 | |||
| 1492 | <YueDisplay> | ||
| 1493 | |||
| 1494 | ```yue | ||
| 1495 | x = class Bucket | ||
| 1496 | drops: 0 | ||
| 1497 | add_drop: => @drops += 1 | ||
| 1498 | ``` | ||
| 1499 | |||
| 1500 | </YueDisplay> | ||
| 1501 | |||
| 1502 | ## 匿名类 | ||
| 1503 | |||
| 1504 |   声明类时可以省略名称。如果类的表达式不在赋值语句中,\_\_name 属性将为 nil。如果出现在赋值语句中,赋值操作左侧的名称将代替 nil。 | ||
| 1505 | |||
| 1506 | ```yuescript | ||
| 1507 | BigBucket = class extends Bucket | ||
| 1508 | add_drop: => @drops += 10 | ||
| 1509 | |||
| 1510 | assert Bucket.__name == "BigBucket" | ||
| 1511 | ``` | ||
| 1512 | |||
| 1513 | <YueDisplay> | ||
| 1514 | |||
| 1515 | ```yue | ||
| 1516 | BigBucket = class extends Bucket | ||
| 1517 | add_drop: => @drops += 10 | ||
| 1518 | |||
| 1519 | assert Bucket.__name == "BigBucket" | ||
| 1520 | ``` | ||
| 1521 | |||
| 1522 | </YueDisplay> | ||
| 1523 | |||
| 1524 |   你甚至可以省略掉主体,这意味着你可以这样写一个空白的匿名类: | ||
| 1525 | |||
| 1526 | ```yuescript | ||
| 1527 | x = class | ||
| 1528 | ``` | ||
| 1529 | |||
| 1530 | <YueDisplay> | ||
| 1531 | |||
| 1532 | ```yue | ||
| 1533 | x = class | ||
| 1534 | ``` | ||
| 1535 | |||
| 1536 | </YueDisplay> | ||
| 1537 | |||
| 1538 | ## 类混合 | ||
| 1539 | |||
| 1540 |   你可以通过使用 `using` 关键字来实现类混合。这意味着你可以从一个普通 Lua 表格或已定义的类对象中,复制函数到你创建的新类中。当你使用普通 Lua 表格进行类混合时,你有机会用自己的实现来重写类的索引方法(例如元方法 `__index`)。然而,当你从一个类对象做混合时,需要注意的是该类对象的元方法将不会被复制到新类。 | ||
| 1541 | |||
| 1542 | ```yuescript | ||
| 1543 | MyIndex = __index: var: 1 | ||
| 1544 | |||
| 1545 | class X using MyIndex | ||
| 1546 | func: => | ||
| 1547 | print 123 | ||
| 1548 | |||
| 1549 | x = X! | ||
| 1550 | print x.var | ||
| 1551 | |||
| 1552 | class Y using X | ||
| 1553 | |||
| 1554 | y = Y! | ||
| 1555 | y\func! | ||
| 1556 | |||
| 1557 | assert y.__class.__parent ~= X -- X 不是 Y 的父类 | ||
| 1558 | ``` | ||
| 1559 | |||
| 1560 | <YueDisplay> | ||
| 1561 | |||
| 1562 | ```yue | ||
| 1563 | MyIndex = __index: var: 1 | ||
| 1564 | |||
| 1565 | class X using MyIndex | ||
| 1566 | func: => | ||
| 1567 | print 123 | ||
| 1568 | |||
| 1569 | x = X! | ||
| 1570 | print x.var | ||
| 1571 | |||
| 1572 | class Y using X | ||
| 1573 | |||
| 1574 | y = Y! | ||
| 1575 | y\func! | ||
| 1576 | |||
| 1577 | assert y.__class.__parent ~= X -- X 不是 Y 的父类 | ||
| 1578 | ``` | ||
| 1579 | |||
| 1580 | </YueDisplay> | ||
| 1581 | |||
| 1582 | # with 语句 | ||
| 1583 | |||
| 1584 | 在编写 Lua 代码时,我们在创建对象后的常见操作是立即调用这个对象一系列操作函数并设置一系列属性。 | ||
| 1585 | |||
| 1586 | 这导致在代码中多次重复引用对象的名称,增加了不必要的文本噪音。一个常见的解决方案是在创建对象时,在构造函数传入一个表,该表包含要覆盖设置的键和值的集合。这样做的缺点是该对象的构造函数必须支持这种初始化形式。 | ||
| 1587 | |||
| 1588 | with 块有助于简化编写这样的代码。在 with 块内,我们可以使用以 . 或 \ 开头的特殊语句,这些语句代表我们正在使用的对象的操作。 | ||
| 1589 | |||
| 1590 | 例如,我们可以这样处理一个新创建的对象: | ||
| 1591 | |||
| 1592 | ```yuescript | ||
| 1593 | with Person! | ||
| 1594 | .name = "Oswald" | ||
| 1595 | \add_relative my_dad | ||
| 1596 | \save! | ||
| 1597 | print .name | ||
| 1598 | ``` | ||
| 1599 | |||
| 1600 | <YueDisplay> | ||
| 1601 | |||
| 1602 | ```yue | ||
| 1603 | with Person! | ||
| 1604 | .name = "Oswald" | ||
| 1605 | \add_relative my_dad | ||
| 1606 | \save! | ||
| 1607 | print .name | ||
| 1608 | ``` | ||
| 1609 | |||
| 1610 | </YueDisplay> | ||
| 1611 | |||
| 1612 | with 语句也可以用作一个表达式,并返回它的代码块正在处理的对象。 | ||
| 1613 | |||
| 1614 | ```yuescript | ||
| 1615 | file = with File "favorite_foods.txt" | ||
| 1616 | \set_encoding "utf8" | ||
| 1617 | ``` | ||
| 1618 | |||
| 1619 | <YueDisplay> | ||
| 1620 | |||
| 1621 | ```yue | ||
| 1622 | file = with File "favorite_foods.txt" | ||
| 1623 | \set_encoding "utf8" | ||
| 1624 | ``` | ||
| 1625 | |||
| 1626 | </YueDisplay> | ||
| 1627 | |||
| 1628 | `with` 表达式支持 `break` 返回一个值: | ||
| 1629 | |||
| 1630 | ```yuescript | ||
| 1631 | result = with obj | ||
| 1632 | break .value | ||
| 1633 | ``` | ||
| 1634 | |||
| 1635 | <YueDisplay> | ||
| 1636 | |||
| 1637 | ```yue | ||
| 1638 | result = with obj | ||
| 1639 | break .value | ||
| 1640 | ``` | ||
| 1641 | |||
| 1642 | </YueDisplay> | ||
| 1643 | |||
| 1644 | 在 `with` 中使用 `break value` 后,`with` 表达式将不再返回其目标对象,而是返回 `break` 给出的值。 | ||
| 1645 | |||
| 1646 | ```yuescript | ||
| 1647 | a = with obj | ||
| 1648 | .x = 1 | ||
| 1649 | -- a 是 obj | ||
| 1650 | |||
| 1651 | b = with obj | ||
| 1652 | break .x | ||
| 1653 | -- b 是 .x,不是 obj | ||
| 1654 | ``` | ||
| 1655 | |||
| 1656 | <YueDisplay> | ||
| 1657 | |||
| 1658 | ```yue | ||
| 1659 | a = with obj | ||
| 1660 | .x = 1 | ||
| 1661 | -- a 是 obj | ||
| 1662 | |||
| 1663 | b = with obj | ||
| 1664 | break .x | ||
| 1665 | -- b 是 .x,不是 obj | ||
| 1666 | ``` | ||
| 1667 | |||
| 1668 | </YueDisplay> | ||
| 1669 | |||
| 1670 | 与 `for` / `while` / `repeat` / `do` 不同,`with` 只支持一个 break 返回值。 | ||
| 1671 | |||
| 1672 | 或者… | ||
| 1673 | |||
| 1674 | ```yuescript | ||
| 1675 | create_person = (name, relatives) -> | ||
| 1676 | with Person! | ||
| 1677 | .name = name | ||
| 1678 | \add_relative relative for relative in *relatives | ||
| 1679 | |||
| 1680 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1681 | ``` | ||
| 1682 | |||
| 1683 | <YueDisplay> | ||
| 1684 | |||
| 1685 | ```yue | ||
| 1686 | create_person = (name, relatives) -> | ||
| 1687 | with Person! | ||
| 1688 | .name = name | ||
| 1689 | \add_relative relative for relative in *relatives | ||
| 1690 | |||
| 1691 | me = create_person "Leaf", [dad, mother, sister] | ||
| 1692 | ``` | ||
| 1693 | |||
| 1694 | </YueDisplay> | ||
| 1695 | |||
| 1696 | 在此用法中,with 可以被视为K组合子(k-combinator)的一种特殊形式。 | ||
| 1697 | |||
| 1698 | 如果你想给表达式另外起一个名称的话,with 语句中的表达式也可以是一个赋值语句。 | ||
| 1699 | |||
| 1700 | ```yuescript | ||
| 1701 | with str := "你好" | ||
| 1702 | print "原始:", str | ||
| 1703 | print "大写:", \upper! | ||
| 1704 | ``` | ||
| 1705 | |||
| 1706 | <YueDisplay> | ||
| 1707 | |||
| 1708 | ```yue | ||
| 1709 | with str := "你好" | ||
| 1710 | print "原始:", str | ||
| 1711 | print "大写:", \upper! | ||
| 1712 | ``` | ||
| 1713 | |||
| 1714 | </YueDisplay> | ||
| 1715 | |||
| 1716 | 你可以在 `with` 语句中使用 `[]` 访问特殊键。 | ||
| 1717 | |||
| 1718 | ```yuescript | ||
| 1719 | with tb | ||
| 1720 | [1] = 1 | ||
| 1721 | print [2] | ||
| 1722 | with [abc] | ||
| 1723 | [3] = [2]\func! | ||
| 1724 | ["key-name"] = value | ||
| 1725 | [] = "abc" -- 追加到 "tb" | ||
| 1726 | ``` | ||
| 1727 | |||
| 1728 | <YueDisplay> | ||
| 1729 | |||
| 1730 | ```yue | ||
| 1731 | with tb | ||
| 1732 | [1] = 1 | ||
| 1733 | print [2] | ||
| 1734 | with [abc] | ||
| 1735 | [3] = [2]\func! | ||
| 1736 | ["key-name"] = value | ||
| 1737 | [] = "abc" -- 追加到 "tb" | ||
| 1738 | ``` | ||
| 1739 | |||
| 1740 | </YueDisplay> | ||
| 1741 | |||
| 1742 | `with?` 是 `with` 语法的一个增强版本,引入了存在性检查,用于在不显式判空的情况下安全访问可能为 nil 的对象。 | ||
| 1743 | |||
| 1744 | ```yuescript | ||
| 1745 | with? obj | ||
| 1746 | print obj.name | ||
| 1747 | ``` | ||
| 1748 | |||
| 1749 | <YueDisplay> | ||
| 1750 | |||
| 1751 | ```yue | ||
| 1752 | with? obj | ||
| 1753 | print obj.name | ||
| 1754 | ``` | ||
| 1755 | |||
| 1756 | </YueDisplay> | ||
| 1757 | |||
| 1758 | # 赋值 | ||
| 1759 | |||
| 1760 |   月之脚本中定义的变量是动态类型的,并默认为局部变量。但你可以通过 **local** 和 **global** 声明来改变声明变量的作用范围。 | ||
| 1761 | |||
| 1762 | ```yuescript | ||
| 1763 | hello = "world" | ||
| 1764 | a, b, c = 1, 2, 3 | ||
| 1765 | hello = 123 -- 访问现有的变量 | ||
| 1766 | ``` | ||
| 1767 | |||
| 1768 | <YueDisplay> | ||
| 1769 | |||
| 1770 | ```yue | ||
| 1771 | hello = "world" | ||
| 1772 | a, b, c = 1, 2, 3 | ||
| 1773 | hello = 123 -- 访问现有的变量 | ||
| 1774 | ``` | ||
| 1775 | |||
| 1776 | </YueDisplay> | ||
| 1777 | |||
| 1778 | ## 执行更新 | ||
| 1779 | |||
| 1780 |   你可以使用各式二进制运算符执行更新赋值。 | ||
| 1781 | |||
| 1782 | ```yuescript | ||
| 1783 | x = 1 | ||
| 1784 | x += 1 | ||
| 1785 | x -= 1 | ||
| 1786 | x *= 10 | ||
| 1787 | x /= 10 | ||
| 1788 | x %= 10 | ||
| 1789 | s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量 | ||
| 1790 | arg or= "默认值" | ||
| 1791 | ``` | ||
| 1792 | |||
| 1793 | <YueDisplay> | ||
| 1794 | |||
| 1795 | ```yue | ||
| 1796 | x = 1 | ||
| 1797 | x += 1 | ||
| 1798 | x -= 1 | ||
| 1799 | x *= 10 | ||
| 1800 | x /= 10 | ||
| 1801 | x %= 10 | ||
| 1802 | s ..= "world" -- 如果执行更新的局部变量不存在,将新建一个局部变量 | ||
| 1803 | arg or= "默认值" | ||
| 1804 | ``` | ||
| 1805 | |||
| 1806 | </YueDisplay> | ||
| 1807 | |||
| 1808 | ## 链式赋值 | ||
| 1809 | |||
| 1810 |   你可以进行链式赋值,将多个项目赋予相同的值。 | ||
| 1811 | |||
| 1812 | ```yuescript | ||
| 1813 | a = b = c = d = e = 0 | ||
| 1814 | x = y = z = f! | ||
| 1815 | ``` | ||
| 1816 | |||
| 1817 | <YueDisplay> | ||
| 1818 | |||
| 1819 | ```yue | ||
| 1820 | a = b = c = d = e = 0 | ||
| 1821 | x = y = z = f! | ||
| 1822 | ``` | ||
| 1823 | |||
| 1824 | </YueDisplay> | ||
| 1825 | |||
| 1826 | ## 显式声明局部变量 | ||
| 1827 | |||
| 1828 | ```yuescript | ||
| 1829 | do | ||
| 1830 | local a = 1 | ||
| 1831 | local * | ||
| 1832 | print "预先声明后续所有变量为局部变量" | ||
| 1833 | x = -> 1 + y + z | ||
| 1834 | y, z = 2, 3 | ||
| 1835 | global instance = Item\new! | ||
| 1836 | |||
| 1837 | do | ||
| 1838 | local X = 1 | ||
| 1839 | local ^ | ||
| 1840 | print "只预先声明后续大写的变量为局部变量" | ||
| 1841 | a = 1 | ||
| 1842 | B = 2 | ||
| 1843 | ``` | ||
| 1844 | |||
| 1845 | <YueDisplay> | ||
| 1846 | |||
| 1847 | ```yue | ||
| 1848 | do | ||
| 1849 | local a = 1 | ||
| 1850 | local * | ||
| 1851 | print "预先声明后续所有变量为局部变量" | ||
| 1852 | x = -> 1 + y + z | ||
| 1853 | y, z = 2, 3 | ||
| 1854 | global instance = Item\new! | ||
| 1855 | |||
| 1856 | do | ||
| 1857 | local X = 1 | ||
| 1858 | local ^ | ||
| 1859 | print "只预先声明后续大写的变量为局部变量" | ||
| 1860 | a = 1 | ||
| 1861 | B = 2 | ||
| 1862 | ``` | ||
| 1863 | |||
| 1864 | </YueDisplay> | ||
| 1865 | |||
| 1866 | ## 显式声明全局变量 | ||
| 1867 | |||
| 1868 | ```yuescript | ||
| 1869 | do | ||
| 1870 | global a = 1 | ||
| 1871 | global * | ||
| 1872 | print "预先声明所有变量为全局变量" | ||
| 1873 | x = -> 1 + y + z | ||
| 1874 | y, z = 2, 3 | ||
| 1875 | |||
| 1876 | do | ||
| 1877 | global x = 1 | ||
| 1878 | global ^ | ||
| 1879 | print "只预先声明大写的变量为全局变量" | ||
| 1880 | a = 1 | ||
| 1881 | B = 2 | ||
| 1882 | local Temp = "一个局部值" | ||
| 1883 | ``` | ||
| 1884 | |||
| 1885 | <YueDisplay> | ||
| 1886 | |||
| 1887 | ```yue | ||
| 1888 | do | ||
| 1889 | global a = 1 | ||
| 1890 | global * | ||
| 1891 | print "预先声明所有变量为全局变量" | ||
| 1892 | x = -> 1 + y + z | ||
| 1893 | y, z = 2, 3 | ||
| 1894 | |||
| 1895 | do | ||
| 1896 | global x = 1 | ||
| 1897 | global ^ | ||
| 1898 | print "只预先声明大写的变量为全局变量" | ||
| 1899 | a = 1 | ||
| 1900 | B = 2 | ||
| 1901 | local Temp = "一个局部值" | ||
| 1902 | ``` | ||
| 1903 | |||
| 1904 | </YueDisplay> | ||
| 1905 | |||
| 1906 | # 可变参数赋值 | ||
| 1907 | |||
| 1908 |   你可以将函数返回的结果赋值给一个可变参数符号 `...`。然后使用 Lua 的方式访问其内容。 | ||
| 1909 | |||
| 1910 | ```yuescript | ||
| 1911 | list = [1, 2, 3, 4, 5] | ||
| 1912 | fn = (ok) -> ok, table.unpack list | ||
| 1913 | ok, ... = fn true | ||
| 1914 | count = select '#', ... | ||
| 1915 | first = select 1, ... | ||
| 1916 | print ok, count, first | ||
| 1917 | ``` | ||
| 1918 | |||
| 1919 | <YueDisplay> | ||
| 1920 | |||
| 1921 | ```yue | ||
| 1922 | list = [1, 2, 3, 4, 5] | ||
| 1923 | fn = (ok) -> ok, table.unpack list | ||
| 1924 | ok, ... = fn true | ||
| 1925 | count = select '#', ... | ||
| 1926 | first = select 1, ... | ||
| 1927 | print ok, count, first | ||
| 1928 | ``` | ||
| 1929 | |||
| 1930 | </YueDisplay> | ||
| 1931 | |||
| 1932 | # If 赋值 | ||
| 1933 | |||
| 1934 |   `if` 和 `elseif` 代码块可以在条件表达式的位置进行赋值。在代码执行到要计算条件时,会首先进行赋值计算,并使用赋与的值作为分支判断的条件。赋值的变量仅在条件分支的代码块内有效,这意味着如果值不是真值,那么它就不会被用到。注意,你必须使用“海象运算符” `:=` 而不是 `=` 来做赋值。 | ||
| 1935 | |||
| 1936 | ```yuescript | ||
| 1937 | if user := database.find_user "moon" | ||
| 1938 | print user.name | ||
| 1939 | ``` | ||
| 1940 | |||
| 1941 | <YueDisplay> | ||
| 1942 | |||
| 1943 | ```yue | ||
| 1944 | if user := database.find_user "moon" | ||
| 1945 | print user.name | ||
| 1946 | ``` | ||
| 1947 | |||
| 1948 | </YueDisplay> | ||
| 1949 | |||
| 1950 | ```yuescript | ||
| 1951 | if hello := os.getenv "hello" | ||
| 1952 | print "你有 hello", hello | ||
| 1953 | elseif world := os.getenv "world" | ||
| 1954 | print "你有 world", world | ||
| 1955 | else | ||
| 1956 | print "什么都没有 :(" | ||
| 1957 | ``` | ||
| 1958 | |||
| 1959 | <YueDisplay> | ||
| 1960 | |||
| 1961 | ```yue | ||
| 1962 | if hello := os.getenv "hello" | ||
| 1963 | print "你有 hello", hello | ||
| 1964 | elseif world := os.getenv "world" | ||
| 1965 | print "你有 world", world | ||
| 1966 | else | ||
| 1967 | print "什么都没有 :(" | ||
| 1968 | ``` | ||
| 1969 | |||
| 1970 | </YueDisplay> | ||
| 1971 | |||
| 1972 |   使用多个返回值的 If 赋值。只有第一个值会被检查,其他值都有同样的作用域。 | ||
| 1973 | |||
| 1974 | ```yuescript | ||
| 1975 | if success, result := pcall -> "无报错地获取结果" | ||
| 1976 | print result -- 变量 result 是有作用域的 | ||
| 1977 | print "好的" | ||
| 1978 | ``` | ||
| 1979 | |||
| 1980 | <YueDisplay> | ||
| 1981 | |||
| 1982 | ```yue | ||
| 1983 | if success, result := pcall -> "无报错地获取结果" | ||
| 1984 | print result -- 变量 result 是有作用域的 | ||
| 1985 | print "好的" | ||
| 1986 | ``` | ||
| 1987 | |||
| 1988 | </YueDisplay> | ||
| 1989 | |||
| 1990 | ## While 赋值 | ||
| 1991 | |||
| 1992 |   你可以在 while 循环中同样使用赋值来获取循环条件的值。 | ||
| 1993 | |||
| 1994 | ```yuescript | ||
| 1995 | while byte := stream\read_one! | ||
| 1996 | -- 对 byte 做一些操作 | ||
| 1997 | print byte | ||
| 1998 | ``` | ||
| 1999 | |||
| 2000 | <YueDisplay> | ||
| 2001 | |||
| 2002 | ```yue | ||
| 2003 | while byte := stream\read_one! | ||
| 2004 | -- 对 byte 做一些操作 | ||
| 2005 | print byte | ||
| 2006 | ``` | ||
| 2007 | |||
| 2008 | </YueDisplay> | ||
| 2009 | |||
| 2010 | # 解构赋值 | ||
| 2011 | |||
| 2012 |   解构赋值是一种快速从 Lua 表中按名称或基于数组中的位置提取值的方法。 | ||
| 2013 | |||
| 2014 |   通常当你看到一个字面量的 Lua 表,比如 `{1,2,3}`,它位于赋值的右侧,因为它是一个值。解构赋值语句的写法就是交换了字面量 Lua 表的角色,并将其放在赋值语句的左侧。 | ||
| 2015 | |||
| 2016 |   最好是通过示例来解释。以下是如何从表格中解包前两个值的方法: | ||
| 2017 | |||
| 2018 | ```yuescript | ||
| 2019 | thing = [1, 2] | ||
| 2020 | |||
| 2021 | [a, b] = thing | ||
| 2022 | print a, b | ||
| 2023 | ``` | ||
| 2024 | |||
| 2025 | <YueDisplay> | ||
| 2026 | |||
| 2027 | ```yue | ||
| 2028 | thing = [1, 2] | ||
| 2029 | |||
| 2030 | [a, b] = thing | ||
| 2031 | print a, b | ||
| 2032 | ``` | ||
| 2033 | |||
| 2034 | </YueDisplay> | ||
| 2035 | |||
| 2036 |   在解构表格字面量中,键代表从右侧读取的键,值代表读取的值将被赋予的名称。 | ||
| 2037 | |||
| 2038 | ```yuescript | ||
| 2039 | obj = { | ||
| 2040 | hello: "world" | ||
| 2041 | day: "tuesday" | ||
| 2042 | length: 20 | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | {hello: hello, day: the_day} = obj | ||
| 2046 | print hello, the_day | ||
| 2047 | |||
| 2048 | :day = obj -- 可以不带大括号进行简单的解构 | ||
| 2049 | ``` | ||
| 2050 | |||
| 2051 | <YueDisplay> | ||
| 2052 | |||
| 2053 | ```yue | ||
| 2054 | obj = { | ||
| 2055 | hello: "world" | ||
| 2056 | day: "tuesday" | ||
| 2057 | length: 20 | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | {hello: hello, day: the_day} = obj | ||
| 2061 | print hello, the_day | ||
| 2062 | |||
| 2063 | :day = obj -- 可以不带大括号进行简单的解构 | ||
| 2064 | ``` | ||
| 2065 | |||
| 2066 | </YueDisplay> | ||
| 2067 | |||
| 2068 |   这也适用于嵌套的数据结构: | ||
| 2069 | |||
| 2070 | ```yuescript | ||
| 2071 | obj2 = { | ||
| 2072 | numbers: [1,2,3,4] | ||
| 2073 | properties: { | ||
| 2074 | color: "green" | ||
| 2075 | height: 13.5 | ||
| 2076 | } | ||
| 2077 | } | ||
| 2078 | |||
| 2079 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2080 | print first, second, color | ||
| 2081 | ``` | ||
| 2082 | |||
| 2083 | <YueDisplay> | ||
| 2084 | |||
| 2085 | ```yue | ||
| 2086 | obj2 = { | ||
| 2087 | numbers: [1,2,3,4] | ||
| 2088 | properties: { | ||
| 2089 | color: "green" | ||
| 2090 | height: 13.5 | ||
| 2091 | } | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | {numbers: [first, second], properties: {color: color}} = obj2 | ||
| 2095 | print first, second, color | ||
| 2096 | ``` | ||
| 2097 | |||
| 2098 | </YueDisplay> | ||
| 2099 | |||
| 2100 |   如果解构语句很复杂,也可以任意将其分散在几行中。稍微复杂一些的示例: | ||
| 2101 | |||
| 2102 | ```yuescript | ||
| 2103 | { | ||
| 2104 | numbers: [first, second] | ||
| 2105 | properties: { | ||
| 2106 | color: color | ||
| 2107 | } | ||
| 2108 | } = obj2 | ||
| 2109 | ``` | ||
| 2110 | |||
| 2111 | <YueDisplay> | ||
| 2112 | |||
| 2113 | ```yue | ||
| 2114 | { | ||
| 2115 | numbers: [first, second] | ||
| 2116 | properties: { | ||
| 2117 | color: color | ||
| 2118 | } | ||
| 2119 | } = obj2 | ||
| 2120 | ``` | ||
| 2121 | |||
| 2122 | </YueDisplay> | ||
| 2123 | |||
| 2124 |   有时候我们会需要从 Lua 表中提取值并将它们赋给与键同名的局部变量。为了避免编写重复代码,我们可以使用 **:** 前缀操作符: | ||
| 2125 | |||
| 2126 | ```yuescript | ||
| 2127 | {:concat, :insert} = table | ||
| 2128 | ``` | ||
| 2129 | |||
| 2130 | <YueDisplay> | ||
| 2131 | |||
| 2132 | ```yue | ||
| 2133 | {:concat, :insert} = table | ||
| 2134 | ``` | ||
| 2135 | |||
| 2136 | </YueDisplay> | ||
| 2137 | |||
| 2138 |   这样的用法与导入语法有些相似。但我们可以通过混合语法重命名我们想要提取的字段: | ||
| 2139 | |||
| 2140 | ```yuescript | ||
| 2141 | {:mix, :max, random: rand} = math | ||
| 2142 | ``` | ||
| 2143 | |||
| 2144 | <YueDisplay> | ||
| 2145 | |||
| 2146 | ```yue | ||
| 2147 | {:mix, :max, random: rand} = math | ||
| 2148 | ``` | ||
| 2149 | |||
| 2150 | </YueDisplay> | ||
| 2151 | |||
| 2152 |   在进行解构时,你可以指定默认值,如: | ||
| 2153 | |||
| 2154 | ```yuescript | ||
| 2155 | {:name = "nameless", :job = "jobless"} = person | ||
| 2156 | ``` | ||
| 2157 | |||
| 2158 | <YueDisplay> | ||
| 2159 | |||
| 2160 | ```yue | ||
| 2161 | {:name = "nameless", :job = "jobless"} = person | ||
| 2162 | ``` | ||
| 2163 | |||
| 2164 | </YueDisplay> | ||
| 2165 | |||
| 2166 |   在进行列表解构时,你可以使用`_`作为占位符: | ||
| 2167 | |||
| 2168 | ```yuescript | ||
| 2169 | [_, two, _, four] = items | ||
| 2170 | ``` | ||
| 2171 | |||
| 2172 | <YueDisplay> | ||
| 2173 | |||
| 2174 | ```yue | ||
| 2175 | [_, two, _, four] = items | ||
| 2176 | ``` | ||
| 2177 | |||
| 2178 | </YueDisplay> | ||
| 2179 | |||
| 2180 | ## 范围解构 | ||
| 2181 | |||
| 2182 |   你可以使用展开运算符 `...` 在列表解构中来捕获一个范围的值到子列表中。这在当你想要从列表的开头和结尾提取特定元素,同时收集中间的元素时非常有用。 | ||
| 2183 | |||
| 2184 | ```yuescript | ||
| 2185 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2186 | [first, ...bulk, last] = orders | ||
| 2187 | print first -- 打印: first | ||
| 2188 | print bulk -- 打印: {"second", "third", "fourth"} | ||
| 2189 | print last -- 打印: last | ||
| 2190 | ``` | ||
| 2191 | |||
| 2192 | <YueDisplay> | ||
| 2193 | |||
| 2194 | ```yue | ||
| 2195 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 2196 | [first, ...bulk, last] = orders | ||
| 2197 | print first -- 打印: first | ||
| 2198 | print bulk -- 打印: {"second", "third", "fourth"} | ||
| 2199 | print last -- 打印: last | ||
| 2200 | ``` | ||
| 2201 | |||
| 2202 | </YueDisplay> | ||
| 2203 | |||
| 2204 |   展开运算符可以用在不同的位置来捕获不同的范围,并且你可以使用 `_` 作为占位符来表示你想跳过对应范围的捕获: | ||
| 2205 | |||
| 2206 | ```yuescript | ||
| 2207 | -- 捕获第一个元素之后的所有元素 | ||
| 2208 | [first, ...rest] = orders | ||
| 2209 | |||
| 2210 | -- 捕获最后一个元素之前的所有元素 | ||
| 2211 | [...start, last] = orders | ||
| 2212 | |||
| 2213 | -- 跳过中间的元素,只捕获第一个和最后一个元素 | ||
| 2214 | [first, ..._, last] = orders | ||
| 2215 | ``` | ||
| 2216 | |||
| 2217 | <YueDisplay> | ||
| 2218 | |||
| 2219 | ```yue | ||
| 2220 | -- 捕获第一个元素之后的所有元素 | ||
| 2221 | [first, ...rest] = orders | ||
| 2222 | |||
| 2223 | -- 捕获最后一个元素之前的所有元素 | ||
| 2224 | [...start, last] = orders | ||
| 2225 | |||
| 2226 | -- 跳过中间的元素,只捕获第一个和最后一个元素 | ||
| 2227 | [first, ..._, last] = orders | ||
| 2228 | ``` | ||
| 2229 | |||
| 2230 | </YueDisplay> | ||
| 2231 | |||
| 2232 | ## 在其它地方的解构赋值 | ||
| 2233 | |||
| 2234 |   解构赋值也可以出现在其它隐式进行赋值的地方。一个例子是用在 for 循环中: | ||
| 2235 | |||
| 2236 | ```yuescript | ||
| 2237 | tuples = [ | ||
| 2238 | ["hello", "world"] | ||
| 2239 | ["egg", "head"] | ||
| 2240 | ] | ||
| 2241 | |||
| 2242 | for [left, right] in *tuples | ||
| 2243 | print left, right | ||
| 2244 | ``` | ||
| 2245 | |||
| 2246 | <YueDisplay> | ||
| 2247 | |||
| 2248 | ```yue | ||
| 2249 | tuples = [ | ||
| 2250 | ["hello", "world"] | ||
| 2251 | ["egg", "head"] | ||
| 2252 | ] | ||
| 2253 | |||
| 2254 | for [left, right] in *tuples | ||
| 2255 | print left, right | ||
| 2256 | ``` | ||
| 2257 | |||
| 2258 | </YueDisplay> | ||
| 2259 | |||
| 2260 |   我们知道数组表中的每个元素都是一个两项的元组,所以我们可以直接在 for 语句的名称子句中使用解构来解包它。 | ||
| 2261 | |||
| 2262 | # 使用 using 语句:防止破坏性赋值 | ||
| 2263 | |||
| 2264 |   Lua 的变量作用域是降低代码复杂度的重要工具。然而,随着代码量的增加,维护这些变量可能变得更加困难。比如,看看下面的代码片段: | ||
| 2265 | |||
| 2266 | ```yuescript | ||
| 2267 | i = 100 | ||
| 2268 | |||
| 2269 | -- 许多代码行... | ||
| 2270 | |||
| 2271 | my_func = -> | ||
| 2272 | i = 10 | ||
| 2273 | while i > 0 | ||
| 2274 | print i | ||
| 2275 | i -= 1 | ||
| 2276 | |||
| 2277 | my_func! | ||
| 2278 | |||
| 2279 | print i -- 将打印 0 | ||
| 2280 | ``` | ||
| 2281 | |||
| 2282 | <YueDisplay> | ||
| 2283 | |||
| 2284 | ```yue | ||
| 2285 | i = 100 | ||
| 2286 | |||
| 2287 | -- 许多代码行... | ||
| 2288 | |||
| 2289 | my_func = -> | ||
| 2290 | i = 10 | ||
| 2291 | while i > 0 | ||
| 2292 | print i | ||
| 2293 | i -= 1 | ||
| 2294 | |||
| 2295 | my_func! | ||
| 2296 | |||
| 2297 | print i -- 将打印 0 | ||
| 2298 | ``` | ||
| 2299 | |||
| 2300 | </YueDisplay> | ||
| 2301 | |||
| 2302 |   在 `my_func` 中,我们不小心覆盖了变量 `i` 的值。虽然在这个例子中这个问题很明显,但在一个庞大的或者是由多人共同维护的代码库中,很难追踪每个变量的声明情况。 | ||
| 2303 | |||
| 2304 |   如果我们可以明确指出哪些变量是我们想在当前作用域内修改的,并且防止我们不小心更改了其他作用域中同名的变量,那将大有裨益。 | ||
| 2305 | |||
| 2306 |   `using` 语句就是为此而生。`using nil` 确保函数内部的赋值不会意外地影响到外部作用域的变量。我们只需将 `using` 子句放在函数的参数列表之后;若函数没有参数,则直接放在括号内即可。 | ||
| 2307 | |||
| 2308 | ```yuescript | ||
| 2309 | i = 100 | ||
| 2310 | |||
| 2311 | my_func = (using nil) -> | ||
| 2312 | i = "hello" -- 这里创建了一个新的局部变量 | ||
| 2313 | |||
| 2314 | my_func! | ||
| 2315 | print i -- 打印 100,i 没有受到影响 | ||
| 2316 | ``` | ||
| 2317 | |||
| 2318 | <YueDisplay> | ||
| 2319 | |||
| 2320 | ```yue | ||
| 2321 | i = 100 | ||
| 2322 | |||
| 2323 | my_func = (using nil) -> | ||
| 2324 | i = "hello" -- 这里创建了一个新的局部变量 | ||
| 2325 | |||
| 2326 | my_func! | ||
| 2327 | print i -- 打印 100,i 没有受到影响 | ||
| 2328 | ``` | ||
| 2329 | |||
| 2330 | </YueDisplay> | ||
| 2331 | |||
| 2332 |   using子句中可以填写多个用逗号分隔名称。指定可以访问和修改的外部变量的名称: | ||
| 2333 | |||
| 2334 | ```yuescript | ||
| 2335 | tmp = 1213 | ||
| 2336 | i, k = 100, 50 | ||
| 2337 | |||
| 2338 | my_func = (add using k, i) -> | ||
| 2339 | tmp = tmp + add -- 创建了一个新的局部tmp | ||
| 2340 | i += tmp | ||
| 2341 | k += tmp | ||
| 2342 | |||
| 2343 | my_func(22) | ||
| 2344 | print i, k -- 这些已经被更新 | ||
| 2345 | ``` | ||
| 2346 | |||
| 2347 | <YueDisplay> | ||
| 2348 | |||
| 2349 | ```yue | ||
| 2350 | tmp = 1213 | ||
| 2351 | i, k = 100, 50 | ||
| 2352 | |||
| 2353 | my_func = (add using k, i) -> | ||
| 2354 | tmp = tmp + add -- 创建了一个新的局部tmp | ||
| 2355 | i += tmp | ||
| 2356 | k += tmp | ||
| 2357 | |||
| 2358 | my_func(22) | ||
| 2359 | print i, k -- 这些已经被更新 | ||
| 2360 | ``` | ||
| 2361 | |||
| 2362 | </YueDisplay> | ||
| 2363 | |||
| 2364 | # 使用方法 | ||
| 2365 | |||
| 2366 | ## Lua 模块 | ||
| 2367 | |||
| 2368 |   在 Lua 中使用月之脚本模块: | ||
| 2369 | |||
| 2370 | - **用法 1** | ||
| 2371 | |||
| 2372 |   在 Lua 中引入 "你的脚本入口文件.yue"。 | ||
| 2373 | |||
| 2374 | ```Lua | ||
| 2375 | require("yue")("你的脚本入口文件") | ||
| 2376 | ``` | ||
| 2377 | |||
| 2378 |   当你在同一路径下把 "你的脚本入口文件.yue" 编译成了 "你的脚本入口文件.lua" 时,仍然可以使用这个代码加载 .lua 代码文件。在其余的月之脚本文件中,只需正常使用 **require** 或 **import** 进行脚本引用即可。错误消息中的代码行号也会被正确处理。 | ||
| 2379 | |||
| 2380 | - **用法 2** | ||
| 2381 | |||
| 2382 |   手动引入月之脚本模块并重写错误消息来帮助调试。 | ||
| 2383 | |||
| 2384 | ```lua | ||
| 2385 | local yue = require("yue") | ||
| 2386 | yue.insert_loaders() | ||
| 2387 | local success, result = xpcall(function() | ||
| 2388 | return require("yuescript_module_name") | ||
| 2389 | end, function(err) | ||
| 2390 | return yue.traceback(err) | ||
| 2391 | end) | ||
| 2392 | ``` | ||
| 2393 | |||
| 2394 | - **用法 3** | ||
| 2395 | |||
| 2396 |   在 Lua 中使用月之脚本编译器功能。 | ||
| 2397 | |||
| 2398 | ```lua | ||
| 2399 | local yue = require("yue") | ||
| 2400 | local codes, err, globals = yue.to_lua([[ | ||
| 2401 | f = -> | ||
| 2402 | print "hello world" | ||
| 2403 | f! | ||
| 2404 | ]],{ | ||
| 2405 | implicit_return_root = true, | ||
| 2406 | reserve_line_number = true, | ||
| 2407 | lint_global = true, | ||
| 2408 | space_over_tab = false, | ||
| 2409 | options = { | ||
| 2410 | target = "5.4", | ||
| 2411 | path = "/script" | ||
| 2412 | } | ||
| 2413 | }) | ||
| 2414 | ``` | ||
| 2415 | |||
| 2416 | ## 月之脚本编译工具 | ||
| 2417 | |||
| 2418 |   使用月之脚本编译工具: | ||
| 2419 | |||
| 2420 | ```shell | ||
| 2421 | > yue -h | ||
| 2422 | 命令行用法: yue | ||
| 2423 | [选项] [<文件/目录>] ... | ||
| 2424 | yue -e <代码或文件> [参数...] | ||
| 2425 | yue -w [<目录>] [选项] | ||
| 2426 | yue - | ||
| 2427 | |||
| 2428 | 说明: | ||
| 2429 | - '-' 或 '--' 必须作为唯一且第一个参数,用于读取标准输入。 | ||
| 2430 | - '-o/--output' 不能与多个输入文件一起使用。 | ||
| 2431 | - '-w/--watch' 仅能用于目录,不能用于单个文件。 | ||
| 2432 | - 使用 '-e/--execute' 时,后续的参数将作为脚本参数传递。 | ||
| 2433 | |||
| 2434 | 选项: | ||
| 2435 | -h, --help 显示帮助信息并退出 | ||
| 2436 | -e <字符串>, --execute <字符串> 执行文件或原始代码 | ||
| 2437 | -m, --minify 生成压缩(最小化)代码 | ||
| 2438 | -r, --rewrite 重写输出以匹配原始代码行号 | ||
| 2439 | -t <目标路径>, --output-to <目标路径> | ||
| 2440 | 指定编译后文件的输出路径 | ||
| 2441 | -o <文件>, --output <文件> 将输出写入文件 | ||
| 2442 | -p, --print 输出到标准输出 | ||
| 2443 | -b, --benchmark 输出编译耗时(不写入文件) | ||
| 2444 | -g, --globals 显示用到的全局变量及其所在的名称、行号、列号 | ||
| 2445 | -s, --spaces 用空格代替制表符(tab)输出代码 | ||
| 2446 | -l, --line-numbers 输出源代码的行号 | ||
| 2447 | -j, --no-implicit-return 禁用文件末尾的隐式返回 | ||
| 2448 | -c, --reserve-comments 保留源代码中的注释 | ||
| 2449 | -w [<目录>], --watch [<目录>] | ||
| 2450 | 监视目录变化并自动编译 | ||
| 2451 | -v, --version 显示版本信息 | ||
| 2452 | - 从标准输入读取,输出到标准输出(仅能作为唯一参数) | ||
| 2453 | -- 等同于 '-',为兼容旧版本保留 | ||
| 2454 | |||
| 2455 | --target <版本> 指定生成代码的 Lua 版本 (只能为 5.1 ~ 5.5) | ||
| 2456 | --path <路径字符串> 附加一个 Lua 搜索路径到 package.path | ||
| 2457 | --<键>=<值> 以 key=value 形式传递编译器选项(保持已有用法) | ||
| 2458 | |||
| 2459 | 不带选项直接运行可进入交互模式(REPL),在交互模式里输入单独的符号 '$' | ||
| 2460 | 可用于开始或结束多行模式。 | ||
| 2461 | ``` | ||
| 2462 | |||
| 2463 |   使用案例: | ||
| 2464 | |||
| 2465 |   递归编译当前路径下扩展名为 **.yue** 的每个月之脚本文件: **yue .** | ||
| 2466 | |||
| 2467 |   编译并将结果保存到目标路径: **yue -t /target/path/ .** | ||
| 2468 | |||
| 2469 |   编译并保留调试信息: **yue -l .** | ||
| 2470 | |||
| 2471 |   编译并生成压缩代码: **yue -m .** | ||
| 2472 | |||
| 2473 |   直接执行代码: **yue -e 'print 123'** | ||
| 2474 | |||
| 2475 |   执行一个月之脚本文件: **yue -e main.yue** | ||
| 2476 | |||
| 2477 | # 介绍 | ||
| 2478 | |||
| 2479 | 月之脚本(YueScript)是一种动态语言,可以编译为 Lua。它是 [MoonScript](https://github.com/leafo/moonscript) 的方言。用月之脚本编写的代码既有表现力又非常简洁。它适合编写一些更易于维护的代码,并在嵌入 Lua 的环境中运行,如游戏或网站服务器。 | ||
| 2480 | |||
| 2481 | Yue(月)是中文中“月亮”的名称。 | ||
| 2482 | |||
| 2483 | ## 月之脚本概览 | ||
| 2484 | |||
| 2485 | ```yuescript | ||
| 2486 | -- 导入语法 | ||
| 2487 | import p, to_lua from "yue" | ||
| 2488 | |||
| 2489 | -- 隐式对象 | ||
| 2490 | inventory = | ||
| 2491 | equipment: | ||
| 2492 | - "sword" | ||
| 2493 | - "shield" | ||
| 2494 | items: | ||
| 2495 | - name: "potion" | ||
| 2496 | count: 10 | ||
| 2497 | - name: "bread" | ||
| 2498 | count: 3 | ||
| 2499 | |||
| 2500 | -- 列表推导 | ||
| 2501 | map = (arr, action) -> | ||
| 2502 | [action item for item in *arr] | ||
| 2503 | |||
| 2504 | filter = (arr, cond) -> | ||
| 2505 | [item for item in *arr when cond item] | ||
| 2506 | |||
| 2507 | reduce = (arr, init, action): init -> | ||
| 2508 | init = action init, item for item in *arr | ||
| 2509 | |||
| 2510 | -- 管道操作符 | ||
| 2511 | [1, 2, 3] | ||
| 2512 | |> map (x) -> x * 2 | ||
| 2513 | |> filter (x) -> x > 4 | ||
| 2514 | |> reduce 0, (a, b) -> a + b | ||
| 2515 | |||
| 2516 | |||
| 2517 | -- 元表操作 | ||
| 2518 | apple = | ||
| 2519 | size: 15 | ||
| 2520 | <index>: | ||
| 2521 | color: 0x00ffff | ||
| 2522 | |||
| 2523 | with apple | ||
| 2524 | p .size, .color, .<index> if .<>? | ||
| 2525 | |||
| 2526 | -- 类似js的导出语法 | ||
| 2527 | export 🌛 = "月之脚本" | ||
| 2528 | ``` | ||
| 2529 | |||
| 2530 | <YueDisplay> | ||
| 2531 | |||
| 2532 | ```yue | ||
| 2533 | -- 导入语法 | ||
| 2534 | import p, to_lua from "yue" | ||
| 2535 | |||
| 2536 | -- 隐式对象 | ||
| 2537 | inventory = | ||
| 2538 | equipment: | ||
| 2539 | - "sword" | ||
| 2540 | - "shield" | ||
| 2541 | items: | ||
| 2542 | - name: "potion" | ||
| 2543 | count: 10 | ||
| 2544 | - name: "bread" | ||
| 2545 | count: 3 | ||
| 2546 | |||
| 2547 | -- 列表推导 | ||
| 2548 | map = (arr, action) -> | ||
| 2549 | [action item for item in *arr] | ||
| 2550 | |||
| 2551 | filter = (arr, cond) -> | ||
| 2552 | [item for item in *arr when cond item] | ||
| 2553 | |||
| 2554 | reduce = (arr, init, action): init -> | ||
| 2555 | init = action init, item for item in *arr | ||
| 2556 | |||
| 2557 | -- 管道操作符 | ||
| 2558 | [1, 2, 3] | ||
| 2559 | |> map (x) -> x * 2 | ||
| 2560 | |> filter (x) -> x > 4 | ||
| 2561 | |> reduce 0, (a, b) -> a + b | ||
| 2562 | |||
| 2563 | |||
| 2564 | -- 元表操作 | ||
| 2565 | apple = | ||
| 2566 | size: 15 | ||
| 2567 | <index>: | ||
| 2568 | color: 0x00ffff | ||
| 2569 | |||
| 2570 | with apple | ||
| 2571 | p .size, .color, .<index> if .<>? | ||
| 2572 | |||
| 2573 | -- 类似js的导出语法 | ||
| 2574 | export 🌛 = "月之脚本" | ||
| 2575 | ``` | ||
| 2576 | |||
| 2577 | </YueDisplay> | ||
| 2578 | |||
| 2579 | ## 关于 Dora SSR | ||
| 2580 | |||
| 2581 | 月之脚本是与开源游戏引擎 [Dora SSR](https://github.com/Dora-SSR/Dora-SSR) 一起开发和维护的。它已被用于创建引擎工具、游戏原型和演示,在实际的游戏项目中验证其能力,同时它也帮助增强了 Dora SSR 游戏引擎的开发体验。 | ||
| 2582 | |||
| 2583 | # 安装 | ||
| 2584 | |||
| 2585 | ## Lua 模块 | ||
| 2586 | |||
| 2587 |  安装 [luarocks](https://luarocks.org),一个 Lua 模块的包管理器。然后作为 Lua 模块和可执行文件安装它: | ||
| 2588 | |||
| 2589 | ```shell | ||
| 2590 | luarocks install yuescript | ||
| 2591 | ``` | ||
| 2592 | |||
| 2593 |  或者你可以自己构建 `yue.so` 文件: | ||
| 2594 | |||
| 2595 | ```shell | ||
| 2596 | make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua | ||
| 2597 | ``` | ||
| 2598 | |||
| 2599 |  然后从路径 **bin/shared/yue.so** 获取二进制文件。 | ||
| 2600 | |||
| 2601 | ## 构建二进制工具 | ||
| 2602 | |||
| 2603 |  克隆项目仓库,然后构建并安装可执行文件: | ||
| 2604 | |||
| 2605 | ```shell | ||
| 2606 | make install | ||
| 2607 | ``` | ||
| 2608 | |||
| 2609 |  构建不带宏功能的月之脚本编译工具: | ||
| 2610 | |||
| 2611 | ```shell | ||
| 2612 | make install NO_MACRO=true | ||
| 2613 | ``` | ||
| 2614 | |||
| 2615 |  构建不带内置Lua二进制文件的月之脚本编译工具: | ||
| 2616 | |||
| 2617 | ```shell | ||
| 2618 | make install NO_LUA=true | ||
| 2619 | ``` | ||
| 2620 | |||
| 2621 | ## 下载预编译的二进制程序 | ||
| 2622 | |||
| 2623 |  你可以下载预编译的二进制程序,包括兼容不同 Lua 版本的二进制可执行文件和库文件。 | ||
| 2624 | |||
| 2625 |  在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程序。 | ||
| 2626 | |||
| 2627 | # 条件语句 | ||
| 2628 | |||
| 2629 | ```yuescript | ||
| 2630 | have_coins = false | ||
| 2631 | if have_coins | ||
| 2632 | print "有硬币" | ||
| 2633 | else | ||
| 2634 | print "没有硬币" | ||
| 2635 | ``` | ||
| 2636 | |||
| 2637 | <YueDisplay> | ||
| 2638 | |||
| 2639 | ```yue | ||
| 2640 | have_coins = false | ||
| 2641 | if have_coins | ||
| 2642 | print "有硬币" | ||
| 2643 | else | ||
| 2644 | print "没有硬币" | ||
| 2645 | ``` | ||
| 2646 | |||
| 2647 | </YueDisplay> | ||
| 2648 | |||
| 2649 |   对于简单的语句,也可以使用简短的语法: | ||
| 2650 | |||
| 2651 | ```yuescript | ||
| 2652 | have_coins = false | ||
| 2653 | if have_coins then print "有硬币" else print "没有硬币" | ||
| 2654 | ``` | ||
| 2655 | |||
| 2656 | <YueDisplay> | ||
| 2657 | |||
| 2658 | ```yue | ||
| 2659 | have_coins = false | ||
| 2660 | if have_coins then print "有硬币" else print "没有硬币" | ||
| 2661 | ``` | ||
| 2662 | |||
| 2663 | </YueDisplay> | ||
| 2664 | |||
| 2665 |   因为 if 语句可以用作表达式,所以也可以这样写: | ||
| 2666 | |||
| 2667 | ```yuescript | ||
| 2668 | have_coins = false | ||
| 2669 | print if have_coins then "有硬币" else "没有硬币" | ||
| 2670 | ``` | ||
| 2671 | |||
| 2672 | <YueDisplay> | ||
| 2673 | |||
| 2674 | ```yue | ||
| 2675 | have_coins = false | ||
| 2676 | print if have_coins then "有硬币" else "没有硬币" | ||
| 2677 | ``` | ||
| 2678 | |||
| 2679 | </YueDisplay> | ||
| 2680 | |||
| 2681 |   条件语句也可以作为表达式用在返回语句和赋值语句中: | ||
| 2682 | |||
| 2683 | ```yuescript | ||
| 2684 | is_tall = (name) -> | ||
| 2685 | if name == "Rob" | ||
| 2686 | true | ||
| 2687 | else | ||
| 2688 | false | ||
| 2689 | |||
| 2690 | message = if is_tall "Rob" | ||
| 2691 | "我很高" | ||
| 2692 | else | ||
| 2693 | "我不是很高" | ||
| 2694 | |||
| 2695 | print message -- 打印: 我很高 | ||
| 2696 | ``` | ||
| 2697 | |||
| 2698 | <YueDisplay> | ||
| 2699 | |||
| 2700 | ```yue | ||
| 2701 | is_tall = (name) -> | ||
| 2702 | if name == "Rob" | ||
| 2703 | true | ||
| 2704 | else | ||
| 2705 | false | ||
| 2706 | |||
| 2707 | message = if is_tall "Rob" | ||
| 2708 | "我很高" | ||
| 2709 | else | ||
| 2710 | "我不是很高" | ||
| 2711 | |||
| 2712 | print message -- 打印: 我很高 | ||
| 2713 | ``` | ||
| 2714 | |||
| 2715 | </YueDisplay> | ||
| 2716 | |||
| 2717 |   if 的反义词是 unless(相当于 if not,正如“如果”对应“除非”): | ||
| 2718 | |||
| 2719 | ```yuescript | ||
| 2720 | unless os.date("%A") == "Monday" | ||
| 2721 | print "今天不是星期一!" | ||
| 2722 | ``` | ||
| 2723 | |||
| 2724 | <YueDisplay> | ||
| 2725 | |||
| 2726 | ```yue | ||
| 2727 | unless os.date("%A") == "Monday" | ||
| 2728 | print "今天不是星期一!" | ||
| 2729 | ``` | ||
| 2730 | |||
| 2731 | </YueDisplay> | ||
| 2732 | |||
| 2733 | ```yuescript | ||
| 2734 | print "你真幸运!" unless math.random! > 0.1 | ||
| 2735 | ``` | ||
| 2736 | |||
| 2737 | <YueDisplay> | ||
| 2738 | |||
| 2739 | ```yue | ||
| 2740 | print "你真幸运!" unless math.random! > 0.1 | ||
| 2741 | ``` | ||
| 2742 | |||
| 2743 | </YueDisplay> | ||
| 2744 | |||
| 2745 | ## 范围表达式 | ||
| 2746 | |||
| 2747 |   你可以使用范围表达式来编写进行范围检查的代码。 | ||
| 2748 | |||
| 2749 | ```yuescript | ||
| 2750 | a = 5 | ||
| 2751 | |||
| 2752 | if a in [1, 3, 5, 7] | ||
| 2753 | print "检查离散值的相等性" | ||
| 2754 | |||
| 2755 | if a in list | ||
| 2756 | print "检查`a`是否在列表中" | ||
| 2757 | ``` | ||
| 2758 | |||
| 2759 | <YueDisplay> | ||
| 2760 | |||
| 2761 | ```yue | ||
| 2762 | a = 5 | ||
| 2763 | |||
| 2764 | if a in [1, 3, 5, 7] | ||
| 2765 | print "检查离散值的相等性" | ||
| 2766 | |||
| 2767 | if a in list | ||
| 2768 | print "检查`a`是否在列表中" | ||
| 2769 | ``` | ||
| 2770 | |||
| 2771 | </YueDisplay> | ||
| 2772 | |||
| 2773 | # for 循环 | ||
| 2774 | |||
| 2775 |   Lua 中有两种 for 循环形式,数字型和通用型: | ||
| 2776 | |||
| 2777 | ```yuescript | ||
| 2778 | for i = 10, 20 | ||
| 2779 | print i | ||
| 2780 | |||
| 2781 | for k = 1, 15, 2 -- 提供了一个遍历的步长 | ||
| 2782 | print k | ||
| 2783 | |||
| 2784 | for key, value in pairs object | ||
| 2785 | print key, value | ||
| 2786 | ``` | ||
| 2787 | |||
| 2788 | <YueDisplay> | ||
| 2789 | |||
| 2790 | ```yue | ||
| 2791 | for i = 10, 20 | ||
| 2792 | print i | ||
| 2793 | |||
| 2794 | for k = 1, 15, 2 -- 提供了一个遍历的步长 | ||
| 2795 | print k | ||
| 2796 | |||
| 2797 | for key, value in pairs object | ||
| 2798 | print key, value | ||
| 2799 | ``` | ||
| 2800 | |||
| 2801 | </YueDisplay> | ||
| 2802 | |||
| 2803 |   可以使用切片和 **\*** 操作符,就像在列表推导中一样: | ||
| 2804 | |||
| 2805 | ```yuescript | ||
| 2806 | for item in *items[2, 4] | ||
| 2807 | print item | ||
| 2808 | ``` | ||
| 2809 | |||
| 2810 | <YueDisplay> | ||
| 2811 | |||
| 2812 | ```yue | ||
| 2813 | for item in *items[2, 4] | ||
| 2814 | print item | ||
| 2815 | ``` | ||
| 2816 | |||
| 2817 | </YueDisplay> | ||
| 2818 | |||
| 2819 |   当代码语句只有一行时,循环语句也都可以写作更短的语法: | ||
| 2820 | |||
| 2821 | ```yuescript | ||
| 2822 | for item in *items do print item | ||
| 2823 | |||
| 2824 | for j = 1, 10, 3 do print j | ||
| 2825 | ``` | ||
| 2826 | |||
| 2827 | <YueDisplay> | ||
| 2828 | |||
| 2829 | ```yue | ||
| 2830 | for item in *items do print item | ||
| 2831 | |||
| 2832 | for j = 1, 10, 3 do print j | ||
| 2833 | ``` | ||
| 2834 | |||
| 2835 | </YueDisplay> | ||
| 2836 | |||
| 2837 |   for 循环也可以用作表达式。for 循环主体中的最后一条语句会被强制转换为一个返回值的表达式,并会将表达式计算结果的值追加到一个作为结果的数组表中。 | ||
| 2838 | |||
| 2839 |   将每个偶数加倍: | ||
| 2840 | |||
| 2841 | ```yuescript | ||
| 2842 | doubled_evens = for i = 1, 20 | ||
| 2843 | if i % 2 == 0 | ||
| 2844 | i * 2 | ||
| 2845 | else | ||
| 2846 | i | ||
| 2847 | ``` | ||
| 2848 | |||
| 2849 | <YueDisplay> | ||
| 2850 | |||
| 2851 | ```yue | ||
| 2852 | doubled_evens = for i = 1, 20 | ||
| 2853 | if i % 2 == 0 | ||
| 2854 | i * 2 | ||
| 2855 | else | ||
| 2856 | i | ||
| 2857 | ``` | ||
| 2858 | |||
| 2859 | </YueDisplay> | ||
| 2860 | |||
| 2861 |   此外,for 循环还支持带返回值的 break 语句,这样循环本身就可以作为一个表达式,在满足条件时提前退出并返回有意义的结果。for 循环表达式支持 `break` 返回多个值。 | ||
| 2862 | |||
| 2863 |   例如,查找第一个大于 10 的数字: | ||
| 2864 | |||
| 2865 | ```yuescript | ||
| 2866 | first_large = for n in *numbers | ||
| 2867 | break n if n > 10 | ||
| 2868 | ``` | ||
| 2869 | |||
| 2870 | <YueDisplay> | ||
| 2871 | |||
| 2872 | ```yue | ||
| 2873 | first_large = for n in *numbers | ||
| 2874 | break n if n > 10 | ||
| 2875 | ``` | ||
| 2876 | |||
| 2877 | </YueDisplay> | ||
| 2878 | |||
| 2879 | ```yuescript | ||
| 2880 | key, score = for k, v in pairs data | ||
| 2881 | break k, v * 10 if k == "target" | ||
| 2882 | ``` | ||
| 2883 | |||
| 2884 | <YueDisplay> | ||
| 2885 | |||
| 2886 | ```yue | ||
| 2887 | key, score = for k, v in pairs data | ||
| 2888 | break k, v * 10 if k == "target" | ||
| 2889 | ``` | ||
| 2890 | |||
| 2891 | </YueDisplay> | ||
| 2892 | |||
| 2893 |   你还可以结合 for 循环表达式与 continue 语句来过滤值。 | ||
| 2894 | |||
| 2895 |   注意出现在函数体末尾的 for 循环,不会被当作是一个表达式并将循环结果累积到一个列表中作为返回值(相反,函数将返回 nil)。如果要函数末尾的循环转换为列表表达式,可以显式地使用返回语句加 for 循环表达式。 | ||
| 2896 | |||
| 2897 | ```yuescript | ||
| 2898 | func_a = -> for i = 1, 10 do print i | ||
| 2899 | func_b = -> return for i = 1, 10 do i | ||
| 2900 | |||
| 2901 | print func_a! -- 打印 nil | ||
| 2902 | print func_b! -- 打印 table 对象 | ||
| 2903 | ``` | ||
| 2904 | |||
| 2905 | <YueDisplay> | ||
| 2906 | |||
| 2907 | ```yue | ||
| 2908 | func_a = -> for i = 1, 10 do print i | ||
| 2909 | func_b = -> return for i = 1, 10 do i | ||
| 2910 | |||
| 2911 | print func_a! -- 打印 nil | ||
| 2912 | print func_b! -- 打印 table 对象 | ||
| 2913 | ``` | ||
| 2914 | |||
| 2915 | </YueDisplay> | ||
| 2916 | |||
| 2917 |   这样做是为了避免在不需要返回循环结果的函数,创建无效的返回值表格。 | ||
| 2918 | |||
| 2919 | # continue 语句 | ||
| 2920 | |||
| 2921 |   继续语句可以用来跳出当前的循环迭代。 | ||
| 2922 | |||
| 2923 | ```yuescript | ||
| 2924 | i = 0 | ||
| 2925 | while i < 10 | ||
| 2926 | i += 1 | ||
| 2927 | continue if i % 2 == 0 | ||
| 2928 | print i | ||
| 2929 | ``` | ||
| 2930 | |||
| 2931 | <YueDisplay> | ||
| 2932 | |||
| 2933 | ```yue | ||
| 2934 | i = 0 | ||
| 2935 | while i < 10 | ||
| 2936 | i += 1 | ||
| 2937 | continue if i % 2 == 0 | ||
| 2938 | print i | ||
| 2939 | ``` | ||
| 2940 | |||
| 2941 | </YueDisplay> | ||
| 2942 | |||
| 2943 |   继续语句也可以与各种循环表达式一起使用,以防止当前的循环迭代结果累积到结果列表中。以下示例将数组表过滤为仅包含偶数的数组: | ||
| 2944 | |||
| 2945 | ```yuescript | ||
| 2946 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2947 | odds = for x in *my_numbers | ||
| 2948 | continue if x % 2 == 1 | ||
| 2949 | x | ||
| 2950 | ``` | ||
| 2951 | |||
| 2952 | <YueDisplay> | ||
| 2953 | |||
| 2954 | ```yue | ||
| 2955 | my_numbers = [1, 2, 3, 4, 5, 6] | ||
| 2956 | odds = for x in *my_numbers | ||
| 2957 | continue if x % 2 == 1 | ||
| 2958 | x | ||
| 2959 | ``` | ||
| 2960 | |||
| 2961 | </YueDisplay> | ||
| 2962 | |||
| 2963 | # switch 语句 | ||
| 2964 | |||
| 2965 |   switch 语句是为了简化检查一系列相同值的if语句而提供的简写语法。要注意用于比较检查的目标值只会计算一次。和 if 语句一样,switch 语句在最后可以接一个 else 代码块来处理没有匹配的情况。在生成的 Lua 代码中,进行比较是使用 == 操作符完成的。switch 语句中也可以使用赋值表达式来储存临时变量值。 | ||
| 2966 | |||
| 2967 | ```yuescript | ||
| 2968 | switch name := "Dan" | ||
| 2969 | when "Robert" | ||
| 2970 | print "你是Robert" | ||
| 2971 | when "Dan", "Daniel" | ||
| 2972 | print "你的名字是Dan" | ||
| 2973 | else | ||
| 2974 | print "我不认识你,你的名字是#{name}" | ||
| 2975 | ``` | ||
| 2976 | |||
| 2977 | <YueDisplay> | ||
| 2978 | |||
| 2979 | ```yue | ||
| 2980 | switch name := "Dan" | ||
| 2981 | when "Robert" | ||
| 2982 | print "你是Robert" | ||
| 2983 | when "Dan", "Daniel" | ||
| 2984 | print "你的名字是Dan" | ||
| 2985 | else | ||
| 2986 | print "我不认识你,你的名字是#{name}" | ||
| 2987 | ``` | ||
| 2988 | |||
| 2989 | </YueDisplay> | ||
| 2990 | |||
| 2991 |   switch 语句的 when 子句中可以通过使用逗号分隔的列表来匹配多个值。 | ||
| 2992 | |||
| 2993 |   switch 语句也可以作为表达式使用,下面我们可以将 switch 语句返回的结果分配给一个变量: | ||
| 2994 | |||
| 2995 | ```yuescript | ||
| 2996 | b = 1 | ||
| 2997 | next_number = switch b | ||
| 2998 | when 1 | ||
| 2999 | 2 | ||
| 3000 | when 2 | ||
| 3001 | 3 | ||
| 3002 | else | ||
| 3003 | error "数字数得太大了!" | ||
| 3004 | ``` | ||
| 3005 | |||
| 3006 | <YueDisplay> | ||
| 3007 | |||
| 3008 | ```yue | ||
| 3009 | b = 1 | ||
| 3010 | next_number = switch b | ||
| 3011 | when 1 | ||
| 3012 | 2 | ||
| 3013 | when 2 | ||
| 3014 | 3 | ||
| 3015 | else | ||
| 3016 | error "数字数得太大了!" | ||
| 3017 | ``` | ||
| 3018 | |||
| 3019 | </YueDisplay> | ||
| 3020 | |||
| 3021 |   我们可以使用 then 关键字在 when 子句的同一行上编写处理代码。else 代码块的后续代码中要写在同一行上不需要额外的关键字。 | ||
| 3022 | |||
| 3023 | ```yuescript | ||
| 3024 | msg = switch math.random(1, 5) | ||
| 3025 | when 1 then "你很幸运" | ||
| 3026 | when 2 then "你差点很幸运" | ||
| 3027 | else "不太幸运" | ||
| 3028 | ``` | ||
| 3029 | |||
| 3030 | <YueDisplay> | ||
| 3031 | |||
| 3032 | ```yue | ||
| 3033 | msg = switch math.random(1, 5) | ||
| 3034 | when 1 then "你很幸运" | ||
| 3035 | when 2 then "你差点很幸运" | ||
| 3036 | else "不太幸运" | ||
| 3037 | ``` | ||
| 3038 | |||
| 3039 | </YueDisplay> | ||
| 3040 | |||
| 3041 |   如果在编写 switch 语句时希望少写一个缩进,那么你可以把第一个 when 子句放在 switch 开始语句的第一行,然后后续的子语句就都可以都少写一个缩进。 | ||
| 3042 | |||
| 3043 | ```yuescript | ||
| 3044 | switch math.random(1, 5) | ||
| 3045 | when 1 | ||
| 3046 | print "你很幸运" -- 两个缩进级别 | ||
| 3047 | else | ||
| 3048 | print "不太幸运" | ||
| 3049 | |||
| 3050 | switch math.random(1, 5) when 1 | ||
| 3051 | print "你很幸运" -- 一个缩进级别 | ||
| 3052 | else | ||
| 3053 | print "不太幸运" | ||
| 3054 | ``` | ||
| 3055 | |||
| 3056 | <YueDisplay> | ||
| 3057 | |||
| 3058 | ```yue | ||
| 3059 | switch math.random(1, 5) | ||
| 3060 | when 1 | ||
| 3061 | print "你很幸运" -- 两个缩进级别 | ||
| 3062 | else | ||
| 3063 | print "不太幸运" | ||
| 3064 | |||
| 3065 | switch math.random(1, 5) when 1 | ||
| 3066 | print "你很幸运" -- 一个缩进级别 | ||
| 3067 | else | ||
| 3068 | print "不太幸运" | ||
| 3069 | ``` | ||
| 3070 | |||
| 3071 | </YueDisplay> | ||
| 3072 | |||
| 3073 |   值得注意的是,在生成 Lua 代码时,我们要做检查的目标变量会放在 == 表达式的右侧。当你希望给 when 子句的比较对象定义一个 \_\_eq 元方法来重载判断逻辑时,可能会有用。 | ||
| 3074 | |||
| 3075 | ## 表格匹配 | ||
| 3076 | |||
| 3077 |   在 switch 的 when 子句中,如果期待检查目标是一个表格,且可以通过特定的结构进行解构并获得非 nil 值,那么你可以尝试使用表格匹配的语法。 | ||
| 3078 | |||
| 3079 | ```yuescript | ||
| 3080 | items = | ||
| 3081 | * x: 100 | ||
| 3082 | y: 200 | ||
| 3083 | * width: 300 | ||
| 3084 | height: 400 | ||
| 3085 | |||
| 3086 | for item in *items | ||
| 3087 | switch item | ||
| 3088 | when :x, :y | ||
| 3089 | print "Vec2 #{x}, #{y}" | ||
| 3090 | when :width, :height | ||
| 3091 | print "尺寸 #{width}, #{height}" | ||
| 3092 | ``` | ||
| 3093 | |||
| 3094 | <YueDisplay> | ||
| 3095 | |||
| 3096 | ```yue | ||
| 3097 | items = | ||
| 3098 | * x: 100 | ||
| 3099 | y: 200 | ||
| 3100 | * width: 300 | ||
| 3101 | height: 400 | ||
| 3102 | |||
| 3103 | for item in *items | ||
| 3104 | switch item | ||
| 3105 | when :x, :y | ||
| 3106 | print "Vec2 #{x}, #{y}" | ||
| 3107 | when :width, :height | ||
| 3108 | print "尺寸 #{width}, #{height}" | ||
| 3109 | ``` | ||
| 3110 | |||
| 3111 | </YueDisplay> | ||
| 3112 | |||
| 3113 |   你可以使用默认值来选择性地解构表格的某些字段。 | ||
| 3114 | |||
| 3115 | ```yuescript | ||
| 3116 | item = {} | ||
| 3117 | |||
| 3118 | {pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos') | ||
| 3119 | |||
| 3120 | switch item | ||
| 3121 | when {pos: {:x = 50, :y = 200}} | ||
| 3122 | print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过 | ||
| 3123 | ``` | ||
| 3124 | |||
| 3125 | <YueDisplay> | ||
| 3126 | |||
| 3127 | ```yue | ||
| 3128 | item = {} | ||
| 3129 | |||
| 3130 | {pos: {:x = 50, :y = 200}} = item -- 获取错误:尝试索引nil值(字段'pos') | ||
| 3131 | |||
| 3132 | switch item | ||
| 3133 | when {pos: {:x = 50, :y = 200}} | ||
| 3134 | print "Vec2 #{x}, #{y}" -- 表格解构仍然会通过 | ||
| 3135 | ``` | ||
| 3136 | |||
| 3137 | </YueDisplay> | ||
| 3138 | |||
| 3139 |   你也可以匹配数组元素、表格字段,甚至使用数组或表格字面量来匹配嵌套的结构。 | ||
| 3140 | |||
| 3141 |   匹配数组元素。 | ||
| 3142 | |||
| 3143 | ```yuescript | ||
| 3144 | switch tb | ||
| 3145 | when [1, 2, 3] | ||
| 3146 | print "1, 2, 3" | ||
| 3147 | when [1, b, 3] | ||
| 3148 | print "1, #{b}, 3" | ||
| 3149 | when [1, 2, b = 3] -- 变量b有默认值 | ||
| 3150 | print "1, 2, #{b}" | ||
| 3151 | ``` | ||
| 3152 | |||
| 3153 | <YueDisplay> | ||
| 3154 | |||
| 3155 | ```yue | ||
| 3156 | switch tb | ||
| 3157 | when [1, 2, 3] | ||
| 3158 | print "1, 2, 3" | ||
| 3159 | when [1, b, 3] | ||
| 3160 | print "1, #{b}, 3" | ||
| 3161 | when [1, 2, b = 3] -- 变量b有默认值 | ||
| 3162 | print "1, 2, #{b}" | ||
| 3163 | ``` | ||
| 3164 | |||
| 3165 | </YueDisplay> | ||
| 3166 | |||
| 3167 |   匹配表格字段。 | ||
| 3168 | |||
| 3169 | ```yuescript | ||
| 3170 | switch tb | ||
| 3171 | when success: true, :result | ||
| 3172 | print "成功", result | ||
| 3173 | when success: false | ||
| 3174 | print "失败", result | ||
| 3175 | else | ||
| 3176 | print "无效值" | ||
| 3177 | ``` | ||
| 3178 | |||
| 3179 | <YueDisplay> | ||
| 3180 | |||
| 3181 | ```yue | ||
| 3182 | switch tb | ||
| 3183 | when success: true, :result | ||
| 3184 | print "成功", result | ||
| 3185 | when success: false | ||
| 3186 | print "失败", result | ||
| 3187 | else | ||
| 3188 | print "无效值" | ||
| 3189 | ``` | ||
| 3190 | |||
| 3191 | </YueDisplay> | ||
| 3192 | |||
| 3193 |   匹配嵌套的表格结构。 | ||
| 3194 | |||
| 3195 | ```yuescript | ||
| 3196 | switch tb | ||
| 3197 | when data: {type: "success", :content} | ||
| 3198 | print "成功", content | ||
| 3199 | when data: {type: "error", :content} | ||
| 3200 | print "失败", content | ||
| 3201 | else | ||
| 3202 | print "无效值" | ||
| 3203 | ``` | ||
| 3204 | |||
| 3205 | <YueDisplay> | ||
| 3206 | |||
| 3207 | ```yue | ||
| 3208 | switch tb | ||
| 3209 | when data: {type: "success", :content} | ||
| 3210 | print "成功", content | ||
| 3211 | when data: {type: "error", :content} | ||
| 3212 | print "失败", content | ||
| 3213 | else | ||
| 3214 | print "无效值" | ||
| 3215 | ``` | ||
| 3216 | |||
| 3217 | </YueDisplay> | ||
| 3218 | |||
| 3219 |   匹配表格数组。 | ||
| 3220 | |||
| 3221 | ```yuescript | ||
| 3222 | switch tb | ||
| 3223 | when [ | ||
| 3224 | {a: 1, b: 2} | ||
| 3225 | {a: 3, b: 4} | ||
| 3226 | {a: 5, b: 6} | ||
| 3227 | fourth | ||
| 3228 | ] | ||
| 3229 | print "匹配成功", fourth | ||
| 3230 | ``` | ||
| 3231 | |||
| 3232 | <YueDisplay> | ||
| 3233 | |||
| 3234 | ```yue | ||
| 3235 | switch tb | ||
| 3236 | when [ | ||
| 3237 | {a: 1, b: 2} | ||
| 3238 | {a: 3, b: 4} | ||
| 3239 | {a: 5, b: 6} | ||
| 3240 | fourth | ||
| 3241 | ] | ||
| 3242 | print "匹配成功", fourth | ||
| 3243 | ``` | ||
| 3244 | |||
| 3245 | </YueDisplay> | ||
| 3246 | |||
| 3247 |   匹配一个列表并捕获特定范围内的元素。 | ||
| 3248 | |||
| 3249 | ```yuescript | ||
| 3250 | segments = ["admin", "users", "logs", "view"] | ||
| 3251 | switch segments | ||
| 3252 | when [...groups, resource, action] | ||
| 3253 | print "Group:", groups -- 打印: {"admin", "users"} | ||
| 3254 | print "Resource:", resource -- 打印: "logs" | ||
| 3255 | print "Action:", action -- 打印: "view" | ||
| 3256 | ``` | ||
| 3257 | |||
| 3258 | <YueDisplay> | ||
| 3259 | |||
| 3260 | ```yue | ||
| 3261 | segments = ["admin", "users", "logs", "view"] | ||
| 3262 | switch segments | ||
| 3263 | when [...groups, resource, action] | ||
| 3264 | print "Group:", groups -- 打印: {"admin", "users"} | ||
| 3265 | print "Resource:", resource -- 打印: "logs" | ||
| 3266 | print "Action:", action -- 打印: "view" | ||
| 3267 | ``` | ||
| 3268 | |||
| 3269 | </YueDisplay> | ||
| 3270 | |||
| 3271 | # while 循环 | ||
| 3272 | |||
| 3273 |   在月之脚本中的 while 循环支持几种不同的写法: | ||
| 3274 | |||
| 3275 | ```yuescript | ||
| 3276 | i = 10 | ||
| 3277 | while i > 0 | ||
| 3278 | print i | ||
| 3279 | i -= 1 | ||
| 3280 | |||
| 3281 | while running == true do my_function! | ||
| 3282 | ``` | ||
| 3283 | |||
| 3284 | <YueDisplay> | ||
| 3285 | |||
| 3286 | ```yue | ||
| 3287 | i = 10 | ||
| 3288 | while i > 0 | ||
| 3289 | print i | ||
| 3290 | i -= 1 | ||
| 3291 | |||
| 3292 | while running == true do my_function! | ||
| 3293 | ``` | ||
| 3294 | |||
| 3295 | </YueDisplay> | ||
| 3296 | |||
| 3297 | ```yuescript | ||
| 3298 | i = 10 | ||
| 3299 | until i == 0 | ||
| 3300 | print i | ||
| 3301 | i -= 1 | ||
| 3302 | |||
| 3303 | until running == false do my_function! | ||
| 3304 | ``` | ||
| 3305 | |||
| 3306 | <YueDisplay> | ||
| 3307 | |||
| 3308 | ```yue | ||
| 3309 | i = 10 | ||
| 3310 | until i == 0 | ||
| 3311 | print i | ||
| 3312 | i -= 1 | ||
| 3313 | until running == false do my_function! | ||
| 3314 | ``` | ||
| 3315 | |||
| 3316 | </YueDisplay> | ||
| 3317 | |||
| 3318 |   像 for 循环的语法一样,while 循环也可以作为一个表达式使用。while / until 循环表达式支持 `break` 返回多个值。 | ||
| 3319 | |||
| 3320 | ```yuescript | ||
| 3321 | value, doubled = while true | ||
| 3322 | n = get_next! | ||
| 3323 | break n, n * 2 if n > 10 | ||
| 3324 | ``` | ||
| 3325 | |||
| 3326 | <YueDisplay> | ||
| 3327 | |||
| 3328 | ```yue | ||
| 3329 | value, doubled = while true | ||
| 3330 | n = get_next! | ||
| 3331 | break n, n * 2 if n > 10 | ||
| 3332 | ``` | ||
| 3333 | |||
| 3334 | </YueDisplay> | ||
| 3335 | |||
| 3336 |   为了使函数返回 while 循环的累积列表值,必须明确使用返回语句返回 while 循环表达式。 | ||
| 3337 | |||
| 3338 | ## repeat 循环 | ||
| 3339 | |||
| 3340 |   repeat 循环是从 Lua 语言中搬过来的相似语法: | ||
| 3341 | |||
| 3342 | ```yuescript | ||
| 3343 | i = 10 | ||
| 3344 | repeat | ||
| 3345 | print i | ||
| 3346 | i -= 1 | ||
| 3347 | until i == 0 | ||
| 3348 | ``` | ||
| 3349 | |||
| 3350 | <YueDisplay> | ||
| 3351 | |||
| 3352 | ```yue | ||
| 3353 | i = 10 | ||
| 3354 | repeat | ||
| 3355 | print i | ||
| 3356 | i -= 1 | ||
| 3357 | until i == 0 | ||
| 3358 | ``` | ||
| 3359 | |||
| 3360 | </YueDisplay> | ||
| 3361 | |||
| 3362 |   repeat 循环表达式同样支持 `break` 返回多个值: | ||
| 3363 | |||
| 3364 | ```yuescript | ||
| 3365 | i = 1 | ||
| 3366 | value, scaled = repeat | ||
| 3367 | break i, i * 100 if i > 3 | ||
| 3368 | i += 1 | ||
| 3369 | until false | ||
| 3370 | ``` | ||
| 3371 | |||
| 3372 | <YueDisplay> | ||
| 3373 | |||
| 3374 | ```yue | ||
| 3375 | i = 1 | ||
| 3376 | value, scaled = repeat | ||
| 3377 | break i, i * 100 if i > 3 | ||
| 3378 | i += 1 | ||
| 3379 | until false | ||
| 3380 | ``` | ||
| 3381 | |||
| 3382 | </YueDisplay> | ||
| 3383 | |||
| 3384 | # 函数存根 | ||
| 3385 | |||
| 3386 |   在编程中,将对象的方法作为函数类型的值进行传递是一种常见做法,尤其是在将实例方法作为回调函数传递给其他函数的情形中。当目标函数需要将该对象作为其第一个参数时,我们需要找到一种方式将对象和函数绑定在一起,以便能够正确地调用该函数。 | ||
| 3387 | |||
| 3388 |   函数存根(stub)语法提供了一种便捷的方法来创建一个新的闭包函数,这个函数将对象和原函数绑定在一起。这样,当调用这个新创建的函数时,它会在正确的对象上下文中执行原有的函数。 | ||
| 3389 | |||
| 3390 |   这种语法类似于使用 \ 操作符调用实例方法的方式,区别在于,这里不需要在 \ 操作符后面附加参数列表。 | ||
| 3391 | |||
| 3392 | ```yuescript | ||
| 3393 | my_object = { | ||
| 3394 | value: 1000 | ||
| 3395 | write: => print "值为:", @value | ||
| 3396 | } | ||
| 3397 | |||
| 3398 | run_callback = (func) -> | ||
| 3399 | print "运行回调..." | ||
| 3400 | func! | ||
| 3401 | |||
| 3402 | -- 这样写不起作用: | ||
| 3403 | -- 函数没有引用my_object | ||
| 3404 | run_callback my_object.write | ||
| 3405 | |||
| 3406 | -- 函数存根语法 | ||
| 3407 | -- 让我们把对象捆绑到一个新函数中 | ||
| 3408 | run_callback my_object\write | ||
| 3409 | ``` | ||
| 3410 | |||
| 3411 | <YueDisplay> | ||
| 3412 | |||
| 3413 | ```yue | ||
| 3414 | my_object = { | ||
| 3415 | value: 1000 | ||
| 3416 | write: => print "值为:", @value | ||
| 3417 | } | ||
| 3418 | |||
| 3419 | run_callback = (func) -> | ||
| 3420 | print "运行回调..." | ||
| 3421 | func! | ||
| 3422 | |||
| 3423 | -- 这样写不起作用: | ||
| 3424 | -- 函数没有引用my_object | ||
| 3425 | run_callback my_object.write | ||
| 3426 | |||
| 3427 | -- 函数存根语法 | ||
| 3428 | -- 让我们把对象捆绑到一个新函数中 | ||
| 3429 | run_callback my_object\write | ||
| 3430 | ``` | ||
| 3431 | |||
| 3432 | </YueDisplay> | ||
| 3433 | |||
| 3434 | # 反向回调 | ||
| 3435 | |||
| 3436 |   反向回调用于减少函数回调的嵌套。它们使用指向左侧的箭头,并且默认会被定义为传入后续函数调用的最后一个参数。它的语法大部分与常规箭头函数相同,只是它指向另一方向,并且后续的函数体不需要进行缩进。 | ||
| 3437 | |||
| 3438 | ```yuescript | ||
| 3439 | x <- f | ||
| 3440 | print "hello" .. x | ||
| 3441 | ``` | ||
| 3442 | |||
| 3443 | <YueDisplay> | ||
| 3444 | |||
| 3445 | ```yue | ||
| 3446 | x <- f | ||
| 3447 | print "hello" .. x | ||
| 3448 | ``` | ||
| 3449 | |||
| 3450 | </YueDisplay> | ||
| 3451 | |||
| 3452 |   月之脚本也提供了粗箭头反向回调函数。 | ||
| 3453 | |||
| 3454 | ```yuescript | ||
| 3455 | <= f | ||
| 3456 | print @value | ||
| 3457 | ``` | ||
| 3458 | |||
| 3459 | <YueDisplay> | ||
| 3460 | |||
| 3461 | ```yue | ||
| 3462 | <= f | ||
| 3463 | print @value | ||
| 3464 | ``` | ||
| 3465 | |||
| 3466 | </YueDisplay> | ||
| 3467 | |||
| 3468 |   你可以通过一个占位符指定回调函数的传参位置。 | ||
| 3469 | |||
| 3470 | ```yuescript | ||
| 3471 | (x) <- map _, [1, 2, 3] | ||
| 3472 | x * 2 | ||
| 3473 | ``` | ||
| 3474 | |||
| 3475 | <YueDisplay> | ||
| 3476 | |||
| 3477 | ```yue | ||
| 3478 | (x) <- map _, [1, 2, 3] | ||
| 3479 | x * 2 | ||
| 3480 | ``` | ||
| 3481 | |||
| 3482 | </YueDisplay> | ||
| 3483 | |||
| 3484 |   如果你希望在反向回调处理后继续编写更多其它的代码,可以使用 do 语句将不属于反向回调的代码分隔开。对于非粗箭头函数的反向回调,回调返回值的括号也是可以省略的。 | ||
| 3485 | |||
| 3486 | ```yuescript | ||
| 3487 | result, msg = do | ||
| 3488 | data <- readAsync "文件名.txt" | ||
| 3489 | print data | ||
| 3490 | info <- processAsync data | ||
| 3491 | check info | ||
| 3492 | print result, msg | ||
| 3493 | ``` | ||
| 3494 | |||
| 3495 | <YueDisplay> | ||
| 3496 | |||
| 3497 | ```yue | ||
| 3498 | result, msg = do | ||
| 3499 | data <- readAsync "文件名.txt" | ||
| 3500 | print data | ||
| 3501 | info <- processAsync data | ||
| 3502 | check info | ||
| 3503 | print result, msg | ||
| 3504 | ``` | ||
| 3505 | |||
| 3506 | </YueDisplay> | ||
| 3507 | |||
| 3508 | # 函数字面量 | ||
| 3509 | |||
| 3510 |   所有函数都是使用月之脚本的函数表达式创建的。一个简单的函数可以用箭头表示为:**->**。 | ||
| 3511 | |||
| 3512 | ```yuescript | ||
| 3513 | my_function = -> | ||
| 3514 | my_function() -- 调用空函数 | ||
| 3515 | ``` | ||
| 3516 | |||
| 3517 | <YueDisplay> | ||
| 3518 | |||
| 3519 | ```yue | ||
| 3520 | my_function = -> | ||
| 3521 | my_function() -- 调用空函数 | ||
| 3522 | ``` | ||
| 3523 | |||
| 3524 | </YueDisplay> | ||
| 3525 | |||
| 3526 |   函数体可以是紧跟在箭头后的一个语句,或者是在后面的行上使用同样缩进的一系列语句: | ||
| 3527 | |||
| 3528 | ```yuescript | ||
| 3529 | func_a = -> print "你好,世界" | ||
| 3530 | |||
| 3531 | func_b = -> | ||
| 3532 | value = 100 | ||
| 3533 | print "这个值是:", value | ||
| 3534 | ``` | ||
| 3535 | |||
| 3536 | <YueDisplay> | ||
| 3537 | |||
| 3538 | ```yue | ||
| 3539 | func_a = -> print "你好,世界" | ||
| 3540 | |||
| 3541 | func_b = -> | ||
| 3542 | value = 100 | ||
| 3543 | print "这个值是:", value | ||
| 3544 | ``` | ||
| 3545 | |||
| 3546 | </YueDisplay> | ||
| 3547 | |||
| 3548 |   如果一个函数没有参数,可以使用 **\!** 操作符调用它,而不是空括号。使用 **\!** 调用没有参数的函数是推荐的写法。 | ||
| 3549 | |||
| 3550 | ```yuescript | ||
| 3551 | func_a! | ||
| 3552 | func_b() | ||
| 3553 | ``` | ||
| 3554 | |||
| 3555 | <YueDisplay> | ||
| 3556 | |||
| 3557 | ```yue | ||
| 3558 | func_a! | ||
| 3559 | func_b() | ||
| 3560 | ``` | ||
| 3561 | |||
| 3562 | </YueDisplay> | ||
| 3563 | |||
| 3564 |   带有参数的函数可以通过在箭头前加上括号中的参数名列表来进行创建: | ||
| 3565 | |||
| 3566 | ```yuescript | ||
| 3567 | sum = (x, y) -> print "数字的和", x + y | ||
| 3568 | ``` | ||
| 3569 | |||
| 3570 | <YueDisplay> | ||
| 3571 | |||
| 3572 | ```yue | ||
| 3573 | sum = (x, y) -> print "数字的和", x + y | ||
| 3574 | ``` | ||
| 3575 | |||
| 3576 | </YueDisplay> | ||
| 3577 | |||
| 3578 |   函数可以通过在函数名后列出参数来调用。当对函数做嵌套的调用时,后面列出的参数会应用于左侧最近的函数。 | ||
| 3579 | |||
| 3580 | ```yuescript | ||
| 3581 | sum 10, 20 | ||
| 3582 | print sum 10, 20 | ||
| 3583 | |||
| 3584 | a b c "a", "b", "c" | ||
| 3585 | ``` | ||
| 3586 | |||
| 3587 | <YueDisplay> | ||
| 3588 | |||
| 3589 | ```yue | ||
| 3590 | sum 10, 20 | ||
| 3591 | print sum 10, 20 | ||
| 3592 | |||
| 3593 | a b c "a", "b", "c" | ||
| 3594 | ``` | ||
| 3595 | |||
| 3596 | </YueDisplay> | ||
| 3597 | |||
| 3598 |   为了避免在调用函数时产生歧义,也可以使用括号将参数括起来。比如在以下的例子中是必需的,这样才能确保参数被传入到正确的函数。 | ||
| 3599 | |||
| 3600 | ```yuescript | ||
| 3601 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3602 | ``` | ||
| 3603 | |||
| 3604 | <YueDisplay> | ||
| 3605 | |||
| 3606 | ```yue | ||
| 3607 | print "x:", sum(10, 20), "y:", sum(30, 40) | ||
| 3608 | ``` | ||
| 3609 | |||
| 3610 | </YueDisplay> | ||
| 3611 | |||
| 3612 |   注意:函数名与开始括号之间不能有任何空格。 | ||
| 3613 | |||
| 3614 |   函数会将函数体中的最后一个语句强制转换为返回语句,这被称作隐式返回: | ||
| 3615 | |||
| 3616 | ```yuescript | ||
| 3617 | sum = (x, y) -> x + y | ||
| 3618 | print "数字的和是", sum 10, 20 | ||
| 3619 | ``` | ||
| 3620 | |||
| 3621 | <YueDisplay> | ||
| 3622 | |||
| 3623 | ```yue | ||
| 3624 | sum = (x, y) -> x + y | ||
| 3625 | print "数字的和是", sum 10, 20 | ||
| 3626 | ``` | ||
| 3627 | |||
| 3628 | </YueDisplay> | ||
| 3629 | |||
| 3630 |   如果你需要做显式返回,可以使用 return 关键字: | ||
| 3631 | |||
| 3632 | ```yuescript | ||
| 3633 | sum = (x, y) -> return x + y | ||
| 3634 | ``` | ||
| 3635 | |||
| 3636 | <YueDisplay> | ||
| 3637 | |||
| 3638 | ```yue | ||
| 3639 | sum = (x, y) -> return x + y | ||
| 3640 | ``` | ||
| 3641 | |||
| 3642 | </YueDisplay> | ||
| 3643 | |||
| 3644 |   就像在Lua中一样,函数可以返回多个值。最后一个语句必须是由逗号分隔的值列表: | ||
| 3645 | |||
| 3646 | ```yuescript | ||
| 3647 | mystery = (x, y) -> x + y, x - y | ||
| 3648 | a, b = mystery 10, 20 | ||
| 3649 | ``` | ||
| 3650 | |||
| 3651 | <YueDisplay> | ||
| 3652 | |||
| 3653 | ```yue | ||
| 3654 | mystery = (x, y) -> x + y, x - y | ||
| 3655 | a, b = mystery 10, 20 | ||
| 3656 | ``` | ||
| 3657 | |||
| 3658 | </YueDisplay> | ||
| 3659 | |||
| 3660 | ## 粗箭头 | ||
| 3661 | |||
| 3662 |   因为在 Lua 中调用方法时,经常习惯将对象作为第一个参数传入,所以月之脚本提供了一种特殊的语法来创建自动包含 self 参数的函数。 | ||
| 3663 | |||
| 3664 | ```yuescript | ||
| 3665 | func = (num) => @value + num | ||
| 3666 | ``` | ||
| 3667 | |||
| 3668 | <YueDisplay> | ||
| 3669 | |||
| 3670 | ```yue | ||
| 3671 | func = (num) => @value + num | ||
| 3672 | ``` | ||
| 3673 | |||
| 3674 | </YueDisplay> | ||
| 3675 | |||
| 3676 | ## 参数默认值 | ||
| 3677 | |||
| 3678 |   可以为函数的参数提供默认值。如果参数的值为 nil,则确定该参数为空。任何具有默认值的 nil 参数在函数体运行之前都会被替换。 | ||
| 3679 | |||
| 3680 | ```yuescript | ||
| 3681 | my_function = (name = "某物", height = 100) -> | ||
| 3682 | print "你好,我是", name | ||
| 3683 | print "我的高度是", height | ||
| 3684 | ``` | ||
| 3685 | |||
| 3686 | <YueDisplay> | ||
| 3687 | |||
| 3688 | ```yue | ||
| 3689 | my_function = (name = "某物", height = 100) -> | ||
| 3690 | print "你好,我是", name | ||
| 3691 | print "我的高度是", height | ||
| 3692 | ``` | ||
| 3693 | |||
| 3694 | </YueDisplay> | ||
| 3695 | |||
| 3696 |   函数参数的默认值表达式在函数体中会按参数声明的顺序进行计算。因此,在默认值的表达式中可以访问先前声明的参数。 | ||
| 3697 | |||
| 3698 | ```yuescript | ||
| 3699 | some_args = (x = 100, y = x + 1000) -> | ||
| 3700 | print x + y | ||
| 3701 | ``` | ||
| 3702 | |||
| 3703 | <YueDisplay> | ||
| 3704 | |||
| 3705 | ```yue | ||
| 3706 | some_args = (x = 100, y = x + 1000) -> | ||
| 3707 | print x + y | ||
| 3708 | ``` | ||
| 3709 | |||
| 3710 | </YueDisplay> | ||
| 3711 | |||
| 3712 | ## 注意事项 | ||
| 3713 | |||
| 3714 |   由于月之脚本支持无需括号的表达式式函数调用,因此为了避免因空白字符造成的解析歧义,需要进行一些限制。 | ||
| 3715 | |||
| 3716 |   减号(-)在表达式中既可以作为一元取反操作符,也可以作为二元减法操作符。请注意下面这些示例的编译方式: | ||
| 3717 | |||
| 3718 | ```yuescript | ||
| 3719 | a = x - 10 | ||
| 3720 | b = x-10 | ||
| 3721 | c = x -y | ||
| 3722 | d = x- z | ||
| 3723 | ``` | ||
| 3724 | |||
| 3725 | <YueDisplay> | ||
| 3726 | |||
| 3727 | ```yue | ||
| 3728 | a = x - 10 | ||
| 3729 | b = x-10 | ||
| 3730 | c = x -y | ||
| 3731 | d = x- z | ||
| 3732 | ``` | ||
| 3733 | |||
| 3734 | </YueDisplay> | ||
| 3735 | |||
| 3736 |   当函数调用的第一个参数是字符串字面量时,可以通过空白控制其优先级。在 Lua 中,常见的写法是调用仅有一个字符串或表字面量参数的函数时省略括号。 | ||
| 3737 | |||
| 3738 |   当变量名和字符串字面量之间没有空格时,函数的调用优先级高于后续表达式,因此此时无法再传入其他参数。 | ||
| 3739 | |||
| 3740 |   当变量名和字符串字面量之间有空格时,字符串字面量会作为后续表达式(如果存在)的参数,这样可以传递参数列表。 | ||
| 3741 | |||
| 3742 | ```yuescript | ||
| 3743 | x = func"hello" + 100 | ||
| 3744 | y = func "hello" + 100 | ||
| 3745 | ``` | ||
| 3746 | |||
| 3747 | <YueDisplay> | ||
| 3748 | |||
| 3749 | ```yue | ||
| 3750 | x = func"hello" + 100 | ||
| 3751 | y = func "hello" + 100 | ||
| 3752 | ``` | ||
| 3753 | |||
| 3754 | </YueDisplay> | ||
| 3755 | |||
| 3756 | ## 多行参数 | ||
| 3757 | |||
| 3758 |   当调用接收大量参数的函数时,将参数列表分成多行是很方便的。由于月之脚本语言对空白字符的敏感性,做参数列表的分割时务必要小心。 | ||
| 3759 | |||
| 3760 |   如果要将参数列表写到下一行,那么当前行必须以逗号结束。并且下一行的缩进必须比当前的缩进多。一旦做了参数的缩进,所有其他参数列表的行必须保持相同的缩进级别,以成为参数列表的一部分。 | ||
| 3761 | |||
| 3762 | ```yuescript | ||
| 3763 | my_func 5, 4, 3, | ||
| 3764 | 8, 9, 10 | ||
| 3765 | |||
| 3766 | cool_func 1, 2, | ||
| 3767 | 3, 4, | ||
| 3768 | 5, 6, | ||
| 3769 | 7, 8 | ||
| 3770 | ``` | ||
| 3771 | |||
| 3772 | <YueDisplay> | ||
| 3773 | |||
| 3774 | ```yue | ||
| 3775 | my_func 5, 4, 3, | ||
| 3776 | 8, 9, 10 | ||
| 3777 | |||
| 3778 | cool_func 1, 2, | ||
| 3779 | 3, 4, | ||
| 3780 | 5, 6, | ||
| 3781 | 7, 8 | ||
| 3782 | ``` | ||
| 3783 | |||
| 3784 | </YueDisplay> | ||
| 3785 | |||
| 3786 |   这种调用方式可以做嵌套。并通过缩进级别来确定参数属于哪一个函数。 | ||
| 3787 | |||
| 3788 | ```yuescript | ||
| 3789 | my_func 5, 6, 7, | ||
| 3790 | 6, another_func 6, 7, 8, | ||
| 3791 | 9, 1, 2, | ||
| 3792 | 5, 4 | ||
| 3793 | ``` | ||
| 3794 | |||
| 3795 | <YueDisplay> | ||
| 3796 | |||
| 3797 | ```yue | ||
| 3798 | my_func 5, 6, 7, | ||
| 3799 | 6, another_func 6, 7, 8, | ||
| 3800 | 9, 1, 2, | ||
| 3801 | 5, 4 | ||
| 3802 | ``` | ||
| 3803 | |||
| 3804 | </YueDisplay> | ||
| 3805 | |||
| 3806 |   因为 Lua 表也使用逗号作为分隔符,这种缩进语法有助于让值成为参数列表的一部分,而不是 Lua 表的一部分。 | ||
| 3807 | |||
| 3808 | ```yuescript | ||
| 3809 | x = [ | ||
| 3810 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3811 | 5, 6, | ||
| 3812 | 8, 9, 10 | ||
| 3813 | ] | ||
| 3814 | ``` | ||
| 3815 | |||
| 3816 | <YueDisplay> | ||
| 3817 | |||
| 3818 | ```yue | ||
| 3819 | x = [ | ||
| 3820 | 1, 2, 3, 4, a_func 4, 5, | ||
| 3821 | 5, 6, | ||
| 3822 | 8, 9, 10 | ||
| 3823 | ] | ||
| 3824 | ``` | ||
| 3825 | |||
| 3826 | </YueDisplay> | ||
| 3827 | |||
| 3828 |   有个不常见的写法可以注意一下,如果我们将在后面使用较低的缩进,我们可以为函数参数提供更深的缩进来区分列表的归属。 | ||
| 3829 | |||
| 3830 | ```yuescript | ||
| 3831 | y = [ my_func 1, 2, 3, | ||
| 3832 | 4, 5, | ||
| 3833 | 5, 6, 7 | ||
| 3834 | ] | ||
| 3835 | ``` | ||
| 3836 | |||
| 3837 | <YueDisplay> | ||
| 3838 | |||
| 3839 | ```yue | ||
| 3840 | y = [ my_func 1, 2, 3, | ||
| 3841 | 4, 5, | ||
| 3842 | 5, 6, 7 | ||
| 3843 | ] | ||
| 3844 | ``` | ||
| 3845 | |||
| 3846 | </YueDisplay> | ||
| 3847 | |||
| 3848 |   对于其它有代码块跟随的语句,比如条件语句,也可以通过小心安排缩进来做类似的事。比如我们可以通过调整缩进级别来控制一些值归属于哪个语句: | ||
| 3849 | |||
| 3850 | ```yuescript | ||
| 3851 | if func 1, 2, 3, | ||
| 3852 | "你好", | ||
| 3853 | "世界" | ||
| 3854 | print "你好" | ||
| 3855 | print "我在if内部" | ||
| 3856 | |||
| 3857 | if func 1, 2, 3, | ||
| 3858 | "你好", | ||
| 3859 | "世界" | ||
| 3860 | print "hello" | ||
| 3861 | print "我在if内部" | ||
| 3862 | ``` | ||
| 3863 | |||
| 3864 | <YueDisplay> | ||
| 3865 | |||
| 3866 | ```yue | ||
| 3867 | if func 1, 2, 3, | ||
| 3868 | "你好", | ||
| 3869 | "世界" | ||
| 3870 | print "你好" | ||
| 3871 | print "我在if内部" | ||
| 3872 | |||
| 3873 | if func 1, 2, 3, | ||
| 3874 | "你好", | ||
| 3875 | "世界" | ||
| 3876 | print "你好" | ||
| 3877 | print "我在if内部" | ||
| 3878 | ``` | ||
| 3879 | |||
| 3880 | </YueDisplay> | ||
| 3881 | |||
| 3882 | ## 参数解构 | ||
| 3883 | |||
| 3884 |   月之脚本支持在函数形参位置对传入对象进行解构。适用两类解构表子面量: | ||
| 3885 | |||
| 3886 | - 使用 {} 包裹的字面量/对象形参,支持提供获得空字段时的默认值(例如 {:a, :b}、{a: a1 = 123})。 | ||
| 3887 | |||
| 3888 | - 无 {} 包裹、以键值/简写键序列开头,直至遇到其它表达式终止(例如 :a, b: b1, :c),表示从同一个对象中解构多个字段。 | ||
| 3889 | |||
| 3890 | ```yuescript | ||
| 3891 | f1 = (:a, :b, :c) -> | ||
| 3892 | print a, b, c | ||
| 3893 | |||
| 3894 | f1 a: 1, b: "2", c: {} | ||
| 3895 | |||
| 3896 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3897 | print a1, b, c | ||
| 3898 | |||
| 3899 | arg1 = {a: 0} | ||
| 3900 | f2 arg1, arg2 | ||
| 3901 | ``` | ||
| 3902 | |||
| 3903 | <YueDisplay> | ||
| 3904 | |||
| 3905 | ```yue | ||
| 3906 | f1 = (:a, :b, :c) -> | ||
| 3907 | print a, b, c | ||
| 3908 | |||
| 3909 | f1 a: 1, b: "2", c: {} | ||
| 3910 | |||
| 3911 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 3912 | print a1, b, c | ||
| 3913 | |||
| 3914 | arg1 = {a: 0} | ||
| 3915 | f2 arg1, arg2 | ||
| 3916 | ``` | ||
| 3917 | |||
| 3918 | </YueDisplay> | ||
| 3919 | |||
| 3920 | ## 前置返回表达式 | ||
| 3921 | |||
| 3922 |   在深度嵌套的函数体中,为了提升返回值的可读性及编写便利性,我们新增了 “前置返回表达式” 语法。其形式如下: | ||
| 3923 | |||
| 3924 | ```yuescript | ||
| 3925 | findFirstEven = (list): nil -> | ||
| 3926 | for item in *list | ||
| 3927 | if type(item) == "table" | ||
| 3928 | for sub in *item | ||
| 3929 | if sub % 2 == 0 | ||
| 3930 | return sub | ||
| 3931 | ``` | ||
| 3932 | |||
| 3933 | <YueDisplay> | ||
| 3934 | |||
| 3935 | ```yue | ||
| 3936 | findFirstEven = (list): nil -> | ||
| 3937 | for item in *list | ||
| 3938 | if type(item) == "table" | ||
| 3939 | for sub in *item | ||
| 3940 | if sub % 2 == 0 | ||
| 3941 | return sub | ||
| 3942 | ``` | ||
| 3943 | |||
| 3944 | </YueDisplay> | ||
| 3945 | |||
| 3946 |   这个写法等价于: | ||
| 3947 | |||
| 3948 | ```yuescript | ||
| 3949 | findFirstEven = (list) -> | ||
| 3950 | for item in *list | ||
| 3951 | if type(item) == "table" | ||
| 3952 | for sub in *item | ||
| 3953 | if sub % 2 == 0 | ||
| 3954 | return sub | ||
| 3955 | nil | ||
| 3956 | ``` | ||
| 3957 | |||
| 3958 | <YueDisplay> | ||
| 3959 | |||
| 3960 | ```yue | ||
| 3961 | findFirstEven = (list) -> | ||
| 3962 | for item in *list | ||
| 3963 | if type(item) == "table" | ||
| 3964 | for sub in *item | ||
| 3965 | if sub % 2 == 0 | ||
| 3966 | return sub | ||
| 3967 | nil | ||
| 3968 | ``` | ||
| 3969 | |||
| 3970 | </YueDisplay> | ||
| 3971 | |||
| 3972 |   唯一的区别在于:你可以将函数的返回值表达式提前写在 `->` 或 `=>` 前,用以指示该函数应隐式返回该表达式的值。这样即使在多层循环或条件判断的场景下,也无需编写尾行悬挂的返回表达式,逻辑结构会更加直观清晰。 | ||
| 3973 | |||
| 3974 | ## 命名变长参数 | ||
| 3975 | |||
| 3976 |   你可以使用 `(...t) ->` 语法来将变长参数自动存储到一个命名表中。这个表会包含所有传入的参数(包括 `nil` 值),并且会在表的 `n` 字段中存储实际传入的参数个数(包括 `nil` 值在内的个数)。 | ||
| 3977 | |||
| 3978 | ```yuescript | ||
| 3979 | f = (...t) -> | ||
| 3980 | print "参数个数:", t.n | ||
| 3981 | print "表长度:", #t | ||
| 3982 | for i = 1, t.n | ||
| 3983 | print t[i] | ||
| 3984 | |||
| 3985 | f 1, 2, 3 | ||
| 3986 | f "a", "b", "c", "d" | ||
| 3987 | f! | ||
| 3988 | |||
| 3989 | -- 处理包含 nil 的情况 | ||
| 3990 | process = (...args) -> | ||
| 3991 | sum = 0 | ||
| 3992 | for i = 1, args.n | ||
| 3993 | if args[i] != nil and type(args[i]) == "number" | ||
| 3994 | sum += args[i] | ||
| 3995 | sum | ||
| 3996 | |||
| 3997 | process 1, nil, 3, nil, 5 | ||
| 3998 | ``` | ||
| 3999 | |||
| 4000 | <YueDisplay> | ||
| 4001 | |||
| 4002 | ```yue | ||
| 4003 | f = (...t) -> | ||
| 4004 | print "参数个数:", t.n | ||
| 4005 | print "表长度:", #t | ||
| 4006 | for i = 1, t.n | ||
| 4007 | print t[i] | ||
| 4008 | |||
| 4009 | f 1, 2, 3 | ||
| 4010 | f "a", "b", "c", "d" | ||
| 4011 | f! | ||
| 4012 | |||
| 4013 | -- 处理包含 nil 的情况 | ||
| 4014 | process = (...args) -> | ||
| 4015 | sum = 0 | ||
| 4016 | for i = 1, args.n | ||
| 4017 | if args[i] != nil and type(args[i]) == "number" | ||
| 4018 | sum += args[i] | ||
| 4019 | sum | ||
| 4020 | |||
| 4021 | process 1, nil, 3, nil, 5 | ||
| 4022 | ``` | ||
| 4023 | |||
| 4024 | </YueDisplay> | ||
| 4025 | |||
| 4026 | # 空白 | ||
| 4027 | |||
| 4028 |   月之脚本是一个对空白敏感的语言。你必须在相同的缩进中使用空格 **' '** 或制表符 **'\t'** 来编写一些代码块,如函数体、值列表和一些控制块。包含不同空白的表达式可能意味着不同的事情。制表符被视为4个空格,但最好不要混合使用空格和制表符。 | ||
| 4029 | |||
| 4030 | ## 语句分隔符 | ||
| 4031 | |||
| 4032 |   一条语句通常以换行结束。你也可以使用分号 `;` 显式结束一条语句,从而在同一行中编写多条语句: | ||
| 4033 | |||
| 4034 | ```yuescript | ||
| 4035 | a = 1; b = 2; print a + b | ||
| 4036 | ``` | ||
| 4037 | |||
| 4038 | <YueDisplay> | ||
| 4039 | |||
| 4040 | ```yue | ||
| 4041 | a = 1; b = 2; print a + b | ||
| 4042 | ``` | ||
| 4043 | |||
| 4044 | </YueDisplay> | ||
| 4045 | |||
| 4046 | ## 多行链式调用 | ||
| 4047 | |||
| 4048 |   你可以使用相同的缩进来编写多行链式函数调用。 | ||
| 4049 | |||
| 4050 | ```yuescript | ||
| 4051 | Rx.Observable | ||
| 4052 | .fromRange 1, 8 | ||
| 4053 | \filter (x) -> x % 2 == 0 | ||
| 4054 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4055 | \map (value) -> value .. '!' | ||
| 4056 | \subscribe print | ||
| 4057 | ``` | ||
| 4058 | |||
| 4059 | <YueDisplay> | ||
| 4060 | |||
| 4061 | ```yue | ||
| 4062 | Rx.Observable | ||
| 4063 | .fromRange 1, 8 | ||
| 4064 | \filter (x) -> x % 2 == 0 | ||
| 4065 | \concat Rx.Observable.of 'who do we appreciate' | ||
| 4066 | \map (value) -> value .. '!' | ||
| 4067 | \subscribe print | ||
| 4068 | ``` | ||
| 4069 | |||
| 4070 | </YueDisplay> | ||
| 4071 | |||
| 4072 | # 注释 | ||
| 4073 | |||
| 4074 | ```yuescript | ||
| 4075 | -- 我是一个注释 | ||
| 4076 | |||
| 4077 | str = --[[ | ||
| 4078 | 这是一个多行注释。 | ||
| 4079 | 没问题。 | ||
| 4080 | ]] strA \ -- 注释 1 | ||
| 4081 | .. strB \ -- 注释 2 | ||
| 4082 | .. strC | ||
| 4083 | |||
| 4084 | func --[[端口]] 3000, --[[ip]] "192.168.1.1" | ||
| 4085 | ``` | ||
| 4086 | |||
| 4087 | <YueDisplay> | ||
| 4088 | |||
| 4089 | ```yue | ||
| 4090 | -- 我是一个注释 | ||
| 4091 | |||
| 4092 | str = --[[ | ||
| 4093 | 这是一个多行注释。 | ||
| 4094 | 没问题。 | ||
| 4095 | ]] strA \ -- 注释 1 | ||
| 4096 | .. strB \ -- 注释 2 | ||
| 4097 | .. strC | ||
| 4098 | |||
| 4099 | func --[[端口]] 3000, --[[ip]] "192.168.1.1" | ||
| 4100 | ``` | ||
| 4101 | |||
| 4102 | </YueDisplay> | ||
| 4103 | |||
| 4104 | # 属性 | ||
| 4105 | |||
| 4106 |   月之脚本现在提供了 Lua 5.4 新增的叫做属性的语法支持。在月之脚本编译到的 Lua 目标版本低于 5.4 时,你仍然可以同时使用`const` 和 `close` 的属性声明语法,并获得常量检查和作用域回调的功能。 | ||
| 4107 | |||
| 4108 | ```yuescript | ||
| 4109 | const a = 123 | ||
| 4110 | close _ = <close>: -> print "超出范围。" | ||
| 4111 | ``` | ||
| 4112 | |||
| 4113 | <YueDisplay> | ||
| 4114 | |||
| 4115 | ```yue | ||
| 4116 | const a = 123 | ||
| 4117 | close _ = <close>: -> print "超出范围。" | ||
| 4118 | ``` | ||
| 4119 | |||
| 4120 | </YueDisplay> | ||
| 4121 | |||
| 4122 |   你可以对进行解构得到的变量标记为常量。 | ||
| 4123 | |||
| 4124 | ```yuescript | ||
| 4125 | const {:a, :b, c, d} = tb | ||
| 4126 | -- a = 1 | ||
| 4127 | ``` | ||
| 4128 | |||
| 4129 | <YueDisplay> | ||
| 4130 | |||
| 4131 | ```yue | ||
| 4132 | const {:a, :b, c, d} = tb | ||
| 4133 | -- a = 1 | ||
| 4134 | ``` | ||
| 4135 | |||
| 4136 | </YueDisplay> | ||
| 4137 | |||
| 4138 |   你也可以声明全局变量为常量。 | ||
| 4139 | |||
| 4140 | ```yuescript | ||
| 4141 | global const Constant = 123 | ||
| 4142 | -- Constant = 1 | ||
| 4143 | ``` | ||
| 4144 | |||
| 4145 | <YueDisplay> | ||
| 4146 | |||
| 4147 | ```yue | ||
| 4148 | global const Constant = 123 | ||
| 4149 | -- Constant = 1 | ||
| 4150 | ``` | ||
| 4151 | |||
| 4152 | </YueDisplay> | ||
| 4153 | |||
| 4154 | # 操作符 | ||
| 4155 | |||
| 4156 |   Lua 的所有二元和一元操作符在月之脚本中都是可用的。此外,**!=** 符号是 **~=** 的别名,而 **\\** 或 **::** 均可用于编写链式函数调用,如写作 `tb\func!` 或 `tb::func!`。此外月之脚本还提供了一些其他特殊的操作符,以编写更具表达力的代码。 | ||
| 4157 | |||
| 4158 | ```yuescript | ||
| 4159 | tb\func! if tb ~= nil | ||
| 4160 | tb::func! if tb != nil | ||
| 4161 | ``` | ||
| 4162 | |||
| 4163 | <YueDisplay> | ||
| 4164 | |||
| 4165 | ```yue | ||
| 4166 | tb\func! if tb ~= nil | ||
| 4167 | tb::func! if tb != nil | ||
| 4168 | ``` | ||
| 4169 | |||
| 4170 | </YueDisplay> | ||
| 4171 | |||
| 4172 | ## 链式比较 | ||
| 4173 | |||
| 4174 |   你可以在月之脚本中进行比较表达式的链式书写: | ||
| 4175 | |||
| 4176 | ```yuescript | ||
| 4177 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4178 | -- 输出:true | ||
| 4179 | |||
| 4180 | a = 5 | ||
| 4181 | print 1 <= a <= 10 | ||
| 4182 | -- 输出:true | ||
| 4183 | ``` | ||
| 4184 | |||
| 4185 | <YueDisplay> | ||
| 4186 | |||
| 4187 | ```yue | ||
| 4188 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
| 4189 | -- 输出:true | ||
| 4190 | |||
| 4191 | a = 5 | ||
| 4192 | print 1 <= a <= 10 | ||
| 4193 | -- 输出:true | ||
| 4194 | ``` | ||
| 4195 | |||
| 4196 | </YueDisplay> | ||
| 4197 | |||
| 4198 |   可以注意一下链式比较表达式的求值行为: | ||
| 4199 | |||
| 4200 | ```yuescript | ||
| 4201 | v = (x) -> | ||
| 4202 | print x | ||
| 4203 | x | ||
| 4204 | |||
| 4205 | print v(1) < v(2) <= v(3) | ||
| 4206 | --[[ | ||
| 4207 | 输出: | ||
| 4208 | 2 | ||
| 4209 | 1 | ||
| 4210 | 3 | ||
| 4211 | true | ||
| 4212 | ]] | ||
| 4213 | |||
| 4214 | print v(1) > v(2) <= v(3) | ||
| 4215 | --[[ | ||
| 4216 | 输出: | ||
| 4217 | 2 | ||
| 4218 | 1 | ||
| 4219 | false | ||
| 4220 | ]] | ||
| 4221 | ``` | ||
| 4222 | |||
| 4223 | <YueDisplay> | ||
| 4224 | |||
| 4225 | ```yue | ||
| 4226 | v = (x) -> | ||
| 4227 | print x | ||
| 4228 | x | ||
| 4229 | |||
| 4230 | print v(1) < v(2) <= v(3) | ||
| 4231 | --[[ | ||
| 4232 | 输出: | ||
| 4233 | 2 | ||
| 4234 | 1 | ||
| 4235 | 3 | ||
| 4236 | true | ||
| 4237 | ]] | ||
| 4238 | |||
| 4239 | print v(1) > v(2) <= v(3) | ||
| 4240 | --[[ | ||
| 4241 | 输出: | ||
| 4242 | 2 | ||
| 4243 | 1 | ||
| 4244 | false | ||
| 4245 | ]] | ||
| 4246 | ``` | ||
| 4247 | |||
| 4248 | </YueDisplay> | ||
| 4249 | |||
| 4250 |   在上面的例子里,中间的表达式 `v(2)` 仅被计算一次,如果把表达式写成 `v(1) < v(2) and v(2) <= v(3)` 的方式,中间的 `v(2)` 才会被计算两次。在链式比较中,求值的顺序往往是未定义的。所以强烈建议不要在链式比较中使用具有副作用(比如做打印操作)的表达式。如果需要使用有副作用的函数,应明确使用短路 `and` 运算符来做连接。 | ||
| 4251 | |||
| 4252 | ## 表追加 | ||
| 4253 | |||
| 4254 |   **[] =** 操作符用于向 Lua 表的最后插入值。 | ||
| 4255 | |||
| 4256 | ```yuescript | ||
| 4257 | tab = [] | ||
| 4258 | tab[] = "Value" | ||
| 4259 | ``` | ||
| 4260 | |||
| 4261 | <YueDisplay> | ||
| 4262 | |||
| 4263 | ```yue | ||
| 4264 | tab = [] | ||
| 4265 | tab[] = "Value" | ||
| 4266 | ``` | ||
| 4267 | |||
| 4268 | </YueDisplay> | ||
| 4269 | |||
| 4270 |   你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中: | ||
| 4271 | |||
| 4272 | ```yuescript | ||
| 4273 | tbA = [1, 2, 3] | ||
| 4274 | tbB = [4, 5, 6] | ||
| 4275 | tbA[] = ...tbB | ||
| 4276 | -- tbA 现在为 [1, 2, 3, 4, 5, 6] | ||
| 4277 | ``` | ||
| 4278 | |||
| 4279 | <YueDisplay> | ||
| 4280 | |||
| 4281 | ```yue | ||
| 4282 | tbA = [1, 2, 3] | ||
| 4283 | tbB = [4, 5, 6] | ||
| 4284 | tbA[] = ...tbB | ||
| 4285 | -- tbA 现在为 [1, 2, 3, 4, 5, 6] | ||
| 4286 | ``` | ||
| 4287 | |||
| 4288 | </YueDisplay> | ||
| 4289 | |||
| 4290 | ## 表扩展 | ||
| 4291 | |||
| 4292 |   你可以使用前置 `...` 操作符在 Lua 表中插入数组表或哈希表。 | ||
| 4293 | |||
| 4294 | ```yuescript | ||
| 4295 | parts = | ||
| 4296 | * "shoulders" | ||
| 4297 | * "knees" | ||
| 4298 | lyrics = | ||
| 4299 | * "head" | ||
| 4300 | * ...parts | ||
| 4301 | * "and" | ||
| 4302 | * "toes" | ||
| 4303 | |||
| 4304 | copy = {...other} | ||
| 4305 | |||
| 4306 | a = {1, 2, 3, x: 1} | ||
| 4307 | b = {4, 5, y: 1} | ||
| 4308 | merge = {...a, ...b} | ||
| 4309 | ``` | ||
| 4310 | |||
| 4311 | <YueDisplay> | ||
| 4312 | |||
| 4313 | ```yue | ||
| 4314 | parts = | ||
| 4315 | * "shoulders" | ||
| 4316 | * "knees" | ||
| 4317 | lyrics = | ||
| 4318 | * "head" | ||
| 4319 | * ...parts | ||
| 4320 | * "and" | ||
| 4321 | * "toes" | ||
| 4322 | |||
| 4323 | copy = {...other} | ||
| 4324 | |||
| 4325 | a = {1, 2, 3, x: 1} | ||
| 4326 | b = {4, 5, y: 1} | ||
| 4327 | merge = {...a, ...b} | ||
| 4328 | ``` | ||
| 4329 | |||
| 4330 | </YueDisplay> | ||
| 4331 | |||
| 4332 | ## 表反向索引 | ||
| 4333 | |||
| 4334 |   你可以使用 **#** 操作符来反向索引表中的元素。 | ||
| 4335 | |||
| 4336 | ```yuescript | ||
| 4337 | last = data.items[#] | ||
| 4338 | second_last = data.items[#-1] | ||
| 4339 | data.items[#] = 1 | ||
| 4340 | ``` | ||
| 4341 | |||
| 4342 | <YueDisplay> | ||
| 4343 | |||
| 4344 | ```yue | ||
| 4345 | last = data.items[#] | ||
| 4346 | second_last = data.items[#-1] | ||
| 4347 | data.items[#] = 1 | ||
| 4348 | ``` | ||
| 4349 | |||
| 4350 | </YueDisplay> | ||
| 4351 | |||
| 4352 | ## 元表 | ||
| 4353 | |||
| 4354 |   **<>** 操作符可提供元表操作的快捷方式。 | ||
| 4355 | |||
| 4356 | ### 元表创建 | ||
| 4357 | |||
| 4358 |   使用空括号 **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。 | ||
| 4359 | |||
| 4360 | ```yuescript | ||
| 4361 | mt = {} | ||
| 4362 | add = (right) => <>: mt, value: @value + right.value | ||
| 4363 | mt.__add = add | ||
| 4364 | |||
| 4365 | a = <>: mt, value: 1 | ||
| 4366 | -- 使用与临时变量名相同的字段名,将临时变量赋值给元表 | ||
| 4367 | b = :<add>, value: 2 | ||
| 4368 | c = <add>: mt.__add, value: 3 | ||
| 4369 | |||
| 4370 | d = a + b + c | ||
| 4371 | print d.value | ||
| 4372 | |||
| 4373 | close _ = <close>: -> print "超出范围" | ||
| 4374 | ``` | ||
| 4375 | |||
| 4376 | <YueDisplay> | ||
| 4377 | |||
| 4378 | ```yue | ||
| 4379 | mt = {} | ||
| 4380 | add = (right) => <>: mt, value: @value + right.value | ||
| 4381 | mt.__add = add | ||
| 4382 | |||
| 4383 | a = <>: mt, value: 1 | ||
| 4384 | -- 使用与临时变量名相同的字段名,将临时变量赋值给元表 | ||
| 4385 | b = :<add>, value: 2 | ||
| 4386 | c = <add>: mt.__add, value: 3 | ||
| 4387 | |||
| 4388 | d = a + b + c | ||
| 4389 | print d.value | ||
| 4390 | |||
| 4391 | close _ = <close>: -> print "超出范围" | ||
| 4392 | ``` | ||
| 4393 | |||
| 4394 | </YueDisplay> | ||
| 4395 | |||
| 4396 | ### 元表访问 | ||
| 4397 | |||
| 4398 |   使用 **<>** 或被 **<>** 包围的元方法名或在 **<>** 中编写某些表达式来访问元表。 | ||
| 4399 | |||
| 4400 | ```yuescript | ||
| 4401 | -- 使用包含字段 "value" 的元表创建 | ||
| 4402 | tb = <"value">: 123 | ||
| 4403 | tb.<index> = tb.<> | ||
| 4404 | print tb.value | ||
| 4405 | |||
| 4406 | tb.<> = __index: {item: "hello"} | ||
| 4407 | print tb.item | ||
| 4408 | ``` | ||
| 4409 | |||
| 4410 | <YueDisplay> | ||
| 4411 | |||
| 4412 | ```yue | ||
| 4413 | -- 使用包含字段 "value" 的元表创建 | ||
| 4414 | tb = <"value">: 123 | ||
| 4415 | tb.<index> = tb.<> | ||
| 4416 | print tb.value | ||
| 4417 | tb.<> = __index: {item: "hello"} | ||
| 4418 | print tb.item | ||
| 4419 | ``` | ||
| 4420 | |||
| 4421 | </YueDisplay> | ||
| 4422 | |||
| 4423 | ### 元表解构 | ||
| 4424 | |||
| 4425 |   使用被 **<>** 包围的元方法键解构元表。 | ||
| 4426 | |||
| 4427 | ```yuescript | ||
| 4428 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4429 | print item, new, close, getter | ||
| 4430 | ``` | ||
| 4431 | |||
| 4432 | <YueDisplay> | ||
| 4433 | |||
| 4434 | ```yue | ||
| 4435 | {item, :new, :<close>, <index>: getter} = tb | ||
| 4436 | print item, new, close, getter | ||
| 4437 | ``` | ||
| 4438 | |||
| 4439 | </YueDisplay> | ||
| 4440 | |||
| 4441 | ## 存在性 | ||
| 4442 | |||
| 4443 |   **?** 运算符可以在多种上下文中用来检查存在性。 | ||
| 4444 | |||
| 4445 | ```yuescript | ||
| 4446 | func?! | ||
| 4447 | print abc?["你好 世界"]?.xyz | ||
| 4448 | |||
| 4449 | x = tab?.value | ||
| 4450 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4451 | |||
| 4452 | if print and x? | ||
| 4453 | print x | ||
| 4454 | |||
| 4455 | with? io.open "test.txt", "w" | ||
| 4456 | \write "你好" | ||
| 4457 | \close! | ||
| 4458 | ``` | ||
| 4459 | |||
| 4460 | <YueDisplay> | ||
| 4461 | |||
| 4462 | ```yue | ||
| 4463 | func?! | ||
| 4464 | print abc?["你好 世界"]?.xyz | ||
| 4465 | |||
| 4466 | x = tab?.value | ||
| 4467 | len = utf8?.len or string?.len or (o) -> #o | ||
| 4468 | |||
| 4469 | if print and x? | ||
| 4470 | print x | ||
| 4471 | |||
| 4472 | with? io.open "test.txt", "w" | ||
| 4473 | \write "你好" | ||
| 4474 | \close! | ||
| 4475 | ``` | ||
| 4476 | |||
| 4477 | </YueDisplay> | ||
| 4478 | |||
| 4479 | ## 管道 | ||
| 4480 | |||
| 4481 |   与其使用一系列嵌套的函数调用,你还可以考虑使用运算符 **|>** 来传递值。 | ||
| 4482 | |||
| 4483 | ```yuescript | ||
| 4484 | "你好" |> print | ||
| 4485 | 1 |> print 2 -- 将管道项作为第一个参数插入 | ||
| 4486 | 2 |> print 1, _, 3 -- 带有占位符的管道 | ||
| 4487 | |||
| 4488 | -- 多行的管道表达式 | ||
| 4489 | readFile "example.txt" | ||
| 4490 | |> extract language, {} | ||
| 4491 | |> parse language | ||
| 4492 | |> emit | ||
| 4493 | |> render | ||
| 4494 | |||
| 4495 | ``` | ||
| 4496 | |||
| 4497 | <YueDisplay> | ||
| 4498 | |||
| 4499 | ```yue | ||
| 4500 | "你好" |> print | ||
| 4501 | 1 |> print 2 -- 将管道项作为第一个参数插入 | ||
| 4502 | 2 |> print 1, _, 3 -- 带有占位符的管道 | ||
| 4503 | -- 多行的管道表达式 | ||
| 4504 | readFile "example.txt" | ||
| 4505 | |> extract language, {} | ||
| 4506 | |> parse language | ||
| 4507 | |> emit | ||
| 4508 | |> render | ||
| 4509 | |||
| 4510 | ``` | ||
| 4511 | |||
| 4512 | </YueDisplay> | ||
| 4513 | |||
| 4514 | ## 空值合并 | ||
| 4515 | |||
| 4516 |   如果其左操作数不是 **nil**,则nil合并运算符 **??** 返回其左操作数的值;否则,它将计算右操作数并返回其结果。如果左操作数计算结果为非 nil 的值,**??** 运算符将不再计算其右操作数。 | ||
| 4517 | |||
| 4518 | ```yuescript | ||
| 4519 | local a, b, c, d | ||
| 4520 | a = b ?? c ?? d | ||
| 4521 | func a ?? {} | ||
| 4522 | |||
| 4523 | a ??= false | ||
| 4524 | ``` | ||
| 4525 | |||
| 4526 | <YueDisplay> | ||
| 4527 | |||
| 4528 | ```yue | ||
| 4529 | local a, b, c, d | ||
| 4530 | a = b ?? c ?? d | ||
| 4531 | func a ?? {} | ||
| 4532 | a ??= false | ||
| 4533 | ``` | ||
| 4534 | |||
| 4535 | </YueDisplay> | ||
| 4536 | |||
| 4537 | ## 隐式对象 | ||
| 4538 | |||
| 4539 |   你可以在表格块内使用符号 **\*** 或是 **-** 开始编写一系列隐式结构。如果你正在创建隐式对象,对象的字段必须具有相同的缩进。 | ||
| 4540 | |||
| 4541 | ```yuescript | ||
| 4542 | -- 赋值时使用隐式对象 | ||
| 4543 | list = | ||
| 4544 | * 1 | ||
| 4545 | * 2 | ||
| 4546 | * 3 | ||
| 4547 | |||
| 4548 | -- 函数调用时使用隐式对象 | ||
| 4549 | func | ||
| 4550 | * 1 | ||
| 4551 | * 2 | ||
| 4552 | * 3 | ||
| 4553 | |||
| 4554 | -- 返回时使用隐式对象 | ||
| 4555 | f = -> | ||
| 4556 | return | ||
| 4557 | * 1 | ||
| 4558 | * 2 | ||
| 4559 | * 3 | ||
| 4560 | |||
| 4561 | -- 表格时使用隐式对象 | ||
| 4562 | tb = | ||
| 4563 | name: "abc" | ||
| 4564 | |||
| 4565 | values: | ||
| 4566 | - "a" | ||
| 4567 | - "b" | ||
| 4568 | - "c" | ||
| 4569 | |||
| 4570 | objects: | ||
| 4571 | - name: "a" | ||
| 4572 | value: 1 | ||
| 4573 | func: => @value + 1 | ||
| 4574 | tb: | ||
| 4575 | fieldA: 1 | ||
| 4576 | |||
| 4577 | - name: "b" | ||
| 4578 | value: 2 | ||
| 4579 | func: => @value + 2 | ||
| 4580 | tb: { } | ||
| 4581 | ``` | ||
| 4582 | |||
| 4583 | <YueDisplay> | ||
| 4584 | |||
| 4585 | ```yue | ||
| 4586 | -- 赋值时使用隐式对象 | ||
| 4587 | list = | ||
| 4588 | * 1 | ||
| 4589 | * 2 | ||
| 4590 | * 3 | ||
| 4591 | |||
| 4592 | -- 函数调用时使用隐式对象 | ||
| 4593 | func | ||
| 4594 | * 1 | ||
| 4595 | * 2 | ||
| 4596 | * 3 | ||
| 4597 | |||
| 4598 | -- 返回时使用隐式对象 | ||
| 4599 | f = -> | ||
| 4600 | return | ||
| 4601 | * 1 | ||
| 4602 | * 2 | ||
| 4603 | * 3 | ||
| 4604 | |||
| 4605 | -- 表格时使用隐式对象 | ||
| 4606 | tb = | ||
| 4607 | name: "abc" | ||
| 4608 | |||
| 4609 | values: | ||
| 4610 | - "a" | ||
| 4611 | - "b" | ||
| 4612 | - "c" | ||
| 4613 | |||
| 4614 | objects: | ||
| 4615 | - name: "a" | ||
| 4616 | value: 1 | ||
| 4617 | func: => @value + 1 | ||
| 4618 | tb: | ||
| 4619 | fieldA: 1 | ||
| 4620 | |||
| 4621 | - name: "b" | ||
| 4622 | value: 2 | ||
| 4623 | func: => @value + 2 | ||
| 4624 | tb: { } | ||
| 4625 | ``` | ||
| 4626 | |||
| 4627 | </YueDisplay> | ||
| 4628 | |||
| 4629 | # 字面量 | ||
| 4630 | |||
| 4631 |   Lua 中的所有基本字面量都可以在月之脚本中使用。包括数字、字符串、布尔值和 **nil**。 | ||
| 4632 | |||
| 4633 |   但与 Lua 不同的是,单引号和双引号字符串内部允许有换行: | ||
| 4634 | |||
| 4635 | ```yuescript | ||
| 4636 | some_string = "这是一个字符串 | ||
| 4637 | 并包括一个换行。" | ||
| 4638 | |||
| 4639 | -- 使用#{}语法可以将表达式插入到字符串字面量中。 | ||
| 4640 | -- 字符串插值只在双引号字符串中可用。 | ||
| 4641 | print "我有#{math.random! * 100}%的把握。" | ||
| 4642 | ``` | ||
| 4643 | |||
| 4644 | <YueDisplay> | ||
| 4645 | |||
| 4646 | ```yue | ||
| 4647 | some_string = "这是一个字符串 | ||
| 4648 | 并包括一个换行。" | ||
| 4649 | |||
| 4650 | -- 使用#{}语法可以将表达式插入到字符串字面量中。 | ||
| 4651 | -- 字符串插值只在双引号字符串中可用。 | ||
| 4652 | print "我有#{math.random! * 100}%的把握。" | ||
| 4653 | ``` | ||
| 4654 | |||
| 4655 | </YueDisplay> | ||
| 4656 | |||
| 4657 | ## 数字字面量 | ||
| 4658 | |||
| 4659 |   你可以在数字字面量中使用下划线来增加可读性。 | ||
| 4660 | |||
| 4661 | ```yuescript | ||
| 4662 | integer = 1_000_000 | ||
| 4663 | hex = 0xEF_BB_BF | ||
| 4664 | binary = 0B10011 | ||
| 4665 | ``` | ||
| 4666 | |||
| 4667 | <YueDisplay> | ||
| 4668 | |||
| 4669 | ```yue | ||
| 4670 | integer = 1_000_000 | ||
| 4671 | hex = 0xEF_BB_BF | ||
| 4672 | binary = 0B10011 | ||
| 4673 | ``` | ||
| 4674 | |||
| 4675 | </YueDisplay> | ||
| 4676 | |||
| 4677 | ## YAML 风格字符串 | ||
| 4678 | |||
| 4679 |   使用 `|` 前缀标记一个多行 YAML 风格字符串: | ||
| 4680 | |||
| 4681 | ```yuescript | ||
| 4682 | str = | | ||
| 4683 | key: value | ||
| 4684 | list: | ||
| 4685 | - item1 | ||
| 4686 | - #{expr} | ||
| 4687 | ``` | ||
| 4688 | |||
| 4689 | <YueDisplay> | ||
| 4690 | |||
| 4691 | ```yue | ||
| 4692 | str = | | ||
| 4693 | key: value | ||
| 4694 | list: | ||
| 4695 | - item1 | ||
| 4696 | - #{expr} | ||
| 4697 | ``` | ||
| 4698 | |||
| 4699 | </YueDisplay> | ||
| 4700 | |||
| 4701 |   其效果类似于原生 Lua 的多行拼接,所有文本(含换行)将被保留下来,并支持 `#{...}` 语法,通过 `tostring(expr)` 插入表达式结果。 | ||
| 4702 | |||
| 4703 |   YAML 风格的多行字符串会自动检测首行后最小的公共缩进,并从所有行中删除该前缀空白字符。这让你可以在代码中对齐文本,但输出字符串不会带多余缩进。 | ||
| 4704 | |||
| 4705 | ```yuescript | ||
| 4706 | fn = -> | ||
| 4707 | str = | | ||
| 4708 | foo: | ||
| 4709 | bar: baz | ||
| 4710 | return str | ||
| 4711 | ``` | ||
| 4712 | |||
| 4713 | <YueDisplay> | ||
| 4714 | |||
| 4715 | ```yue | ||
| 4716 | fn = -> | ||
| 4717 | str = | | ||
| 4718 | foo: | ||
| 4719 | bar: baz | ||
| 4720 | return str | ||
| 4721 | ``` | ||
| 4722 | |||
| 4723 | </YueDisplay> | ||
| 4724 | |||
| 4725 |   输出字符串中的 foo: 对齐到行首,不会带有函数缩进空格。保留内部缩进的相对结构,适合书写结构化嵌套样式的内容。 | ||
| 4726 | |||
| 4727 |   支持自动处理字符中的引号、反斜杠等特殊符号,无需手动转义: | ||
| 4728 | |||
| 4729 | ```yuescript | ||
| 4730 | str = | | ||
| 4731 | path: "C:\Program Files\App" | ||
| 4732 | note: 'He said: "#{Hello}!"' | ||
| 4733 | ``` | ||
| 4734 | |||
| 4735 | <YueDisplay> | ||
| 4736 | |||
| 4737 | ```yue | ||
| 4738 | str = | | ||
| 4739 | path: "C:\Program Files\App" | ||
| 4740 | note: 'He said: "#{Hello}!"' | ||
| 4741 | ``` | ||
| 4742 | |||
| 4743 | </YueDisplay> | ||
| 4744 | |||
| 4745 | # 模块 | ||
| 4746 | |||
| 4747 | ## 导入 | ||
| 4748 | |||
| 4749 |   导入语句是一个语法糖,用于需要引入一个模块或者从已导入的模块中提取子项目。从模块导入的变量默认为不可修改的常量。 | ||
| 4750 | |||
| 4751 | ```yuescript | ||
| 4752 | -- 用作表解构 | ||
| 4753 | do | ||
| 4754 | import insert, concat from table | ||
| 4755 | -- 当给 insert, concat 变量赋值时,编译器会报告错误 | ||
| 4756 | import C, Ct, Cmt from require "lpeg" | ||
| 4757 | -- 快捷写法引入模块的子项 | ||
| 4758 | import x, y, z from 'mymodule' | ||
| 4759 | -- 使用Python风格的导入 | ||
| 4760 | from 'module' import a, b, c | ||
| 4761 | |||
| 4762 | -- 快捷地导入一个模块 | ||
| 4763 | do | ||
| 4764 | import 'module' | ||
| 4765 | import 'module_x' | ||
| 4766 | import "d-a-s-h-e-s" | ||
| 4767 | import "module.part" | ||
| 4768 | |||
| 4769 | -- 导入模块后起一个别名使用,或是进行导入模块表的解构 | ||
| 4770 | do | ||
| 4771 | import "player" as PlayerModule | ||
| 4772 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4773 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4774 | ``` | ||
| 4775 | |||
| 4776 | <YueDisplay> | ||
| 4777 | |||
| 4778 | ```yue | ||
| 4779 | -- 用作表解构 | ||
| 4780 | do | ||
| 4781 | import insert, concat from table | ||
| 4782 | -- 当给 insert, concat 变量赋值时,编译器会报告错误 | ||
| 4783 | import C, Ct, Cmt from require "lpeg" | ||
| 4784 | -- 快捷写法引入模块的子项 | ||
| 4785 | import x, y, z from 'mymodule' | ||
| 4786 | -- 使用Python风格的导入 | ||
| 4787 | from 'module' import a, b, c | ||
| 4788 | |||
| 4789 | -- 快捷地导入一个模块 | ||
| 4790 | do | ||
| 4791 | import 'module' | ||
| 4792 | import 'module_x' | ||
| 4793 | import "d-a-s-h-e-s" | ||
| 4794 | import "module.part" | ||
| 4795 | |||
| 4796 | -- 导入模块后起一个别名使用,或是进行导入模块表的解构 | ||
| 4797 | do | ||
| 4798 | import "player" as PlayerModule | ||
| 4799 | import "lpeg" as :C, :Ct, :Cmt | ||
| 4800 | import "export" as {one, two, Something:{umm:{ch}}} | ||
| 4801 | ``` | ||
| 4802 | |||
| 4803 | </YueDisplay> | ||
| 4804 | |||
| 4805 | ## 导入全局变量 | ||
| 4806 | |||
| 4807 |   你可以使用 `import` 将指定的全局变量导入到本地变量中。当导入一系列对全局变量的链式访问时,最后一个访问的字段将被赋值给本地变量。 | ||
| 4808 | |||
| 4809 | ```yuescript | ||
| 4810 | do | ||
| 4811 | import tostring | ||
| 4812 | import table.concat | ||
| 4813 | print concat ["a", tostring 1] | ||
| 4814 | ``` | ||
| 4815 | |||
| 4816 | <YueDisplay> | ||
| 4817 | |||
| 4818 | ```yue | ||
| 4819 | do | ||
| 4820 | import tostring | ||
| 4821 | import table.concat | ||
| 4822 | print concat ["a", tostring 1] | ||
| 4823 | ``` | ||
| 4824 | |||
| 4825 | </YueDisplay> | ||
| 4826 | |||
| 4827 | ### 自动全局变量导入 | ||
| 4828 | |||
| 4829 |   在一个代码块的顶部写 `import global`,会将当前作用域中尚未显式声明或赋值过的变量名,自动导入为本地常量,并在该语句的位置绑定到同名的全局变量。 | ||
| 4830 | |||
| 4831 |   但是在同一作用域中被显式声明为全局的变量不会被自动导入,因此可以继续进行赋值操作。 | ||
| 4832 | |||
| 4833 | ```yuescript | ||
| 4834 | do | ||
| 4835 | import global | ||
| 4836 | print "hello" | ||
| 4837 | math.random 3 | ||
| 4838 | -- print = nil -- 报错:自动导入的全局变量为常量 | ||
| 4839 | |||
| 4840 | do | ||
| 4841 | -- 被显式声明为全局的变量不会被自动导入 | ||
| 4842 | import global | ||
| 4843 | global FLAG | ||
| 4844 | print FLAG | ||
| 4845 | FLAG = 123 | ||
| 4846 | ``` | ||
| 4847 | |||
| 4848 | <YueDisplay> | ||
| 4849 | |||
| 4850 | ```yue | ||
| 4851 | do | ||
| 4852 | import global | ||
| 4853 | print "hello" | ||
| 4854 | math.random 3 | ||
| 4855 | -- print = nil -- 报错:自动导入的全局变量是常量 | ||
| 4856 | |||
| 4857 | do | ||
| 4858 | -- 被显式声明为全局的变量不会被自动导入 | ||
| 4859 | import global | ||
| 4860 | global FLAG | ||
| 4861 | print FLAG | ||
| 4862 | FLAG = 123 | ||
| 4863 | ``` | ||
| 4864 | |||
| 4865 | </YueDisplay> | ||
| 4866 | |||
| 4867 | ## 导出 | ||
| 4868 | |||
| 4869 |   导出语句提供了一种简洁的方式来定义当前的模块。 | ||
| 4870 | |||
| 4871 | ### 命名导出 | ||
| 4872 | |||
| 4873 |   带命名的导出将定义一个局部变量,并在导出的表中添加一个同名的字段。 | ||
| 4874 | |||
| 4875 | ```yuescript | ||
| 4876 | export a, b, c = 1, 2, 3 | ||
| 4877 | export cool = "cat" | ||
| 4878 | |||
| 4879 | export What = if this | ||
| 4880 | "abc" | ||
| 4881 | else | ||
| 4882 | "def" | ||
| 4883 | |||
| 4884 | export y = -> | ||
| 4885 | hallo = 3434 | ||
| 4886 | |||
| 4887 | export class Something | ||
| 4888 | umm: "cool" | ||
| 4889 | ``` | ||
| 4890 | |||
| 4891 | <YueDisplay> | ||
| 4892 | |||
| 4893 | ```yue | ||
| 4894 | export a, b, c = 1, 2, 3 | ||
| 4895 | export cool = "cat" | ||
| 4896 | |||
| 4897 | export What = if this | ||
| 4898 | "abc" | ||
| 4899 | else | ||
| 4900 | "def" | ||
| 4901 | |||
| 4902 | export y = -> | ||
| 4903 | hallo = 3434 | ||
| 4904 | |||
| 4905 | export class Something | ||
| 4906 | umm: "cool" | ||
| 4907 | ``` | ||
| 4908 | |||
| 4909 | </YueDisplay> | ||
| 4910 | |||
| 4911 |   使用解构进行命名导出。 | ||
| 4912 | |||
| 4913 | ```yuescript | ||
| 4914 | export :loadstring, to_lua: tolua = yue | ||
| 4915 | export {itemA: {:fieldA = '默认值'}} = tb | ||
| 4916 | ``` | ||
| 4917 | |||
| 4918 | <YueDisplay> | ||
| 4919 | |||
| 4920 | ```yue | ||
| 4921 | export :loadstring, to_lua: tolua = yue | ||
| 4922 | export {itemA: {:fieldA = '默认值'}} = tb | ||
| 4923 | ``` | ||
| 4924 | |||
| 4925 | </YueDisplay> | ||
| 4926 | |||
| 4927 |   从模块导出命名项目时,可以不用创建局部变量。 | ||
| 4928 | |||
| 4929 | ```yuescript | ||
| 4930 | export.itemA = tb | ||
| 4931 | export.<index> = items | ||
| 4932 | export["a-b-c"] = 123 | ||
| 4933 | ``` | ||
| 4934 | |||
| 4935 | <YueDisplay> | ||
| 4936 | |||
| 4937 | ```yue | ||
| 4938 | export.itemA = tb | ||
| 4939 | export.<index> = items | ||
| 4940 | export["a-b-c"] = 123 | ||
| 4941 | ``` | ||
| 4942 | |||
| 4943 | </YueDisplay> | ||
| 4944 | |||
| 4945 | ### 未命名导出 | ||
| 4946 | |||
| 4947 |   未命名导出会将要导出的目标项目添加到导出表的数组部分。 | ||
| 4948 | |||
| 4949 | ```yuescript | ||
| 4950 | d, e, f = 3, 2, 1 | ||
| 4951 | export d, e, f | ||
| 4952 | |||
| 4953 | export if this | ||
| 4954 | 123 | ||
| 4955 | else | ||
| 4956 | 456 | ||
| 4957 | |||
| 4958 | export with tmp | ||
| 4959 | j = 2000 | ||
| 4960 | ``` | ||
| 4961 | |||
| 4962 | <YueDisplay> | ||
| 4963 | |||
| 4964 | ```yue | ||
| 4965 | d, e, f = 3, 2, 1 | ||
| 4966 | export d, e, f | ||
| 4967 | |||
| 4968 | export if this | ||
| 4969 | 123 | ||
| 4970 | else | ||
| 4971 | 456 | ||
| 4972 | |||
| 4973 | export with tmp | ||
| 4974 | j = 2000 | ||
| 4975 | ``` | ||
| 4976 | |||
| 4977 | </YueDisplay> | ||
| 4978 | |||
| 4979 | ### 默认导出 | ||
| 4980 | |||
| 4981 |   在导出语句中使用 **default** 关键字,来替换导出的表为一个目标的对象。 | ||
| 4982 | |||
| 4983 | ```yuescript | ||
| 4984 | export default -> | ||
| 4985 | print "你好" | ||
| 4986 | 123 | ||
| 4987 | ``` | ||
| 4988 | |||
| 4989 | <YueDisplay> | ||
| 4990 | |||
| 4991 | ```yue | ||
| 4992 | export default -> | ||
| 4993 | print "你好" | ||
| 4994 | 123 | ||
| 4995 | ``` | ||
| 4996 | |||
| 4997 | </YueDisplay> | ||
| 4998 | |||
| 4999 | # MIT 许可证 | ||
| 5000 | |||
| 5001 | 版权 (c) 2017-2026 李瑾 \<dragon-fly@qq.com\> | ||
| 5002 | |||
| 5003 | 特此免费授予任何获得本软件副本和相关文档文件(下称“软件”)的人不受限制地处置该软件的权利,包括不受限制地使用、复制、修改、合并、发布、分发、转授许可和/或出售该软件副本,以及再授权被配发了本软件的人如上的权利,须在下列条件下: | ||
| 5004 | 上述版权声明和本许可声明应包含在该软件的所有副本或实质成分中。 | ||
| 5005 | 本软件是“如此”提供的,没有任何形式的明示或暗示的保证,包括但不限于对适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人都不对任何索赔、损害或其他责任负责,无论这些追责来自合同、侵权或其它行为中,还是产生于、源于或有关于本软件以及本软件的使用或其它处置。 | ||
| 5006 | |||
| 5007 | # 月之脚本语言库 | ||
| 5008 | |||
| 5009 | 在 Lua 中使用 `local yue = require("yue")` 来访问。 | ||
| 5010 | |||
| 5011 | ## yue | ||
| 5012 | |||
| 5013 | **描述:** | ||
| 5014 | |||
| 5015 | 月之脚本语言库。 | ||
| 5016 | |||
| 5017 | ### version | ||
| 5018 | |||
| 5019 | **类型:** 成员变量。 | ||
| 5020 | |||
| 5021 | **描述:** | ||
| 5022 | |||
| 5023 | 月之脚本版本。 | ||
| 5024 | |||
| 5025 | **签名:** | ||
| 5026 | |||
| 5027 | ```lua | ||
| 5028 | version: string | ||
| 5029 | ``` | ||
| 5030 | |||
| 5031 | ### dirsep | ||
| 5032 | |||
| 5033 | **类型:** 成员变量。 | ||
| 5034 | |||
| 5035 | **描述:** | ||
| 5036 | |||
| 5037 | 当前平台的文件分隔符。 | ||
| 5038 | |||
| 5039 | **签名:** | ||
| 5040 | |||
| 5041 | ```lua | ||
| 5042 | dirsep: string | ||
| 5043 | ``` | ||
| 5044 | |||
| 5045 | ### yue_compiled | ||
| 5046 | |||
| 5047 | **类型:** 成员变量。 | ||
| 5048 | |||
| 5049 | **描述:** | ||
| 5050 | |||
| 5051 | 编译模块代码缓存。 | ||
| 5052 | |||
| 5053 | **签名:** | ||
| 5054 | |||
| 5055 | ```lua | ||
| 5056 | yue_compiled: {string: string} | ||
| 5057 | ``` | ||
| 5058 | |||
| 5059 | ### to_lua | ||
| 5060 | |||
| 5061 | **类型:** 函数。 | ||
| 5062 | |||
| 5063 | **描述:** | ||
| 5064 | |||
| 5065 | 月之脚本的编译函数。它将 YueScript 代码编译为 Lua 代码。 | ||
| 5066 | |||
| 5067 | **签名:** | ||
| 5068 | |||
| 5069 | ```lua | ||
| 5070 | to_lua: function(code: string, config?: Config): | ||
| 5071 | --[[codes]] string | nil, | ||
| 5072 | --[[error]] string | nil, | ||
| 5073 | --[[globals]] {{string, integer, integer}} | nil | ||
| 5074 | ``` | ||
| 5075 | |||
| 5076 | **参数:** | ||
| 5077 | |||
| 5078 | | 参数名 | 类型 | 描述 | | ||
| 5079 | | ------ | ------ | ------------------- | | ||
| 5080 | | code | string | YueScript 代码。 | | ||
| 5081 | | config | Config | [可选] 编译器选项。 | | ||
| 5082 | |||
| 5083 | **返回值:** | ||
| 5084 | |||
| 5085 | | 返回类型 | 描述 | | ||
| 5086 | | ----------------------------------- | ------------------------------------------------------------------------------------------ | | ||
| 5087 | | string \| nil | 编译后的 Lua 代码,如果编译失败则为 nil。 | | ||
| 5088 | | string \| nil | 错误消息,如果编译成功则为 nil。 | | ||
| 5089 | | {{string, integer, integer}} \| nil | 代码中出现的全局变量(带有名称、行和列),如果编译器选项 `lint_global` 为 false 则为 nil。 | | ||
| 5090 | |||
| 5091 | ### file_exist | ||
| 5092 | |||
| 5093 | **类型:** 函数。 | ||
| 5094 | |||
| 5095 | **描述:** | ||
| 5096 | |||
| 5097 | 检查源文件是否存在的函数。可以覆盖该函数以自定义行为。 | ||
| 5098 | |||
| 5099 | **签名:** | ||
| 5100 | |||
| 5101 | ```lua | ||
| 5102 | file_exist: function(filename: string): boolean | ||
| 5103 | ``` | ||
| 5104 | |||
| 5105 | **参数:** | ||
| 5106 | |||
| 5107 | | 参数名 | 类型 | 描述 | | ||
| 5108 | | -------- | ------ | -------- | | ||
| 5109 | | filename | string | 文件名。 | | ||
| 5110 | |||
| 5111 | **返回值:** | ||
| 5112 | |||
| 5113 | | 返回类型 | 描述 | | ||
| 5114 | | -------- | -------------- | | ||
| 5115 | | boolean | 文件是否存在。 | | ||
| 5116 | |||
| 5117 | ### read_file | ||
| 5118 | |||
| 5119 | **类型:** 函数。 | ||
| 5120 | |||
| 5121 | **描述:** | ||
| 5122 | |||
| 5123 | 读取源文件的函数。可以覆盖该函数以自定义行为。 | ||
| 5124 | |||
| 5125 | **签名:** | ||
| 5126 | |||
| 5127 | ```lua | ||
| 5128 | read_file: function(filename: string): string | ||
| 5129 | ``` | ||
| 5130 | |||
| 5131 | **参数:** | ||
| 5132 | |||
| 5133 | | 参数名 | 类型 | 描述 | | ||
| 5134 | | -------- | ------ | -------- | | ||
| 5135 | | filename | string | 文件名。 | | ||
| 5136 | |||
| 5137 | **返回值:** | ||
| 5138 | |||
| 5139 | | 返回类型 | 描述 | | ||
| 5140 | | -------- | ---------- | | ||
| 5141 | | string | 文件内容。 | | ||
| 5142 | |||
| 5143 | ### insert_loader | ||
| 5144 | |||
| 5145 | **类型:** 函数。 | ||
| 5146 | |||
| 5147 | **描述:** | ||
| 5148 | |||
| 5149 | 将 YueScript 加载器插入到 Lua 包加载器(搜索器)中。 | ||
| 5150 | |||
| 5151 | **签名:** | ||
| 5152 | |||
| 5153 | ```lua | ||
| 5154 | insert_loader: function(pos?: integer): boolean | ||
| 5155 | ``` | ||
| 5156 | |||
| 5157 | **参数:** | ||
| 5158 | |||
| 5159 | | 参数名 | 类型 | 描述 | | ||
| 5160 | | ------ | ------- | ------------------------------------- | | ||
| 5161 | | pos | integer | [可选] 要插入加载器的位置。默认为 3。 | | ||
| 5162 | |||
| 5163 | **返回值:** | ||
| 5164 | |||
| 5165 | | 返回类型 | 描述 | | ||
| 5166 | | -------- | ---------------------------------------------------- | | ||
| 5167 | | boolean | 是否成功插入加载器。如果加载器已经插入,则返回失败。 | | ||
| 5168 | |||
| 5169 | ### remove_loader | ||
| 5170 | |||
| 5171 | **类型:** 函数。 | ||
| 5172 | |||
| 5173 | **描述:** | ||
| 5174 | |||
| 5175 | 从 Lua 包加载器(搜索器)中移除 YueScript 加载器。 | ||
| 5176 | |||
| 5177 | **签名:** | ||
| 5178 | |||
| 5179 | ```lua | ||
| 5180 | remove_loader: function(): boolean | ||
| 5181 | ``` | ||
| 5182 | |||
| 5183 | **返回值:** | ||
| 5184 | |||
| 5185 | | 返回类型 | 描述 | | ||
| 5186 | | -------- | -------------------------------------------------- | | ||
| 5187 | | boolean | 是否成功移除加载器。如果加载器未插入,则返回失败。 | | ||
| 5188 | |||
| 5189 | ### loadstring | ||
| 5190 | |||
| 5191 | **类型:** 函数。 | ||
| 5192 | |||
| 5193 | **描述:** | ||
| 5194 | |||
| 5195 | 将 YueScript 代码字符串加载为一个函数。 | ||
| 5196 | |||
| 5197 | **签名:** | ||
| 5198 | |||
| 5199 | ```lua | ||
| 5200 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | ||
| 5201 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5202 | --[[error]] string | nil | ||
| 5203 | ``` | ||
| 5204 | |||
| 5205 | **参数:** | ||
| 5206 | |||
| 5207 | | 参数名 | 类型 | 描述 | | ||
| 5208 | | --------- | ------ | ------------------- | | ||
| 5209 | | input | string | YueScript 代码。 | | ||
| 5210 | | chunkname | string | 代码块的名称。 | | ||
| 5211 | | env | table | 环境表。 | | ||
| 5212 | | config | Config | [可选] 编译器选项。 | | ||
| 5213 | |||
| 5214 | **返回值:** | ||
| 5215 | |||
| 5216 | | 返回类型 | 描述 | | ||
| 5217 | | --------------- | ---------------------------------- | | ||
| 5218 | | function \| nil | 加载的函数,如果加载失败则为 nil。 | | ||
| 5219 | | string \| nil | 错误消息,如果加载成功则为 nil。 | | ||
| 5220 | |||
| 5221 | ### loadstring | ||
| 5222 | |||
| 5223 | **类型:** 函数。 | ||
| 5224 | |||
| 5225 | **描述:** | ||
| 5226 | |||
| 5227 | 将 YueScript 代码字符串加载为一个函数。 | ||
| 5228 | |||
| 5229 | **签名:** | ||
| 5230 | |||
| 5231 | ```lua | ||
| 5232 | loadstring: function(input: string, chunkname: string, config?: Config): | ||
| 5233 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5234 | --[[error]] string | nil | ||
| 5235 | ``` | ||
| 5236 | |||
| 5237 | **参数:** | ||
| 5238 | |||
| 5239 | | 参数名 | 类型 | 描述 | | ||
| 5240 | | --------- | ------ | ------------------- | | ||
| 5241 | | input | string | YueScript 代码。 | | ||
| 5242 | | chunkname | string | 代码块的名称。 | | ||
| 5243 | | config | Config | [可选] 编译器选项。 | | ||
| 5244 | |||
| 5245 | **返回值:** | ||
| 5246 | |||
| 5247 | | 返回类型 | 描述 | | ||
| 5248 | | --------------- | ---------------------------------- | | ||
| 5249 | | function \| nil | 加载的函数,如果加载失败则为 nil。 | | ||
| 5250 | | string \| nil | 错误消息,如果加载成功则为 nil。 | | ||
| 5251 | |||
| 5252 | ### loadstring | ||
| 5253 | |||
| 5254 | **类型:** 函数。 | ||
| 5255 | |||
| 5256 | **描述:** | ||
| 5257 | |||
| 5258 | 将 YueScript 代码字符串加载为一个函数。 | ||
| 5259 | |||
| 5260 | **签名:** | ||
| 5261 | |||
| 5262 | ```lua | ||
| 5263 | loadstring: function(input: string, config?: Config): | ||
| 5264 | --[[loaded function]] nil | function(...: any): (any...), | ||
| 5265 | --[[error]] string | nil | ||
| 5266 | ``` | ||
| 5267 | |||
| 5268 | **参数:** | ||
| 5269 | |||
| 5270 | | 参数名 | 类型 | 描述 | | ||
| 5271 | | ------ | ------ | ------------------- | | ||
| 5272 | | input | string | YueScript 代码。 | | ||
| 5273 | | config | Config | [可选] 编译器选项。 | | ||
| 5274 | |||
| 5275 | **返回值:** | ||
| 5276 | |||
| 5277 | | 返回类型 | 描述 | | ||
| 5278 | | --------------- | ---------------------------------- | | ||
| 5279 | | function \| nil | 加载的函数,如果加载失败则为 nil。 | | ||
| 5280 | | string \| nil | 错误消息,如果加载成功则为 nil。 | | ||
| 5281 | |||
| 5282 | ### loadfile | ||
| 5283 | |||
| 5284 | **类型:** 函数。 | ||
| 5285 | |||
| 5286 | **描述:** | ||
| 5287 | |||
| 5288 | 将 YueScript 代码文件加载为一个函数。 | ||
| 5289 | |||
| 5290 | **签名:** | ||
| 5291 | |||
| 5292 | ```lua | ||
| 5293 | loadfile: function(filename: string, env: table, config?: Config): | ||
| 5294 | nil | function(...: any): (any...), | ||
| 5295 | string | nil | ||
| 5296 | ``` | ||
| 5297 | |||
| 5298 | **参数:** | ||
| 5299 | |||
| 5300 | | 参数名 | 类型 | 描述 | | ||
| 5301 | | -------- | ------ | ------------------- | | ||
| 5302 | | filename | string | 文件名。 | | ||
| 5303 | | env | table | 环境表。 | | ||
| 5304 | | config | Config | [可选] 编译器选项。 | | ||
| 5305 | |||
| 5306 | **返回值:** | ||
| 5307 | |||
| 5308 | | 返回类型 | 描述 | | ||
| 5309 | | --------------- | ---------------------------------- | | ||
| 5310 | | function \| nil | 加载的函数,如果加载失败则为 nil。 | | ||
| 5311 | | string \| nil | 错误消息,如果加载成功则为 nil。 | | ||
| 5312 | |||
| 5313 | ### loadfile | ||
| 5314 | |||
| 5315 | **类型:** 函数。 | ||
| 5316 | |||
| 5317 | **描述:** | ||
| 5318 | |||
| 5319 | 将 YueScript 代码文件加载为一个函数。 | ||
| 5320 | |||
| 5321 | **签名:** | ||
| 5322 | |||
| 5323 | ```lua | ||
| 5324 | loadfile: function(filename: string, config?: Config): | ||
| 5325 | nil | function(...: any): (any...), | ||
| 5326 | string | nil | ||
| 5327 | ``` | ||
| 5328 | |||
| 5329 | **参数:** | ||
| 5330 | |||
| 5331 | | 参数名 | 类型 | 描述 | | ||
| 5332 | | -------- | ------ | ------------------- | | ||
| 5333 | | filename | string | 文件名。 | | ||
| 5334 | | config | Config | [可选] 编译器选项。 | | ||
| 5335 | |||
| 5336 | **返回值:** | ||
| 5337 | |||
| 5338 | | 返回类型 | 描述 | | ||
| 5339 | | --------------- | ---------------------------------- | | ||
| 5340 | | function \| nil | 加载的函数,如果加载失败则为 nil。 | | ||
| 5341 | | string \| nil | 错误消息,如果加载成功则为 nil。 | | ||
| 5342 | |||
| 5343 | ### dofile | ||
| 5344 | |||
| 5345 | **类型:** 函数。 | ||
| 5346 | |||
| 5347 | **描述:** | ||
| 5348 | |||
| 5349 | 将 YueScript 代码文件加载为一个函数并执行。 | ||
| 5350 | |||
| 5351 | **签名:** | ||
| 5352 | |||
| 5353 | ```lua | ||
| 5354 | dofile: function(filename: string, env: table, config?: Config): any... | ||
| 5355 | ``` | ||
| 5356 | |||
| 5357 | **参数:** | ||
| 5358 | |||
| 5359 | | 参数名 | 类型 | 描述 | | ||
| 5360 | | -------- | ------ | ------------------- | | ||
| 5361 | | filename | string | 文件名。 | | ||
| 5362 | | env | table | 环境表。 | | ||
| 5363 | | config | Config | [可选] 编译器选项。 | | ||
| 5364 | |||
| 5365 | **返回值:** | ||
| 5366 | |||
| 5367 | | 返回类型 | 描述 | | ||
| 5368 | | -------- | -------------------------- | | ||
| 5369 | | any... | 加载的函数执行后的返回值。 | | ||
| 5370 | |||
| 5371 | ### dofile | ||
| 5372 | |||
| 5373 | **类型:** 函数。 | ||
| 5374 | |||
| 5375 | **描述:** | ||
| 5376 | |||
| 5377 | 将 YueScript 代码文件加载为一个函数并执行。 | ||
| 5378 | |||
| 5379 | **签名:** | ||
| 5380 | |||
| 5381 | ```lua | ||
| 5382 | dofile: function(filename: string, config?: Config): any... | ||
| 5383 | ``` | ||
| 5384 | |||
| 5385 | **参数:** | ||
| 5386 | |||
| 5387 | | 参数名 | 类型 | 描述 | | ||
| 5388 | | -------- | ------ | ------------------- | | ||
| 5389 | | filename | string | 文件名。 | | ||
| 5390 | | config | Config | [可选] 编译器选项。 | | ||
| 5391 | |||
| 5392 | **返回值:** | ||
| 5393 | |||
| 5394 | | 返回类型 | 描述 | | ||
| 5395 | | -------- | -------------------------- | | ||
| 5396 | | any... | 加载的函数执行后的返回值。 | | ||
| 5397 | |||
| 5398 | ### find_modulepath | ||
| 5399 | |||
| 5400 | **类型:** 函数。 | ||
| 5401 | |||
| 5402 | **描述:** | ||
| 5403 | |||
| 5404 | 将 YueScript 模块名解析为文件路径。 | ||
| 5405 | |||
| 5406 | **签名:** | ||
| 5407 | |||
| 5408 | ```lua | ||
| 5409 | find_modulepath: function(name: string): string | ||
| 5410 | ``` | ||
| 5411 | |||
| 5412 | **参数:** | ||
| 5413 | |||
| 5414 | | 参数名 | 类型 | 描述 | | ||
| 5415 | | ------ | ------ | -------- | | ||
| 5416 | | name | string | 模块名。 | | ||
| 5417 | |||
| 5418 | **返回值:** | ||
| 5419 | |||
| 5420 | | 返回类型 | 描述 | | ||
| 5421 | | -------- | ---------- | | ||
| 5422 | | string | 文件路径。 | | ||
| 5423 | |||
| 5424 | ### pcall | ||
| 5425 | |||
| 5426 | **类型:** 函数。 | ||
| 5427 | |||
| 5428 | **描述:** | ||
| 5429 | |||
| 5430 | 在保护模式下调用一个函数。 | ||
| 5431 | 会捕获任何错误,执行成功则返回成功状态和结果,否则为失败状态和错误信息。 | ||
| 5432 | 当发生错误时,将错误信息中的代码行号重写为 YueScript 代码中的原始行号。 | ||
| 5433 | |||
| 5434 | **签名:** | ||
| 5435 | |||
| 5436 | ```lua | ||
| 5437 | pcall: function(f: function, ...: any): boolean, any... | ||
| 5438 | ``` | ||
| 5439 | |||
| 5440 | **参数:** | ||
| 5441 | |||
| 5442 | | 参数名 | 类型 | 描述 | | ||
| 5443 | | ------ | -------- | -------------------- | | ||
| 5444 | | f | function | 要调用的函数。 | | ||
| 5445 | | ... | any | 要传递给函数的参数。 | | ||
| 5446 | |||
| 5447 | **返回值:** | ||
| 5448 | |||
| 5449 | | 返回类型 | 描述 | | ||
| 5450 | | ------------ | ---------------------------- | | ||
| 5451 | | boolean, ... | 状态码和函数结果或错误信息。 | | ||
| 5452 | |||
| 5453 | ### require | ||
| 5454 | |||
| 5455 | **类型:** 函数。 | ||
| 5456 | |||
| 5457 | **描述:** | ||
| 5458 | |||
| 5459 | 加载给定的模块。可以是 Lua 模块或 YueScript 模块。 | ||
| 5460 | 如果模块是 YueScript 模块且加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。 | ||
| 5461 | |||
| 5462 | **签名:** | ||
| 5463 | |||
| 5464 | ```lua | ||
| 5465 | require: function(name: string): any... | ||
| 5466 | ``` | ||
| 5467 | |||
| 5468 | **参数:** | ||
| 5469 | |||
| 5470 | | 参数名 | 类型 | 描述 | | ||
| 5471 | | ------- | ------ | ---------------- | | ||
| 5472 | | modname | string | 要加载的模块名。 | | ||
| 5473 | |||
| 5474 | **返回值:** | ||
| 5475 | |||
| 5476 | | 返回类型 | 描述 | | ||
| 5477 | | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| 5478 | | any | 如果模块已经加载,则返回 package.loaded[modname] 中存储的值。否则,尝试查找加载器并返回 package.loaded[modname] 的最终值和加载器数据作为第二个结果。 | | ||
| 5479 | |||
| 5480 | ### p | ||
| 5481 | |||
| 5482 | **类型:** 函数。 | ||
| 5483 | |||
| 5484 | **描述:** | ||
| 5485 | |||
| 5486 | 检查传递的值的内部结构,并打印值出它的字符串表示。 | ||
| 5487 | |||
| 5488 | **签名:** | ||
| 5489 | |||
| 5490 | ```lua | ||
| 5491 | p: function(...: any) | ||
| 5492 | ``` | ||
| 5493 | |||
| 5494 | **参数:** | ||
| 5495 | |||
| 5496 | | 参数名 | 类型 | 描述 | | ||
| 5497 | | ------ | ---- | ------------ | | ||
| 5498 | | ... | any | 要检查的值。 | | ||
| 5499 | |||
| 5500 | ### options | ||
| 5501 | |||
| 5502 | **类型:** 成员变量。 | ||
| 5503 | |||
| 5504 | **描述:** | ||
| 5505 | |||
| 5506 | 当前编译器选项。 | ||
| 5507 | |||
| 5508 | **签名:** | ||
| 5509 | |||
| 5510 | ```lua | ||
| 5511 | options: Config.Options | ||
| 5512 | ``` | ||
| 5513 | |||
| 5514 | ### traceback | ||
| 5515 | |||
| 5516 | **类型:** 函数。 | ||
| 5517 | |||
| 5518 | **描述:** | ||
| 5519 | |||
| 5520 | 重写堆栈跟踪中的行号为 YueScript 代码中的原始行号的 traceback 函数。 | ||
| 5521 | |||
| 5522 | **签名:** | ||
| 5523 | |||
| 5524 | ```lua | ||
| 5525 | traceback: function(message: string): string | ||
| 5526 | ``` | ||
| 5527 | |||
| 5528 | **参数:** | ||
| 5529 | |||
| 5530 | | 参数名 | 类型 | 描述 | | ||
| 5531 | | ------- | ------ | -------------- | | ||
| 5532 | | message | string | 堆栈跟踪消息。 | | ||
| 5533 | |||
| 5534 | **返回值:** | ||
| 5535 | |||
| 5536 | | 返回类型 | 描述 | | ||
| 5537 | | -------- | ---------------------- | | ||
| 5538 | | string | 重写后的堆栈跟踪消息。 | | ||
| 5539 | |||
| 5540 | ### is_ast | ||
| 5541 | |||
| 5542 | **类型:** 函数。 | ||
| 5543 | |||
| 5544 | **描述:** | ||
| 5545 | |||
| 5546 | 检查代码是否匹配指定的 AST。 | ||
| 5547 | |||
| 5548 | **签名:** | ||
| 5549 | |||
| 5550 | ```lua | ||
| 5551 | is_ast: function(astName: string, code: string): boolean | ||
| 5552 | ``` | ||
| 5553 | |||
| 5554 | **参数:** | ||
| 5555 | |||
| 5556 | | 参数名 | 类型 | 描述 | | ||
| 5557 | | ------- | ------ | ---------- | | ||
| 5558 | | astName | string | AST 名称。 | | ||
| 5559 | | code | string | 代码。 | | ||
| 5560 | |||
| 5561 | **返回值:** | ||
| 5562 | |||
| 5563 | | 返回类型 | 描述 | | ||
| 5564 | | -------- | ------------------ | | ||
| 5565 | | boolean | 代码是否匹配 AST。 | | ||
| 5566 | |||
| 5567 | ### AST | ||
| 5568 | |||
| 5569 | **类型:** 成员变量。 | ||
| 5570 | |||
| 5571 | **描述:** | ||
| 5572 | |||
| 5573 | AST 类型定义,带有名称、行、列和子节点。 | ||
| 5574 | |||
| 5575 | **签名:** | ||
| 5576 | |||
| 5577 | ```lua | ||
| 5578 | type AST = {string, integer, integer, any} | ||
| 5579 | ``` | ||
| 5580 | |||
| 5581 | ### to_ast | ||
| 5582 | |||
| 5583 | **类型:** 函数。 | ||
| 5584 | |||
| 5585 | **描述:** | ||
| 5586 | |||
| 5587 | 将代码转换为 AST。 | ||
| 5588 | |||
| 5589 | **签名:** | ||
| 5590 | |||
| 5591 | ```lua | ||
| 5592 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): | ||
| 5593 | --[[AST]] AST | nil, | ||
| 5594 | --[[error]] nil | string | ||
| 5595 | ``` | ||
| 5596 | |||
| 5597 | **参数:** | ||
| 5598 | |||
| 5599 | | 参数名 | 类型 | 描述 | | ||
| 5600 | | -------------- | ------- | ------------------------------------------------------------------------------ | | ||
| 5601 | | code | string | 代码。 | | ||
| 5602 | | flattenLevel | integer | [可选] 扁平化级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | | ||
| 5603 | | astName | string | [可选] AST 名称。默认为 "File"。 | | ||
| 5604 | | reserveComment | boolean | [可选] 是否保留原始注释。默认为 false。 | | ||
| 5605 | |||
| 5606 | **返回值:** | ||
| 5607 | |||
| 5608 | | 返回类型 | 描述 | | ||
| 5609 | | ------------- | -------------------------------- | | ||
| 5610 | | AST \| nil | AST,如果转换失败则为 nil。 | | ||
| 5611 | | string \| nil | 错误消息,如果转换成功则为 nil。 | | ||
| 5612 | |||
| 5613 | ### format | ||
| 5614 | |||
| 5615 | **类型:** 函数。 | ||
| 5616 | |||
| 5617 | **描述:** | ||
| 5618 | |||
| 5619 | 格式化 YueScript 代码。 | ||
| 5620 | |||
| 5621 | **签名:** | ||
| 5622 | |||
| 5623 | ```lua | ||
| 5624 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 5625 | ``` | ||
| 5626 | |||
| 5627 | **参数:** | ||
| 5628 | |||
| 5629 | | 参数名 | 类型 | 描述 | | ||
| 5630 | | -------------- | ------- | -------------------------------------- | | ||
| 5631 | | code | string | 代码。 | | ||
| 5632 | | tabSize | integer | [可选] 制表符大小。默认为 4。 | | ||
| 5633 | | reserveComment | boolean | [可选] 是否保留原始注释。默认为 true。 | | ||
| 5634 | |||
| 5635 | **返回值:** | ||
| 5636 | |||
| 5637 | | 返回类型 | 描述 | | ||
| 5638 | | -------- | ---------------- | | ||
| 5639 | | string | 格式化后的代码。 | | ||
| 5640 | |||
| 5641 | ### \_\_call | ||
| 5642 | |||
| 5643 | **类型:** 元方法。 | ||
| 5644 | |||
| 5645 | **描述:** | ||
| 5646 | |||
| 5647 | 导入 YueScript 模块。 | ||
| 5648 | 如果发生加载失败,则将错误信息中的代码行号重写为 YueScript 代码中的原始行号。 | ||
| 5649 | |||
| 5650 | **签名:** | ||
| 5651 | |||
| 5652 | ```lua | ||
| 5653 | metamethod __call: function(self: yue, module: string): any... | ||
| 5654 | ``` | ||
| 5655 | |||
| 5656 | **参数:** | ||
| 5657 | |||
| 5658 | | 参数名 | 类型 | 描述 | | ||
| 5659 | | ------ | ------ | -------- | | ||
| 5660 | | module | string | 模块名。 | | ||
| 5661 | |||
| 5662 | **返回值:** | ||
| 5663 | |||
| 5664 | | 返回类型 | 描述 | | ||
| 5665 | | -------- | -------- | | ||
| 5666 | | any | 模块值。 | | ||
| 5667 | |||
| 5668 | ## Config | ||
| 5669 | |||
| 5670 | **描述:** | ||
| 5671 | |||
| 5672 | 编译器编译选项。 | ||
| 5673 | |||
| 5674 | ### lint_global | ||
| 5675 | |||
| 5676 | **类型:** 成员变量。 | ||
| 5677 | |||
| 5678 | **描述:** | ||
| 5679 | |||
| 5680 | 编译器是否应该收集代码中出现的全局变量。 | ||
| 5681 | |||
| 5682 | **签名:** | ||
| 5683 | |||
| 5684 | ```lua | ||
| 5685 | lint_global: boolean | ||
| 5686 | ``` | ||
| 5687 | |||
| 5688 | ### implicit_return_root | ||
| 5689 | |||
| 5690 | **类型:** 成员变量。 | ||
| 5691 | |||
| 5692 | **描述:** | ||
| 5693 | |||
| 5694 | 编译器是否应该对根层级的代码块进行隐式的表达式返回。 | ||
| 5695 | |||
| 5696 | **签名:** | ||
| 5697 | |||
| 5698 | ```lua | ||
| 5699 | implicit_return_root: boolean | ||
| 5700 | ``` | ||
| 5701 | |||
| 5702 | ### reserve_line_number | ||
| 5703 | |||
| 5704 | **类型:** 成员变量。 | ||
| 5705 | |||
| 5706 | **描述:** | ||
| 5707 | |||
| 5708 | 编译器是否应该在编译后的代码中保留原始行号。 | ||
| 5709 | |||
| 5710 | **签名:** | ||
| 5711 | |||
| 5712 | ```lua | ||
| 5713 | reserve_line_number: boolean | ||
| 5714 | ``` | ||
| 5715 | |||
| 5716 | ### reserve_comment | ||
| 5717 | |||
| 5718 | **类型:** 成员变量。 | ||
| 5719 | |||
| 5720 | **描述:** | ||
| 5721 | |||
| 5722 | 编译器是否应该在编译后的代码中保留原始注释。 | ||
| 5723 | |||
| 5724 | **签名:** | ||
| 5725 | |||
| 5726 | ```lua | ||
| 5727 | reserve_comment: boolean | ||
| 5728 | ``` | ||
| 5729 | |||
| 5730 | ### space_over_tab | ||
| 5731 | |||
| 5732 | **类型:** 成员变量。 | ||
| 5733 | |||
| 5734 | **描述:** | ||
| 5735 | |||
| 5736 | 编译器是否应该在编译后的代码中使用空格字符而不是制表符字符。 | ||
| 5737 | |||
| 5738 | **签名:** | ||
| 5739 | |||
| 5740 | ```lua | ||
| 5741 | space_over_tab: boolean | ||
| 5742 | ``` | ||
| 5743 | |||
| 5744 | ### same_module | ||
| 5745 | |||
| 5746 | **类型:** 成员变量。 | ||
| 5747 | |||
| 5748 | **描述:** | ||
| 5749 | |||
| 5750 | 编译器是否应该将要编译的代码视为当前正在编译的模块。仅供编译器内部使用。 | ||
| 5751 | |||
| 5752 | **签名:** | ||
| 5753 | |||
| 5754 | ```lua | ||
| 5755 | same_module: boolean | ||
| 5756 | ``` | ||
| 5757 | |||
| 5758 | ### line_offset | ||
| 5759 | |||
| 5760 | **类型:** 成员变量。 | ||
| 5761 | |||
| 5762 | **描述:** | ||
| 5763 | |||
| 5764 | 编译器错误消息是否应该包含行号偏移量。仅供编译器内部使用。 | ||
| 5765 | |||
| 5766 | **签名:** | ||
| 5767 | |||
| 5768 | ```lua | ||
| 5769 | line_offset: integer | ||
| 5770 | ``` | ||
| 5771 | |||
| 5772 | ### yue.Config.LuaTarget | ||
| 5773 | |||
| 5774 | **类型:** 枚举。 | ||
| 5775 | |||
| 5776 | **描述:** | ||
| 5777 | |||
| 5778 | 目标 Lua 版本枚举。 | ||
| 5779 | |||
| 5780 | **签名:** | ||
| 5781 | |||
| 5782 | ```lua | ||
| 5783 | enum LuaTarget | ||
| 5784 | "5.1" | ||
| 5785 | "5.2" | ||
| 5786 | "5.3" | ||
| 5787 | "5.4" | ||
| 5788 | "5.5" | ||
| 5789 | end | ||
| 5790 | ``` | ||
| 5791 | |||
| 5792 | ### options | ||
| 5793 | |||
| 5794 | **类型:** 成员变量。 | ||
| 5795 | |||
| 5796 | **描述:** | ||
| 5797 | |||
| 5798 | 要传递给编译函数的额外选项。 | ||
| 5799 | |||
| 5800 | **签名:** | ||
| 5801 | |||
| 5802 | ```lua | ||
| 5803 | options: Options | ||
| 5804 | ``` | ||
| 5805 | |||
| 5806 | ## Options | ||
| 5807 | |||
| 5808 | **描述:** | ||
| 5809 | |||
| 5810 | 额外编译器选项定义。 | ||
| 5811 | |||
| 5812 | ### target | ||
| 5813 | |||
| 5814 | **类型:** 成员变量。 | ||
| 5815 | |||
| 5816 | **描述:** | ||
| 5817 | |||
| 5818 | 编译目标 Lua 版本。 | ||
| 5819 | |||
| 5820 | **签名:** | ||
| 5821 | |||
| 5822 | ```lua | ||
| 5823 | target: LuaTarget | ||
| 5824 | ``` | ||
| 5825 | |||
| 5826 | ### path | ||
| 5827 | |||
| 5828 | **类型:** 成员变量。 | ||
| 5829 | |||
| 5830 | **描述:** | ||
| 5831 | |||
| 5832 | 额外模块搜索路径。 | ||
| 5833 | |||
| 5834 | **签名:** | ||
| 5835 | |||
| 5836 | ```lua | ||
| 5837 | path: string | ||
| 5838 | ``` | ||
| 5839 | |||
| 5840 | ### dump_locals | ||
| 5841 | |||
| 5842 | **类型:** 成员变量。 | ||
| 5843 | |||
| 5844 | **描述:** | ||
| 5845 | |||
| 5846 | 是否在回溯错误消息中输出代码块的局部变量。默认为 false。 | ||
| 5847 | |||
| 5848 | **签名:** | ||
| 5849 | |||
| 5850 | ```lua | ||
| 5851 | dump_locals: boolean | ||
| 5852 | ``` | ||
| 5853 | |||
| 5854 | ### simplified | ||
| 5855 | |||
| 5856 | **类型:** 成员变量。 | ||
| 5857 | |||
| 5858 | **描述:** | ||
| 5859 | |||
| 5860 | 是否简化输出的错误消息。默认为 true。 | ||
| 5861 | |||
| 5862 | **签名:** | ||
| 5863 | |||
| 5864 | ```lua | ||
| 5865 | simplified: boolean | ||
| 5866 | ``` | ||
| @@ -33,6 +33,7 @@ INSTALL_PREFIX = usr/local | |||
| 33 | TEST_INPUT = ./spec/inputs | 33 | TEST_INPUT = ./spec/inputs |
| 34 | TEST_OUTPUT = ./spec/generated | 34 | TEST_OUTPUT = ./spec/generated |
| 35 | GEN_OUTPUT = ./spec/outputs | 35 | GEN_OUTPUT = ./spec/outputs |
| 36 | DOC_OUTPUT = ./doc | ||
| 36 | 37 | ||
| 37 | PLAT = macos | 38 | PLAT = macos |
| 38 | 39 | ||
| @@ -439,7 +440,7 @@ test: debug | |||
| 439 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(TEST_OUTPUT)/5.1/import_global.lua --target 5.1 | 440 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(TEST_OUTPUT)/5.1/import_global.lua --target 5.1 |
| 440 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target 5.1 | 441 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target 5.1 |
| 441 | @./$(BIN_NAME) $(TEST_INPUT)/test/try_catch_spec.yue -o $(TEST_OUTPUT)/5.1/test/try_catch_spec.lua --target 5.1 | 442 | @./$(BIN_NAME) $(TEST_INPUT)/test/try_catch_spec.yue -o $(TEST_OUTPUT)/5.1/test/try_catch_spec.lua --target 5.1 |
| 442 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT) | 443 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT) $(DOC_OUTPUT) |
| 443 | @echo -en "Compile time: " | 444 | @echo -en "Compile time: " |
| 444 | @$(END_TIME) | 445 | @$(END_TIME) |
| 445 | @./$(BIN_NAME) -e "$$(printf "r = io.popen('git diff --no-index $(TEST_OUTPUT) $(GEN_OUTPUT) | head -5')\\\\read '*a'\nif r ~= ''\n print r\n os.exit 1")" | 446 | @./$(BIN_NAME) -e "$$(printf "r = io.popen('git diff --no-index $(TEST_OUTPUT) $(GEN_OUTPUT) | head -5')\\\\read '*a'\nif r ~= ''\n print r\n os.exit 1")" |
| @@ -466,7 +467,7 @@ gen: release | |||
| 466 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(GEN_OUTPUT)/5.1/import_global.lua --target 5.1 | 467 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(GEN_OUTPUT)/5.1/import_global.lua --target 5.1 |
| 467 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target 5.1 | 468 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target 5.1 |
| 468 | @./$(BIN_NAME) $(TEST_INPUT)/test/try_catch_spec.yue -o $(GEN_OUTPUT)/5.1/test/try_catch_spec.lua --target 5.1 | 469 | @./$(BIN_NAME) $(TEST_INPUT)/test/try_catch_spec.yue -o $(GEN_OUTPUT)/5.1/test/try_catch_spec.lua --target 5.1 |
| 469 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT) | 470 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT) $(DOC_OUTPUT) |
| 470 | @echo -en "Compile time: " | 471 | @echo -en "Compile time: " |
| 471 | @$(END_TIME) | 472 | @$(END_TIME) |
| 472 | 473 | ||
diff --git a/spec/inputs/compile_doc.yue b/spec/inputs/compile_doc.yue index ab621f8..f6a8d49 100644 --- a/spec/inputs/compile_doc.yue +++ b/spec/inputs/compile_doc.yue | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | outputFolder = ... | 1 | [outputFolder, docFolder] = {...} |
| 2 | 2 | ||
| 3 | getFiles = (locale) -> | 3 | getFiles = (locale) -> |
| 4 | locale = if locale == "en" then "" else "#{locale}/" | 4 | locale = if locale == "en" then "" else "#{locale}/" |
| @@ -37,13 +37,15 @@ getFiles = (locale) -> | |||
| 37 | "doc/docs/#{locale}doc/reference/license-mit.md" | 37 | "doc/docs/#{locale}doc/reference/license-mit.md" |
| 38 | "doc/docs/#{locale}doc/reference/the-yuescript-library.md" | 38 | "doc/docs/#{locale}doc/reference/the-yuescript-library.md" |
| 39 | ] | 39 | ] |
| 40 | docs = [ ["codes_from_doc_#{locale}.lua", getFiles locale] for locale in *["en", "zh", "pt-br", "de", "id-id"]] | 40 | docs = [ ["codes_from_doc_#{locale}.lua", "yue-#{locale}.md", getFiles locale] for locale in *["en", "zh", "pt-br", "de", "id-id"]] |
| 41 | for [compiledFile, docFiles] in *docs | 41 | for [compiledFile, docFile, docFiles] in *docs |
| 42 | codes = [] | 42 | codes = [] |
| 43 | docTexts = [] | ||
| 43 | for docFile in *docFiles | 44 | for docFile in *docFiles |
| 44 | close input = with? io.open docFile | 45 | close input = with? io.open docFile |
| 45 | import "yue" as :to_lua | 46 | import "yue" as :to_lua |
| 46 | text = \read "*a" | 47 | text = \read "*a" |
| 48 | docTexts[] = text | ||
| 47 | for code in text\gmatch "```yuescript[\r\n]+(.-)```[^%w]" | 49 | for code in text\gmatch "```yuescript[\r\n]+(.-)```[^%w]" |
| 48 | if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false | 50 | if result, err := to_lua code, implicit_return_root: false, reserve_line_number: false |
| 49 | codes[] = result | 51 | codes[] = result |
| @@ -58,4 +60,6 @@ for [compiledFile, docFiles] in *docs | |||
| 58 | os.exit 1 | 60 | os.exit 1 |
| 59 | close output = with io.open "#{outputFolder}/#{compiledFile}", "w+" | 61 | close output = with io.open "#{outputFolder}/#{compiledFile}", "w+" |
| 60 | \write table.concat codes | 62 | \write table.concat codes |
| 63 | close output2 = with io.open "#{docFolder}/#{docFile}", "w+" | ||
| 64 | \write table.concat docTexts, "\n" | ||
| 61 | 65 | ||
diff --git a/spec/outputs/codes_from_doc_de.lua b/spec/outputs/codes_from_doc_de.lua index 428f788..4c9ba1d 100644 --- a/spec/outputs/codes_from_doc_de.lua +++ b/spec/outputs/codes_from_doc_de.lua | |||
| @@ -2163,6 +2163,18 @@ repeat | |||
| 2163 | result = _with_0.value | 2163 | result = _with_0.value |
| 2164 | break | 2164 | break |
| 2165 | until true | 2165 | until true |
| 2166 | local a | ||
| 2167 | do | ||
| 2168 | local _with_0 = obj | ||
| 2169 | _with_0.x = 1 | ||
| 2170 | a = _with_0 | ||
| 2171 | end | ||
| 2172 | local b | ||
| 2173 | local _with_0 = obj | ||
| 2174 | repeat | ||
| 2175 | b = _with_0.x | ||
| 2176 | break | ||
| 2177 | until true | ||
| 2166 | local create_person | 2178 | local create_person |
| 2167 | create_person = function(name, relatives) | 2179 | create_person = function(name, relatives) |
| 2168 | local _with_0 = Person() | 2180 | local _with_0 = Person() |
| @@ -2209,6 +2221,18 @@ repeat | |||
| 2209 | result = _with_0.value | 2221 | result = _with_0.value |
| 2210 | break | 2222 | break |
| 2211 | until true | 2223 | until true |
| 2224 | local a | ||
| 2225 | do | ||
| 2226 | local _with_0 = obj | ||
| 2227 | _with_0.x = 1 | ||
| 2228 | a = _with_0 | ||
| 2229 | end | ||
| 2230 | local b | ||
| 2231 | local _with_0 = obj | ||
| 2232 | repeat | ||
| 2233 | b = _with_0.x | ||
| 2234 | break | ||
| 2235 | until true | ||
| 2212 | local create_person | 2236 | local create_person |
| 2213 | create_person = function(name, relatives) | 2237 | create_person = function(name, relatives) |
| 2214 | local _with_0 = Person() | 2238 | local _with_0 = Person() |
diff --git a/spec/outputs/codes_from_doc_en.lua b/spec/outputs/codes_from_doc_en.lua index 4006605..6d822e1 100644 --- a/spec/outputs/codes_from_doc_en.lua +++ b/spec/outputs/codes_from_doc_en.lua | |||
| @@ -2163,6 +2163,18 @@ repeat | |||
| 2163 | result = _with_0.value | 2163 | result = _with_0.value |
| 2164 | break | 2164 | break |
| 2165 | until true | 2165 | until true |
| 2166 | local a | ||
| 2167 | do | ||
| 2168 | local _with_0 = obj | ||
| 2169 | _with_0.x = 1 | ||
| 2170 | a = _with_0 | ||
| 2171 | end | ||
| 2172 | local b | ||
| 2173 | local _with_0 = obj | ||
| 2174 | repeat | ||
| 2175 | b = _with_0.x | ||
| 2176 | break | ||
| 2177 | until true | ||
| 2166 | local create_person | 2178 | local create_person |
| 2167 | create_person = function(name, relatives) | 2179 | create_person = function(name, relatives) |
| 2168 | local _with_0 = Person() | 2180 | local _with_0 = Person() |
| @@ -2209,6 +2221,18 @@ repeat | |||
| 2209 | result = _with_0.value | 2221 | result = _with_0.value |
| 2210 | break | 2222 | break |
| 2211 | until true | 2223 | until true |
| 2224 | local a | ||
| 2225 | do | ||
| 2226 | local _with_0 = obj | ||
| 2227 | _with_0.x = 1 | ||
| 2228 | a = _with_0 | ||
| 2229 | end | ||
| 2230 | local b | ||
| 2231 | local _with_0 = obj | ||
| 2232 | repeat | ||
| 2233 | b = _with_0.x | ||
| 2234 | break | ||
| 2235 | until true | ||
| 2212 | local create_person | 2236 | local create_person |
| 2213 | create_person = function(name, relatives) | 2237 | create_person = function(name, relatives) |
| 2214 | local _with_0 = Person() | 2238 | local _with_0 = Person() |
diff --git a/spec/outputs/codes_from_doc_id-id.lua b/spec/outputs/codes_from_doc_id-id.lua index 7d95eaa..4026240 100644 --- a/spec/outputs/codes_from_doc_id-id.lua +++ b/spec/outputs/codes_from_doc_id-id.lua | |||
| @@ -2163,6 +2163,18 @@ repeat | |||
| 2163 | result = _with_0.value | 2163 | result = _with_0.value |
| 2164 | break | 2164 | break |
| 2165 | until true | 2165 | until true |
| 2166 | local a | ||
| 2167 | do | ||
| 2168 | local _with_0 = obj | ||
| 2169 | _with_0.x = 1 | ||
| 2170 | a = _with_0 | ||
| 2171 | end | ||
| 2172 | local b | ||
| 2173 | local _with_0 = obj | ||
| 2174 | repeat | ||
| 2175 | b = _with_0.x | ||
| 2176 | break | ||
| 2177 | until true | ||
| 2166 | local create_person | 2178 | local create_person |
| 2167 | create_person = function(name, relatives) | 2179 | create_person = function(name, relatives) |
| 2168 | local _with_0 = Person() | 2180 | local _with_0 = Person() |
| @@ -2209,6 +2221,18 @@ repeat | |||
| 2209 | result = _with_0.value | 2221 | result = _with_0.value |
| 2210 | break | 2222 | break |
| 2211 | until true | 2223 | until true |
| 2224 | local a | ||
| 2225 | do | ||
| 2226 | local _with_0 = obj | ||
| 2227 | _with_0.x = 1 | ||
| 2228 | a = _with_0 | ||
| 2229 | end | ||
| 2230 | local b | ||
| 2231 | local _with_0 = obj | ||
| 2232 | repeat | ||
| 2233 | b = _with_0.x | ||
| 2234 | break | ||
| 2235 | until true | ||
| 2212 | local create_person | 2236 | local create_person |
| 2213 | create_person = function(name, relatives) | 2237 | create_person = function(name, relatives) |
| 2214 | local _with_0 = Person() | 2238 | local _with_0 = Person() |
diff --git a/spec/outputs/codes_from_doc_pt-br.lua b/spec/outputs/codes_from_doc_pt-br.lua index caa15d6..0d0c76f 100644 --- a/spec/outputs/codes_from_doc_pt-br.lua +++ b/spec/outputs/codes_from_doc_pt-br.lua | |||
| @@ -2163,6 +2163,18 @@ repeat | |||
| 2163 | result = _with_0.value | 2163 | result = _with_0.value |
| 2164 | break | 2164 | break |
| 2165 | until true | 2165 | until true |
| 2166 | local a | ||
| 2167 | do | ||
| 2168 | local _with_0 = obj | ||
| 2169 | _with_0.x = 1 | ||
| 2170 | a = _with_0 | ||
| 2171 | end | ||
| 2172 | local b | ||
| 2173 | local _with_0 = obj | ||
| 2174 | repeat | ||
| 2175 | b = _with_0.x | ||
| 2176 | break | ||
| 2177 | until true | ||
| 2166 | local create_person | 2178 | local create_person |
| 2167 | create_person = function(name, relatives) | 2179 | create_person = function(name, relatives) |
| 2168 | local _with_0 = Person() | 2180 | local _with_0 = Person() |
| @@ -2209,6 +2221,18 @@ repeat | |||
| 2209 | result = _with_0.value | 2221 | result = _with_0.value |
| 2210 | break | 2222 | break |
| 2211 | until true | 2223 | until true |
| 2224 | local a | ||
| 2225 | do | ||
| 2226 | local _with_0 = obj | ||
| 2227 | _with_0.x = 1 | ||
| 2228 | a = _with_0 | ||
| 2229 | end | ||
| 2230 | local b | ||
| 2231 | local _with_0 = obj | ||
| 2232 | repeat | ||
| 2233 | b = _with_0.x | ||
| 2234 | break | ||
| 2235 | until true | ||
| 2212 | local create_person | 2236 | local create_person |
| 2213 | create_person = function(name, relatives) | 2237 | create_person = function(name, relatives) |
| 2214 | local _with_0 = Person() | 2238 | local _with_0 = Person() |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index 4ff3866..c847841 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
| @@ -2163,6 +2163,18 @@ repeat | |||
| 2163 | result = _with_0.value | 2163 | result = _with_0.value |
| 2164 | break | 2164 | break |
| 2165 | until true | 2165 | until true |
| 2166 | local a | ||
| 2167 | do | ||
| 2168 | local _with_0 = obj | ||
| 2169 | _with_0.x = 1 | ||
| 2170 | a = _with_0 | ||
| 2171 | end | ||
| 2172 | local b | ||
| 2173 | local _with_0 = obj | ||
| 2174 | repeat | ||
| 2175 | b = _with_0.x | ||
| 2176 | break | ||
| 2177 | until true | ||
| 2166 | local create_person | 2178 | local create_person |
| 2167 | create_person = function(name, relatives) | 2179 | create_person = function(name, relatives) |
| 2168 | local _with_0 = Person() | 2180 | local _with_0 = Person() |
| @@ -2209,6 +2221,18 @@ repeat | |||
| 2209 | result = _with_0.value | 2221 | result = _with_0.value |
| 2210 | break | 2222 | break |
| 2211 | until true | 2223 | until true |
| 2224 | local a | ||
| 2225 | do | ||
| 2226 | local _with_0 = obj | ||
| 2227 | _with_0.x = 1 | ||
| 2228 | a = _with_0 | ||
| 2229 | end | ||
| 2230 | local b | ||
| 2231 | local _with_0 = obj | ||
| 2232 | repeat | ||
| 2233 | b = _with_0.x | ||
| 2234 | break | ||
| 2235 | until true | ||
| 2212 | local create_person | 2236 | local create_person |
| 2213 | create_person = function(name, relatives) | 2237 | create_person = function(name, relatives) |
| 2214 | local _with_0 = Person() | 2238 | local _with_0 = Person() |
diff --git a/spec/outputs/compile_doc.lua b/spec/outputs/compile_doc.lua index 8d5c11a..f661bbd 100644 --- a/spec/outputs/compile_doc.lua +++ b/spec/outputs/compile_doc.lua | |||
| @@ -1,4 +1,10 @@ | |||
| 1 | local outputFolder = ... | 1 | local outputFolder, docFolder |
| 2 | do | ||
| 3 | local _obj_0 = { | ||
| 4 | ... | ||
| 5 | } | ||
| 6 | outputFolder, docFolder = _obj_0[1], _obj_0[2] | ||
| 7 | end | ||
| 2 | local getFiles | 8 | local getFiles |
| 3 | getFiles = function(locale) | 9 | getFiles = function(locale) |
| 4 | if locale == "en" then | 10 | if locale == "en" then |
| @@ -57,6 +63,7 @@ do | |||
| 57 | local locale = _list_0[_index_0] | 63 | local locale = _list_0[_index_0] |
| 58 | _accum_0[_len_0] = { | 64 | _accum_0[_len_0] = { |
| 59 | "codes_from_doc_" .. tostring(locale) .. ".lua", | 65 | "codes_from_doc_" .. tostring(locale) .. ".lua", |
| 66 | "yue-" .. tostring(locale) .. ".md", | ||
| 60 | getFiles(locale) | 67 | getFiles(locale) |
| 61 | } | 68 | } |
| 62 | _len_0 = _len_0 + 1 | 69 | _len_0 = _len_0 + 1 |
| @@ -65,8 +72,9 @@ do | |||
| 65 | end | 72 | end |
| 66 | for _index_0 = 1, #docs do | 73 | for _index_0 = 1, #docs do |
| 67 | local _des_0 = docs[_index_0] | 74 | local _des_0 = docs[_index_0] |
| 68 | local compiledFile, docFiles = _des_0[1], _des_0[2] | 75 | local compiledFile, docFile, docFiles = _des_0[1], _des_0[2], _des_0[3] |
| 69 | local codes = { } | 76 | local codes = { } |
| 77 | local docTexts = { } | ||
| 70 | for _index_1 = 1, #docFiles do | 78 | for _index_1 = 1, #docFiles do |
| 71 | local docFile = docFiles[_index_1] | 79 | local docFile = docFiles[_index_1] |
| 72 | local input | 80 | local input |
| @@ -74,6 +82,7 @@ for _index_0 = 1, #docs do | |||
| 74 | if _with_0 ~= nil then | 82 | if _with_0 ~= nil then |
| 75 | local to_lua = require("yue").to_lua | 83 | local to_lua = require("yue").to_lua |
| 76 | local text = _with_0:read("*a") | 84 | local text = _with_0:read("*a") |
| 85 | docTexts[#docTexts + 1] = text | ||
| 77 | for code in text:gmatch("```yuescript[\r\n]+(.-)```[^%w]") do | 86 | for code in text:gmatch("```yuescript[\r\n]+(.-)```[^%w]") do |
| 78 | local result, err = to_lua(code, { | 87 | local result, err = to_lua(code, { |
| 79 | implicit_return_root = false, | 88 | implicit_return_root = false, |
| @@ -103,8 +112,15 @@ for _index_0 = 1, #docs do | |||
| 103 | local _close_0 <close> = input | 112 | local _close_0 <close> = input |
| 104 | end | 113 | end |
| 105 | local output | 114 | local output |
| 106 | local _with_0 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+") | 115 | do |
| 107 | _with_0:write(table.concat(codes)) | 116 | local _with_0 = io.open(tostring(outputFolder) .. "/" .. tostring(compiledFile), "w+") |
| 108 | output = _with_0 | 117 | _with_0:write(table.concat(codes)) |
| 118 | output = _with_0 | ||
| 119 | end | ||
| 109 | local _close_0 <close> = output | 120 | local _close_0 <close> = output |
| 121 | local output2 | ||
| 122 | local _with_0 = io.open(tostring(docFolder) .. "/" .. tostring(docFile), "w+") | ||
| 123 | _with_0:write(table.concat(docTexts, "\n")) | ||
| 124 | output2 = _with_0 | ||
| 125 | local _close_1 <close> = output2 | ||
| 110 | end | 126 | end |
