Logo

This Week in Mojo 2023-07-21

Official Content

Proposal

Jeff Niu has put forward a Mojo and Dynamism proposalopen in new window for how Mojo will handle Python dynamic behaviour, with a ladder type system:

  • fn for fully optimized static behavior
  • def will by default use vtables and have the ability to inline method calls for better performance
  • def opt-in @dynamic decorator to match Python behaviour while retaining some performance benefits such as no GIL. Python to Mojo conversion tool to automatically add this decorator.
  • Importing a Python module will work the same as it does now will full CPython ABI interop but no performance improvement

Roadmap addition

New section added to the roadmap document overall prioritiesopen in new window:

Mojo is still in early development and many language features will arrive in the coming months. We are highly focused on building Mojo the right way (for the long-term), so we want to fully build-out the core Mojo language features before we work on other dependent features and enhancements.

Currently, that means we are focused on the core system programming features that are essential to Mojo’s mission, and as outlined in the following sections of this roadmap.

In the near-term, we will not prioritize “general goodness” work such as:

  • Adding syntactic sugar and short-hands for Python.
  • Adding features from other languages that are missing from Python (such as public/private declarations).
  • Tackling broad Python ecosystem challenges like packaging.

If you have encountered any bugs with current Mojo behavior, please submit an issue on GitHub.

If you have ideas about how to improve the core Mojo features, we prefer that you first look for similar topics or start a new conversation about it in our GitHub Discussions.

We also consider Mojo to be a new member of the Python family, so if you have suggestions to improve the experience with Python, we encourage you to propose these “general goodness” enhancements through the formal PEP process.

Community Content

Mojo Playground Update

⭐️ New

Mojo now includes a Limits module, which contains functions to get the max and min values representable by a type, as requested in Issue #51. The following functions moved from Math to Limits:

  • inf()
  • neginf()
  • isinf()
  • isfinite()

Mojo decorators are now distinguished between “signature” and “body” decorators and are ordered. Signature decorators, like @register_passable and @parameter, modify the type of declaration before the body is parsed. Body decorators, like @value, modify the body of declaration after it is fully parsed. Due to ordering, a signature decorator cannot be applied after a body decorator. That means the following is now invalid:

@register_passable # error: cannot apply signature decorator after a body one!
@value
struct Foo:
    pass

Global variables can now be exported in Mojo compiled archives, using the @export decorator. Exported global variables are public symbols in compiled archives and use the variable name as its linkage name, by default. A custom linkage name can be specified with @export("new_name"). This does not affect variable names in Mojo code.

Mojo now supports packages! A Mojo package is defined by placing an __init__.mojo or __init__.🔥 within a directory. Other files in the same directory form modules within the package, this works exactly like it does in Python, for example:

main.🔥
my_package/
  __init__.🔥
  module.🔥
  my_other_package/
    __init__.🔥
    stuff.🔥

main.🔥

from my_package.module import some_function
from my_package.my_other_package.stuff import SomeType

fn main():
    var x: SomeType = some_function()

Mojo now supports direct module and package imports! Modules and packages can be imported and bound to names. Module and package elements, like functions, types, global variables, and other modules, can be accessed using attribute references, like my_module.foo. Note that modules lack runtime representations, meaning module references cannot be instantiated.

import IO as io
import SIMD

io.print("hello world")
var x: SIMD.Float32 = 1.2

🦋 Changed

Reverted the feature from 2023-02-13 that allowed unqualified struct members. Use the Self keyword to conveniently access struct members with bound parameters instead. This was required to fix Issue #260.

Updated the RayTracing notebook: added step 5 to create specular lighting for more realistic images and step 6 to add a background image.

🛠️ Fixed

Issue #260open in new window - Definitions inside structs no longer shadow definitions outside of struct definitions.

Mojo Team Answers

Top level code in REPL and Jupyter

The default right now is in a bit of a weird place, Mojo top-level code behaves differently than anything else. It is "strict" by default, however the problem right now is that top-level Mojo code is neither "static" in the fn sense or "dynamic" in the def sense. The goal is to make it behave like an imperative body of code.

Only allowing fn in struct

I can see how this might avoid some accidental use of dynamic behavior, but I'm not sure why that is something we're worried about. Further, there are other issues - we need to support top level code and other things that aren't tied to an fn keyword. Furthermore, we want constrained dynamic classes as well (Jeff will share a doc hopefully ~this week about this) in Mojo that aren't as dynamic as Python's.

At the end of the day, we also want fn and def to be friends and get along and allow intermixing. This is a pretty important design principle - we don't want "fn to be mojo" and "def to be legacy python code", so I see this approach working...

Renaming Mojo to Python++

Just to set expectations here, we don't plan to rename Mojo - we quite like the name 😀. I agree with you that Python++ is a useful working model to think about some of Mojo's goals though!

Vales region borrow checker

Yep, I've followed it. It is currently experimental and adds non-trivial overhead to the runtime of a program, so it will be interesting to see how it bakes out and matures in Vale. For Mojo, we're sticking with somewhat more traditional implementation approaches.

This isn't to say "no, we will never do this": we need to get more experience with the planned lifetimes and other features, and if they don't work then we'd consider it. That said, I can say that "it isn't on our radar and it looks like there is more research to be done before we'd seriously consider it".