Skip to main content

Mojo v0.4.0

⭐️ New

  • Mojo now supports default parameter values. For example:

    fn foo[a: Int = 3, msg: StringLiteral = "woof"]():
        print(msg, a)
    
    fn main():
        foo()  # prints 'woof 3'
        foo[5]()  # prints 'woof 5'
        foo[7, "meow"]()  # prints 'meow 7'

    Inferred parameter values take precedence over defaults:

    @value
    struct Bar[v: Int]:
        pass
    
    fn foo[a: Int = 42, msg: StringLiteral = "quack"](bar: Bar[a]):
        print(msg, a)
    
    fn main():
        foo(Bar[9]())  # prints 'quack 9'

    Structs also support default parameters:

    @value
    struct DefaultParams[msg: StringLiteral = "woof"]:
        alias message = msg
    
    fn main():
        print(DefaultParams[]().message)  # prints 'woof'
        print(DefaultParams["meow"]().message)  # prints 'meow'
  • The new file module adds basic file I/O support. You can now write:

    var f = open("my_file.txt", "r")
    print(f.read())
    f.close()

    or

    with open("my_file.txt", "r") as f:
        print(f.read())
  • Mojo now allows context managers to support an __enter__ method without implementing support for an __exit__ method, enabling idioms like this:

    # This context manager consumes itself and returns it as the value.
    fn __enter__(owned self) -> Self:
        return self^

    Here Mojo cannot invoke a noop __exit__ method because the context manager is consumed by the __enter__ method. This can be used for types (like file descriptors) that are traditionally used with with statements, even though Mojo's guaranteed early destruction doesn't require that.

  • A very basic version of pathlib has been implemented in Mojo. The module will be improved to achieve functional parity with Python in the next few releases.

  • The memory.unsafe module now contains a bitcast function. This is a low-level operation that enables bitcasting between pointers and scalars.

  • The input parameters of a parametric type can now be directly accessed as attribute references on the type or variables of the type. For example:

    @value
    struct Thing[param: Int]:
        pass
    
    fn main():
        print(Thing[2].param) # prints '2'
        let x = Thing[9]()
        print(x.param) # prints '9'

    Input parameters on values can even be accessed in parameter contexts. For example:

    fn foo[value: Int]():
        print(value)
    
    let y = Thing[12]()
    alias constant = y.param + 4
    foo[constant]() # prints '16'
  • The Mojo REPL now supports code completion. Press Tab while typing to query potential completion results.

  • Error messages from Python are now exposed in Mojo. For example the following should print No module named 'my_uninstalled_module':

    fn main():
        try:
            let my_module = Python.import_module("my_uninstalled_module")
        except e:
            print(e)
  • Error messages can now store dynamic messages. For example, the following should print "Failed on: Hello"

    fn foo(x: String) raises:
        raise Error("Failed on: " + x)
    
    fn main():
        try:
            foo("Hello")
        except e:
            print(e)

🦋 Changed

  • We have improved and simplified the parallelize function. The function now elides some overhead by caching the Mojo parallel runtime.

  • The Mojo REPL and Jupyter environments no longer implicitly expose Python, PythonObject, or Pointer. These symbols must now be imported explicitly, for example:

    from python import Python
    from python.object import PythonObject
    from memory.unsafe import Pointer
  • The syntax for specifying attributes with the __mlir_op prefix have changed to mimic Python's keyword argument passing syntax. That is, = should be used instead of :, e.g.:

    # Old syntax, now fails.
    __mlir_op.`index.bool.constant`[value : __mlir_attr.false]()
    # New syntax.
    __mlir_op.`index.bool.constant`[value=__mlir_attr.false]()
  • You can now print the Error object directly. The message() method has been removed.

🛠️ Fixed

  • #794 - Parser crash when using the in operator.
  • #936 - The Int constructor now accepts other Int instances.
  • #921 - Better error message when running mojo on a module with no main function.
  • #556 - UInt64s are now printed correctly.
  • #804 - Emit error instead of crashing when passing variadic arguments of unsupported types.
  • #833 - Parser crash when assigning module value.
  • #752 - Parser crash when calling async def.
  • #711 - The overload resolution logic now correctly prioritizes instance methods over static methods (if candidates are an equally good match otherwise), and no longer crashed if a static method has a Self type as its first argument.
  • #859 - Fix confusing error and documentation of the rebind builtin.
  • #753 - Direct use of LLVM dialect produces strange errors in the compiler.
  • #926 - Fixes an issue that occurred when a function with a return type of StringRef raised an error. When the function raised an error, it incorrectly returned the string value of that error.
  • #536 - Report More information on python exception.

Was this page helpful?