weekly 2024-08-12
Language Updateβ
-
Added support for
for .. in
loops based onIter
andIter2
types: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
for
andin
to iterate over elements inIter
. A single-variable loopfor x in expr1
iterates overexpr1.iter() : Iter[_]
, while a two-variable loopfor x, y in expr2
iterates overexpr2.iter2() : Iter2[_, _]
. Underscores can be used to ignore elements, but pattern matching is not allowed betweenfor
andin
.The loop body in
for .. in
can 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
BigInt
type 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 functiong
above 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
TextDecoder
API. If Node.js support forTextDecoder
improves 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`
}