Skip to main content

August 2023

2023-08-24

  • Fixed issue where the with expr as x statement within fn behaved as if it were in a def, binding x with function scope instead of using lexical scope.

⭐️ New

  • Major refactoring of the standard library to enable packaging and better import ergonomics:

    • The packages are built as binaries to improve startup speed.
    • Package and module names are now lowercase to align with the Python style.
    • Modules have been moved to better reflect the purpose of the underlying functions (e.g. Pointer is now within the unsafe module in the memory package).
    • The following modules are now included as built-ins: SIMD, DType, IO, Object, and String. This means it's no longer necessary to explicitly import these modules. Instead, these modules will be implicitly imported for the user. Private methods within the module are still accessible using the builtin.module_name._private_method import syntax.
    • New math package has been added to contain the bit, math, numerics, and polynomial modules. The contents of the math.math module are re-exported into the math package.
  • Mojo now supports using memory-only types in parameter expressions and as function or type parameters:

    @value
    struct IntPair:
        var first: Int
        var second: Int
    
    fn add_them[value: IntPair]() -> Int:
        return value.first + value.second
    
    fn main():
        print(add_them[IntPair(1, 2)]()) # prints '3'
  • In addition, Mojo supports evaluating code that uses heap-allocated memory at compile-time and materializing compile-time values with heap-allocated memory into dynamic values:

    fn fillVector(lowerBound: Int, upperBound: Int, step: Int) -> DynamicVector[Int]:
        var result = DynamicVector[Int]()
        for i in range(lowerBound, upperBound, step):
            result.push_back(i)
        return result
    
    fn main():
        alias values = fillVector(5, 23, 7)
        for i in range(0, values.__len__()):
            print(values[i]) # prints '5', '12', and then '19'

🦋 Changed

  • def main():, without the explicit None type, can now be used to define the entry point to a Mojo program.

  • The assert_param function has been renamed to constrained and is now a built-in function.

  • The print function now works on Complex values.

🛠️ Fixed

  • Fixed issues with print formatting for DType.uint16 and DType.int16.
  • Issue #499 - Two new rotate_right and rotate_left functions have been added to the SIMD module.
  • Issue #429 - You can now construct a Bool from a SIMD type whose element-type is DType.bool.
  • Issue #350 - Confusing Matrix implementation
  • Issue #349 - Missing load_tr in struct Matrix
  • Issue #501 - Missing syntax error messages in Python expressions.

2023-08-09

🦋 Changed

  • The ref and mutref identifiers are now treated as keywords, which means they cannot be used as variable, attribute, or function names. These keywords are used by the "lifetimes" features, which is still in development. We can consider renaming these (as well as other related keywords) when the development work gels, support is enabled in public Mojo builds, and when we have experience using them.

  • The argument handling in def functions has changed: previously, they had special behavior that involved mutable copies in the callee. Now, we have a simple rule, which is that def argument default to the owned convention (fn arguments still default to the borrowed convention).

    This change is mostly an internal cleanup and simplification of the compiler and argument model, but does enable one niche use-case: you can now pass non-copyable types to def arguments by transferring ownership of a value into the def call. Before, that would not be possible because the copy was made on the callee side, not the caller's side. This also allows the explicit use of the borrowed keyword with a def that wants to opt-in to that behavior.

2023-08-03

⭐️ New

  • A new Tensor type has been introduced. This tensor type manages its own data (unlike NDBuffer and Buffer which are just views). Therefore, the tensor type performs its own allocation and free. Here is a simple example of using the tensor type to represent an RGB image and convert it to grayscale:

    from tensor import Tensor, TensorShape
    from utils.index import Index
    from random import rand
    
    let height = 256
    let width = 256
    let channels = 3
    
    # Create the tensor of dimensions height, width, channels and fill with
    # random value.
    let image = rand[DType.float32](height, width, channels)
    
    # Declare the grayscale image.
    var gray_scale_image = Tensor[DType.float32](height, width)
    
    # Perform the RGB to grayscale transform.
    for y in range(height):
        for x in range(width):
            let r = image[y, x, 0]
            let g = image[y, x, 1]
            let b = image[y, x, 2]
            gray_scale_image[Index(y, x)] = 0.299 * r + 0.587 * g + 0.114 * b

🛠️ Fixed

  • Issue #53 - Int now implements true division with the / operator. Similar to Python, this returns a 64-bit floating point number. The corresponding in-place operator, /=, has the same semantics as //=.

Was this page helpful?