weekly 2024-08-12
Language Updateβ
-
Added support for
for .. inloops based onIterandIter2types:fn main { for x in [1, 2, 3] { println(x) } for k, v in {"x": 1, "y": 2} { println("\{k} => \{v}") } }You can bind one or two variables between
forandinto iterate over elements inIter. A single-variable loopfor x in expr1iterates overexpr1.iter() : Iter[_], while a two-variable loopfor x, y in expr2iterates overexpr2.iter2() : Iter2[_, _]. Underscores can be used to ignore elements, but pattern matching is not allowed betweenforandin.The loop body in
for .. incan use control flow statements likereturn/break/raise:test "for/in" { // `iter2` for arrays iterates over index + elements for i, x in [1, 2, 3] { assert_eq!(i + 1, x) } }
-Introduced new string interpolation syntax \{}, deprecating the old \(). This allows embedding more complex expressions directly into strings. Future updates will relax syntax restrictions within string interpolations, such as supporting \{1 + 2} and \{x.f(y)}.
"hello, \(name)!" // warning: deprecated
"hello, \{name}!" // new syntax
- Expanded numerical handling: Added a new built-in
BigInttype for managing large values beyond the range of regular integers.
// BigInt literals end with N
let num = 100000000N
// Like Int literals, underscores are allowed between digits. Hexadecimal, octal, and binary formats are also supported.
let n2 = 0xFFFFFFFFN
let n3 = 0o77777777N
let n4 = 0b1111111100000000N
let n5 = 1234_4567_91011N
// If the type is explicitly BigInt, the N suffix is not required
let n6 : BigInt = 1000000000000000000
// Pattern matching also supports BigInt
match 10N {
1N => println(1)
10N => println(10)
100 => println(100)
}
-
Added support for declaring error types using enums. For example, errors in the Json package can be declared as follows:
pub type! ParseError { InvalidChar(Position, Char) InvalidEof InvalidNumber(Position, String) InvalidIdentEscape(Position) } derive(Eq)You can also use labeled and mutable arguments within error types using enums, the same as how you would use them in regular enum types.
type! Error1 {
A
B(Int, ~x: String)
C(mut ~x: String, Char, ~y: Bool)
} derive(Show)
fn f() -> Unit!Error1 {
raise Error1::C('x', x="error2", y=false)
}
fn g() -> Unit!Error1 {
try f!() {
Error1::C(_) as c => {
c.x = "Rethrow Error2::C"
raise c
}
e => raise e
}
}
fn main {
println(g?()) // Err(C(x="Rethrow Error2::C", 'x', y=false))
}
- Introduced
catch!syntax to rethrow errors that are not handled within an error handler. By usingcatch!, you can more easily manage and propagate errors through your code, simplifying the process of error handling. For example, the functiongabove can be rewritten as:
fn g() -> Unit!Error1 {
try f!() catch! {
Error1::C(_) as c => {
c.x = "Rethrow Error2::C"
raise c
}
}
}
- The generated JavaScript code no longer relies on the
TextDecoderAPI. If Node.js support forTextDecoderimproves in the future, we might consider adding it back.
IDE Updateβ
-
Fixed an issue where the source code in the core library couldn't load in web-based VSCode plugin while debugging. Debugging features in MoonBit IDE are now functional.
-
MoonBit IDE now supports auto-completion for constructors in pattern matching based on type:
match (x : Option[Int]) {
// ^^^^ Auto-completes `None` and `Some`
}
Core Updateβ
- Added a new
Iter2type for iterating over collections with two elements, like Map, or iterating over arrays with an index:
fn main {
let map = {"x": 1, "y": 2}
map.iter2().each(fn (k, v) {
println("\{k} => \{v}")
})
}
Compared to Iter[(X, Y)], Iter2[X, Y] offers better performance and native support for for .. in loops.
-
Moved
@json.JsonValueto the@builtinpackage and renamed it toJson.@json.JsonValueis now an alias forJson, so this change is backward compatible. -
Added a
ToJsoninterface in@builtinto represent types that can be converted toJson.
Build System Updateβ
-
Added
-C/--directorycommands tomoon check|build|test, equivalent to--source-dir, to specify the root directory of a MoonBit project, i.e., wheremoon.mod.jsonis located. -
Updated the
root-dirinmoon.mod.jsontosource. This field specifies the source directory for modules, and the value of thesourcefield can be a multi-level directory but must be a subdirectory of the directory containingmoon.mod.json, e.g.,"source": "a/b/c".This field is introduced because package names in MoonBit modules are related to file paths. For example, if the current module name is
moonbitlang/exampleand a package is located atlib/moon.pkg.json, you would need to import the package using its full namemoonbitlang/example/lib. Sometimes, to better organize the project structure, we may want to place the source code in thesrcdirectory, such assrc/lib/moon.pkg.json. In this case, you would need to usemoonbitlang/example/src/libto import the package. However, generally, we do not wantsrcto appear in the package path, so you can specify"source": "src"to ignore this directory level and still import the package asmoonbitlang/example/lib.
Toolchain Updateβ
- MoonBit AI supported generating code explanations: In MoonBit IDE, click the MoonBit logo and select
/explainto get code explanations which will appear on the right side. Don't forget to click π or π to give us your feedback.
