Mojo vs Python: Comparison with Examples - Part I: List, Tuple, Dict and Set

enter image description here

If you are reading this article, you may be just as excited as I am about Mojo. Almost a year ago, I already wrote an article about it and now I have even more confidence in its future. I felt it was high time I did some hands-on coding in Mojo and I decided to start a series of articles, this one being the first.

Update:
On 17th June 2024 Mojo 24.4.0 was released and it brought some great improvements. I updated this article based on the new release, but you can check the updates in detail here.

Get Started with Mojo

Install Mojo and write your first Hello, World! example. Mojo has a great VS Code Extension.
I recommend that you continue with the Mojo Manual and check the Mojo standard library.

I am still reading the manual and the documentation, but I think it is best to have some hands-on experience as you go, so I have already started solving last year’s Advent of Code exercises. You can find it on my GitHub.

Examples of List, Tuple, Dict and Set

Before getting into the examples, let’s clarify some things.
In Mojo you must have a main() function which is the entry point of your program. While in Python you define functions with def, in Mojo you can define them with both def and fn. In my previous article I already pointed out the difference, you can have a look here. Throughout all the examples I will be using the stricter and faster implementation with fn.

You can find the complete code in my GitHub repository dedicated to comparing Mojo with Python.

Let’s see the examples then. I will first show the code in Python so that you know exactly what I wanted to achieve in Mojo.

List

Python:

l = []
l.append(1)
l.insert(1, 2)
l.insert(2, 3)
l[2] = 5

if 5 in l:
    print("5 is an element of l, it is present " + str(l.count(5)) + " time(s)")

print("Loop by index:")
for i in range(len(l)):
    print(l[i])

print("Pop:", l.pop())

print("Loop by element:")
for element in l:
    print(element)

l.clear()
print("Length after clear:", len(l))
5 is an element of l, it is present 1 time(s)
Loop by index:
1
2
5
Pop: 5
Loop by element:
1
2
Length after clear: 0

Mojo:

var l: List[Int] = List[Int]()
l.append(1)
l.insert(1, 2)
l.insert(2, 3)
l[2] = 5

if 5 in l:
    print("5 is an element of l, it is present " + str(l.count(5)) + " time(s)")

print("Loop by index:")
for i in range(len(l)):
    print(l[i])

print("Pop:", l.pop())

print("Loop by element:")
for element in l:
    print(element[])

l.clear()
print("Length after clear:", len(l))
5 is an element of l, it is present 1 time(s)
Loop by index:
1
2
5
Pop: 5
Loop by element:
1
2
Length after clear: 0

Apart from declaring the types, which are “real” types, not like in Python, there is no extraordinary difference. You may have noticed that when looping through the list elements in Mojo, I use element[]. This is because iterating over a list directly with a for..in loop currently produces a reference for each value instead of the value itself, so you must add an empty subscript operator [] to dereference the reference and retrieve the value. This is the same for the below examples as well.

Update on 18th June 2024:
The in operator is already available for Mojo lists. Also, new methods were added such as count() or index().

Tuple

Python:

t = (1, "two")
print("Length:", len(t))
print("First element:", t[0])
print("Second element:", t[1])

if 1 in t:
    print("1 is in t")
Length: 2
First element: 1
Second element: two
1 is in t

Mojo:

var t: Tuple[Int, StringLiteral] = Tuple[Int, StringLiteral](1, "two")
print("Length:", len(t))
print("First element:", t.get[0, Int]())
print("Second element:", t.get[1, StringLiteral]())

if 1 in t:
    print("1 is in t")
Length: 2
First element: 1
Second element: two
1 is in t

A big difference here is that it’s a little more “work” to retrieve elements from the tuple. Let’s pause for a moment and jump ahead a little. In Mojo there are parameters and arguments. Parameters are in square brackets and are used at compilation time. Arguments are the usual arguments that are used at runtime. When we retrieve a tuple element in Mojo, we provide the index and type of the element as parameters and it has no arguments. Also, when we declare a List, Tuple or other collections, we have to provide the type of their elements as parameters in square brackets.

