The newly unveiled Mojo language is being promoted as the best of multiple worlds: the ease of use and clear syntax of Python, with the speed and memory safety of Rust.
Those are bold claims, and since Mojo is still in the very early stages of development, it will be some time before users can see for themselves how the language lives up to them. But Mojo's originator—a company named Modular—has provided early access to an online playground: a Jupyter Notebook environment where users can run Mojo code and learn about the language's features and behavior.
Because Mojo isn't available yet as an end-user download, this first look focuses on what Mojo is like as a language. We'll examine how it resembles Python, how it's different, and what it has to offer for a programmer familiar with Python or other languages.
Mojo language basics
Mojo can be described as a "superset" of Python. Programs written in Python are valid Mojo programs, although some Python behaviors haven't yet been implemented. Some examples of Python behavior that you won't currently find in Python are keyword arguments for functions, the global
keyword, and list
and dict
comprehensions. It's also possible to use the actual Python runtime for working with existing Python modules, although there is a performance cost.
When Mojo introduces new syntax, it's for system-level programming features, chiefly manual memory handling. In other words, you can write Python code (or something almost exactly like it) for casual use cases, then use Mojo for more advanced, performance-intensive programming scenarios. In both cases, you can draw on existing Python libraries, but the performance cost is higher.
Mojo's other big difference from Python is that Mojo's not interpreted through a runtime, as Python is. Mojo is compiled ahead-of-time to machine-native code, using the LLVM toolchain. To that end, the best performance comes from using features specific to Mojo. Python features are likely to come at the cost of emulating Python's dynamic behaviors, which are inherently slow—or again, by just using the Python runtime.
Mojo vs. Python syntax
Many of Mojo's native language features do one of two things. They're either entirely new features not found in Python at all, or expansions of a Python feature that make it more performant, although with less of Python's dynamism.
For instance, in Python, there is no way to formally declare a variable reference immutable at runtime, although type hinting and other mechanisms can emulate this at edit time. In Mojo, you can use the keywords let
and var
to declare Mojo-specific variables, in much the same way as you would in Rust. The let
keyword indicates a variable is immutable; var
indicates it's mutable. Those restrictions are enforced at compile time, so programs that try to mutate immutable references won't even compile.
Mojo also has its own struct
keyword that stands in contrast to Python's class
. Classes are just Python classes, with all the dynamic (and slow) behaviors you'd expect. The struct
types, though, are more like their C/C++ and Rust counterparts, with fixed layouts determined at compile time but optimized for machine-native speed.
Another Mojo keyword designed to distinguish Mojo's behaviors from Python's is fn
. If you use def
to define a function, you get a Python function, with all the dynamism associated with such things. The fn
keyword defines a function, as well, but as a Mojo function. This means arguments are immutable by default and must be explicitly typed, and that all local variables must be declared (among other things).
The Modular Playground
If you want to find out what it's like to work with Mojo right now, you'll need to take a number and get in line. Modular offers early access to Mojo through the Modular Playground, a web-based Jupyter Notebook environment that runs on Modular's server. Right now, Mojo doesn't have a runtime available for download on one's own system. On the plus side, this means you can run Mojo by way of any computer with a web browser.
The Mojo online environment comes with a few example notebooks, with detailed inline notes about using Mojo for certain tasks. One of the examples is a common programmer's demo, plotting a Mandelbrot set algorithm. At a glance, the code closely resembles Python. Even the new Mojo-specific keywords integrate well with existing Python syntax, so you can run your eye down the code and get a general idea of what's happening.
That demo also shows how to use existing Python modules as part of a Mojo workflow. The actual math is handled in Mojo, then rendered into a numpy
-style array and passed to matplotlib
, a C library, for rendering. In other words, while this demo makes use of legacy Python libraries, everything performance-sensitive is in either Mojo or C, so the Python parts aren't a significant bottleneck—which is more or less as it would be when Python's used well.
The notebook demos also give examples of how Mojo code can be accelerated via parallelism, vectorizing, and "tiling" (increasing cache locality for operations). One of the demos, a 128x128 matrix multiplication demo, yielded a claimed 17-times speedup over Python (using the Python runtime in the Mojo playground) by simply running as-is with no special modification. Mojo added 1866x speedup by adding type annotations, 8500x speedup by adding vectorized operations, and 15000x speedup by adding parallelization.
Again, the best way to verify these claims would be by having Mojo available locally, but it's worth experimenting with both the Python runtime and the Mojo compiler in the same code side by side to see what happens.
Could Mojo replace Python?
The very first public pitches for Mojo made a case for it as a language for data science and machine learning. Those two subjects make up a big part of Python's modern use case—not because Python itself is fast, but because it provides a convenient programmatic interface for fast things that are hard to use as-is.
Mojo's clearly meant to provide a fast-by-default version of that use case, where you don't have to reach for external libraries to make things fast. What Mojo isn't aiming for, at least not this early on, is Python's broader set of use cases: web back ends, process automation, and so on. That may come later, when Mojo is more complete and has a better collection of third-party libraries, but it clearly isn't the first order of business.
Even if Mojo is faster by default, it'll be tough to displace Python's presence in machine learning and data science. Python's user community, existing culture of software, and convenience all make it a mainstay of those fields. Mojo would have to do more than just be fast to replace Python for that work. Still, it'll be interesting to see how Mojo continues to develop along both its Python-compatible and high-speed use-case paths.