20260407 MoonBit v0.9 Release
moonc version: v0.9.0+9f1423bcb
Language Updatesβ
-
Deprecate
derive(Show)The interface for debugging data structures has moved to the
Debugtrait. TheShowtrait will now focus on customizable output formats such asJson::stringify, rather than special-casing onlyStringandChar. ManualShowimplementations are still supported. -
Add formal verification support
For example, we can use
proof_ensureto specify properties that the result of a function should satisfy:// Int is assumed to be unbounded integers // We will provide a config option to change it to 32-bit machine integers // in later releases pub fn abs(x : Int) -> Int where { proof_ensure: result => result >= 0, proof_ensure: result => (result == x) || (result == -x) } { if x >= 0 { x } else { -x } }Enable proof support in
moon.pkg:options( "proof-enabled": true )Then run
moon proveto view the proof results. More details about verification support will be covered in another article. -
Deprecate
loopsyntaxThe
loopsyntax has been deprecated to simplify the language. Existing code usingloopcan be rewritten usingfor+match:loop value { Pattern1 => continue value1 Pattern2 => ... }for x = value { match x { Pattern1 => continue value1 Pattern2 => { ...; break } } } -
Stable
regexsupport and the new regex match expressions =~ re"..."The new regex match expression is similar to the earlier experimental
lexmatch?, but it has important semantic differences. See the documentation for regex literal expressions and regex match expressions for details.We plan to deprecate the experimental
lexmatchandlexmatch?expressions in the future.const PREFIX = re"a" const ALT = re"b" const SUFFIX = re"bc" fn main { let s = "==abc==" let _ = s =~ re"abc" let _ = s =~ (PREFIX + SUFFIX, ) let _ = s =~ (((re"x" as x) | ALT) + SUFFIX, before=y, after~) } -
Int64andUInt64now compile toBigInton the JavaScript backendUInt64maps directly to JavaScriptBigInt. ForInt64, useBigInt.asIntN(64, x)to obtain the corresponding signed 64-bit value.We are switching to
BigIntfor two main reasons:- Modern JavaScript engines have significantly improved
BigIntperformance, andInt64built on top ofBigIntis now substantially faster than the previous two-Intrepresentation. - It aligns MoonBit with the natural way 64-bit integers are handled in modern JavaScript.
- Modern JavaScript engines have significantly improved
-
Add reverse pipeline syntax
div(id="...") <| []Reverse pipeline introduces a new DSL style for UI libraries and improves readability by reducing nested parentheses in view code:
fn view() -> Html { div([ text("hello"), ul([ li("item 1"), li("item 2"), ]), h1(id="...", [ a(href="..."), ]), ]) }fn view() -> Html { div <| [ text("hello"), ul <| [ li("item 1"), li("item 2"), ], h1(id="...") <| [ a(href="..."), ], ] }The right-hand side also supports lambdas. This enables trailing-lambda style APIs for UI frameworks similar to Compose UI or SwiftUI:
list(album.songs) <| song => { hstack <| () => { image(album.cover) vstack(alignment=Leading) <| () => { text(song.title) text(song.artist.name) .foreground_style(Secondary) } } } -
Unify the ABI of
Unit-returning FFI functionsOn the native / wasm / wasm-gc backends, FFI functions returning
Unitnow use a no-return ABI. For example, on the native backend, a MoonBitextern "C"declaration returningUnitnow corresponds to a C function returningvoid. -
Add
#deprecatedsupport forimplCurrently,
#deprecatedcan only be attached toimpl Trait for Typedeclarations withoutwith. Any use of a deprecatedimpl, including polymorphic calls and direct method calls through thatimpl, will produce a warning:struct T(Int) #deprecated impl Eq for T impl Eq for T with equal(x, y) { x.0 == y.0 } test { let _ = T(1) == T(2) // deprecated warning } -
usingand#aliasnow create constructor aliases automaticallyTuple structs, structs with constructors, and errors with a single constructor can now automatically get constructor aliases, making them constructible and matchable via the alias:
using @ref {type Ref} test { let _ = Ref(42) // No need to write `@ref.Ref(42)` anymore } #alias(Alias) struct MyType(Int) test { let _ = Alias(42) // No need to write `MyType(42)` anymore }This makes all three forms work naturally with re-export through
usingand renaming through#alias.
Toolchain Updatesβ
-
Add workspace support
This includes
moon work initandmoon work usefor creating and managing workspaces.moon work syncsyncs package versions inside the workspace.Commands such as
check,test, andformatnow support workspaces. Publishing still works at the module level only, and should be done withmoon -C module publish. -
Deprecate symbol lookup in
moon docSymbol lookup is now unified under
moon ide doc. -
Add Windows aarch64 support to the install script
-
Retire
try.moonbitlang.cnandoj.moonbitlang.com -
Change version resolution for pre-1.0 packages
Pre-1.0 versions are now treated as compatible until the official 1.0 release. For example,
moonbitlang/async@0.15.0andmoonbitlang/async@0.16.0in the dependency graph will now resolve tomoonbitlang/async@0.16.0. -
Improve the UI and documentation browsing experience on
mooncakes.io
Standard Library Updatesβ
-
Add
immut/vectorimmut/vectorreplaces the oldimmut/arrayand provides better performance. -
Adjust the
Showformat ofSourceLocFile names are now rendered relative to the module rather than the package. This change allows a project's
sourceconfiguration to be reflected inSourceLoc. If your tests printSourceLoc, you may need to update the expected output withmoon test -u. -
moonbitlang/asyncupdate (latest versionv0.17.0)- Add the
@async.Timertype, which can be used to implement abstractions such as idle timeouts. - Many types, such as
@async.Queue, now providestructconstructor APIs and can be created with forms like@async.Queue(..). @async.spawn_loophas some breaking signature changes to adapt to upstream type changes.- It is now possible to access socket file descriptors directly, which is useful for advanced users binding platform-specific socket APIs.
- Add the