The Mojo programming language is new. In fact, it’s still under development. At the end of 2023, the latest milestone release is version 0.6.0. There is no word on when the first full increment release will go GA, and the language’s final feature set is still a work in progress.
However, even at this early state of inception, the Mojo programming language has already demonstrated the ability to outperform other major languages including Python, C and Rust.
Modular’s Mojo programming language is poised to revolutionize software development in the AI space. For those who want to stay ahead of the next big machine learning trend, now is the right time to learn how to code your first Mojo program.
In this Mojo tutorial, my plan is to help you build your first Mojo program.
I’m not talking about building a simple Hello World program in Mojo, although that is on the docket. My goal is to show you a mildly sophisticated Mojo program that will accomplish the following:
All of this will be achieved through the development of a simple, Mojo-based number guesser game.
This will be not unlike the Java-based game I wrote a tutorial about. In fact, the Java article will make for a fun comparison between Mojo, Python and Java.
One of my philosophies is that it’s important to have some idea of where you’re going before beginning your coding journey. So, I’m going to put the cart before the horse a little bit and show you the full Mojo code for the example we are about to build before we actually build it. Here it is:
The rest of this tutorial will be the incremental building of this Mojo app from the ground up.
This tutorial assumes you already have installed Visual Studio, along with the Mojo runtime and the Mojo Visual Studio plugins.
Visual Studio isn’t required, as you can compile the file and run it using the utilities that come as part of the Mojo install. Still, VSCode will certainly make things easier for you.
This Mojo tutorial also assumes you have opened Visual Studio up in a clean, empty folder in which to store the code used in this Mojo example.
To begin, create a new file in Visual Studio named number_guesser.mojo.
If you want, you can use the flame emoji as the file extension instead of the .mojo extension. The Mojo plugins in Visual Studio recognize . (“dot-flame”) as well as .mojo.
The ability to use the flame emoji as a file extension is a fun little feature that the Mojo creators put in to reinforce the idea that Mojo is a little bit different from all of the other programming languages out there.
Add the following code to your new file to get the required Hello World Mojo application out of the way:
fn main(): print("Hello Mojo World!")
Run the program and Hello Mojo World prints to the console.
Python developers might notice many similarities, and a couple of big differences, between Mojo and Python’s syntax.
The similarities that will make Python developers feel at ease include the following:
The three big differences between Mojo and Python are:
Python developers will be happy to know that they can actually change fn to def in this Hello World example and the code would work just fine.
Mojo is a superset of Python. Mojo completely supports Python code. That means yes, Mojo supports the def preamble.
The difference between these keywords is that if you use fn, you commit to the stricter coding requirements that Mojo demands. Choose defand you can write any dynamically typed Python code you like.
Given its roots as a scripting language, Python does not require statements to be packaged within a method. Any code that is written in the top-level scope of a file will be executed from top to bottom, both when a file is executed or when it is imported.
This is a pretty significant Python security flaw that remains unsolved, even when the language’s cryptic name equals play construct is used.
In Mojo, variables can be declared in the top-level scope, but all executable statements must go within a method.
Furthermore, to be consistent with all C-based programming languages, Mojo uses a main method to represent the entry-point of an application. The name equals play construct has been eliminated.
We are building a number guessing game, so our program demands two variables:
Note: An experienced developer wouldn’t prepare a variable with the, but since this is intended as a novice developer’s first program, it is permissible as it will help improve the code’s readability. There’s no need to send me any shade on these variable name choices.
To declare a local variable inside a Mojo method, follow these steps:
For constants, you use the let keywords. In this iteration of our application, the magic number will be constant, so we will declare it with let.
Our updated method, after the Hello World print statement is removed, looks as follows:
fn main(): let the_magic_number = 7 var the_guess = 5
You may have heard that Mojo is statically typed, which contrasts statically with Python.
You may also be wondering why we specified no data type when declaring these variables. After all, most statically typed languages require you to indicate if you are using a float or an integer or a String or a Boolean.
Much like Java, in Mojo variables local to a method can have their type inferred, which relieves the developer from explicitly providing a type name. However, explicit typing is allowed and would look as follows:
fn main(): let the_magic_number : Int = 7 var the_guess : Int = 5
Python developers might notice that Int has a leading uppercase letter, while in Python it is all lower-case.
Python’s lower case int does some interesting stuff that might work counter to some of the performance interests of Mojo. The different capitalization provides the Mojo language architects some wiggle-room as they figure out how to handle some of Python’s whole-number of peculiarities.
We need to decide if the_guess is higher, lower or equal to the_magic_numberand that requires conditional statements.
Conditional logic doesn’t vary much from one programming language to another. After all, there are only so many ways to construct an if..else statements.
Mojo follows the familiar syntax of Python for conditional statements, including Elif along with the if and else keywords.
fn main(): let the_magic_number : Int = 7 var the_guess : Int = 5 if the_guess < the_magic_number: print(the_guess + " is too low!"); elif the_guess > theMagicNumber: print(the_guess + " is too high!"); else print("You guessed correct!");
Run the application in its current state and you will get the following output:
5 is too low!
You will also get a few warning messages, as Mojo does not like the fact that the guess variable does not change throughout the course of the program.
Data that is marked as constant and unchanging is handled much differently than data that is variable. The compiler can apply many low-level optimizations when it knows a given value is immutable.
In Mojo, a constant is identified through the use of let Rather than var. When we run our program, the compiler tells us we should use let for the_guess since its value does change. We can dismiss this warning for now, as future iterations of our program will have the_guess live up to its variables moniker.
Rather than hard coding the_guesswe should obtain it from the user.
This requires user input features that are not yet part of the Mojo API. However, they are available from the Python APIs, which is exactly what we’ll use.
To access Python functions inside our Mojo code, we must add the following import at the top of the file:
from python import Python as impy
We then must import the function we need and maintain a reference to the Python component in our code:
let py_input = impy.import_module("builtins").input
Now we can use the Python input function in our Mojo code just as we would in a normal Python program.
However, a resource pulled from Python is returned as a PythonObject. In our code, we explicitly type the data returned from the Python input function as a PythonObject to make this fact clear:
let input : PythonObject = py_input()
Mojo gets a little nervous when you call on objects from external libraries, so we need to add the raises keyword to the main method declaration to indicate that this method might now raise an unexpected exception at runtime:
fn main() raises:
The PythonObject implements the Stringable Mojo trait, so we can easily access the text-based value PythonObject represents:
let text_input : String = input.__str__() #convert PythonObject to String
A cleaner option is to just pass the input to the str() function to get back a Strings:
let text_input : String = str(input) #convert PythonObject to String
We can then convert the Strings to an Int with the atoll method:
the_guess = atol(text_input) #convert Mojo String to int
To finish off our application, we embed the logic for gathering input and evaluating the guess inside a while loop that checks if the correct number was chosen:
while the_magic_number != the_guess:
Pepper in a few print statements to provide feedback to the user, and you’ve completed your first Mojo program!
from python import Python as impy fn main() raises: let py_input = impy.import_module("builtins").input let the_magic_number : Int = 7 var the_guess : Int = 5 print("Guess a number between 1 and 10") while the_magic_number != the_guess: let input : PythonObject = py_input() let text_input : String = str(input) #PythonObject to String the_guess = atol(text_input) #convert String to int in Mojo print("You guessed: " + str(the_guess)) if the_guess < the_magic_number: print(the_guess + " is too low!") elif the_guess > theMagicNumber: print(the_guess + " is too high!") else print("You guessed correct!");)
When the code runs, the output is as follows:
scrumtuous@mojo-tutorial:~/ mojo number_guesser.mojo Guess a number between 1 and 10 2 You guessed: 2 Guess higher! 9 You guessed: 9 Guess lower! 8 You guessed: 8 Guess lower! 5 You guessed: 5 Guess higher! 7 You guessed: 7 You guessed correct!
And that’s it! That’s how easy it is to program in Mojo!
For Python developers, there’s really nothing too difficult to wrap your head around. And developers who come to the world of artificial intelligence and machine learning from languages including Java, Rust and C octothorpe will enjoy the statically typed nature of the Mojo language, not to mention its main method.
There really is something here in this new Mojo programming language for everyone in the computer programming world to love.