Update on 18th June 2024:
The in operator is already available for Mojo tuples.

Dict

Python:

d = {}
d["first"] = 1
d["second"] = 2
print(d)
d2 = {"third": 3}
d.update(d2)
print(d)

print("First element popped:", d.pop("first"))

if "second" in d:
    print("The dictionary has the key 'second'.")

print("Keys:")
for key in d.keys():
    print(key)
print("Values:")
for value in d.values():
    print(value)
print("Items:")
for key, value in d.items():
    print(key, ":", value)

print("Length:", len(d))
d.clear()
print("Length after clear:", len(d))
{'first': 1, 'second': 2}
{'first': 1, 'second': 2, 'third': 3}
First element popped: 1
The dictionary has the key 'second'.
Keys:
second
third
Values:
2
3
Items:
second : 2
third : 3
Length: 2
Length after clear: 0

Mojo:

var d: Dict[String, Int] = Dict[String, Int]()
d["first"] = 1
d["second"] = 2
print(Dict[String, Int].__str__(d))
var d2: Dict[String, Int] = Dict[String, Int]()
d2["third"] = 3
d.update(d2)
print(Dict[String, Int].__str__(d))

print("First element popped:", d.pop("first"))

if d.__contains__("second"):
    print("The dictionary has the key 'second'.")
# since 24.4.0
if "second" in d:
    print("The dictionary has the key 'second'.")

print("Keys:")
for key in d.keys():
    print(key[])
print("Values:")
for value in d.values():
    print(value[])
print("Items:")
for item in d.items():
    print(item[].key, ":", item[].value)

print("Length:", len(d))
d.clear()
print("Length after clear:", len(d))
{first: 1, second: 2}
{first: 1, second: 2, third: 3}
First element popped: 1
The dictionary has the key 'second'.
The dictionary has the key 'second'.
Keys:
second
third
Values:
2
3
Items:
second : 2
third : 3
Length: 2
Length after clear: 0

Dictionary literals are not yet supported in Mojo. Printing out a dictionary is more complicated than in Python, we use a static method with the types as compile-time parameters. Looping through the dictionary’s keys, values and items also differs from Python for the same reason I mentioned in the list section.

Update on 18th June 2024:
The in operator is already available for Mojo dictionaries. Also, new methods were added such as clear() or get().

Set

Python:

s = {1, 2, 3}
s.add(4)
print("Length:", len(s))
s.remove(3)
if 4 in s:
    print("The set contains 4.")

print("Pop:", s.pop())

s2 = {1, 3}
s = s | s2
print("Elements after union:")
for element in s:
    print(element)
Length: 4
The set contains 4.
Pop: 1
Elements after union:
1
2
3
4

Mojo:

var s: Set[Int] = Set[Int](1, 2, 3)
s.add(4)
print("Length:", len(s))
s.remove(3)
if s.__contains__(4):
    print("The set contains 4.")
# since 24.4.0
if 4 in s:
    print("The set contains 4.")

print("Pop:", s.pop())

var s2: Set[Int] = Set[Int](1, 3)
s = s | s2
print("Elements after union:")
for element in s:
    print(element[])
Length: 4
The set contains 4.
The set contains 4.
Pop: 1
Elements after union:
2
4
1
3

The first thing I noticed is that in Python the set comes sorted, but not in Mojo.

Update on 18th June 2024:
The in operator is already available for Mojo sets.

As the examples prove it, Mojo does have a Pythonic style and syntax. Despite these differences mentioned above, Mojo is still quite easy for Python developers to adapt to, at least at this level. This similarity may even get stronger as the currently unsupported features are being implemented in Mojo.
A good example is today’s update (18th June 2024), where we went from Mojo 24.3 to 24.4.

This article ends here, but the next one is already on the way. We will take a look at files and strings. Good luck on your journey with Mojo and Happy Coding! 🔥🔥🔥

Comments