Перейти к содержимому

Первая программа

Если окружение уже настроено, напишем первую осмысленную программу и разберём её построчно. Она короткая, но в ней уже видны три главных отличия Mojo от Python.

temperature.mojo
def average(values: List[Float64]) -> Float64:
var total = 0.0
for value in values:
total += value
return total / Float64(len(values))
def main():
var measurements: List[Float64] = [21.5, 23.0, 19.8, 24.2]
var mean = average(measurements)
print("Средняя температура:", mean)

Запустим:

Окно терминала
uv run mojo temperature.mojo
Результат

Средняя температура: 22.125

def main():
print("Привет!")

В Python код можно писать прямо на верхнем уровне файла, и он выполнится сверху вниз. В Mojo так нельзя: каждая программа обязана содержать функцию main() — именно с неё начинается выполнение.

🐍 Python
# Работает: код на верхнем уровне
print("Привет!")
🔥 Mojo
# Обязательно внутри main()
def main():
print("Привет!")

В коротких примерах этого курса def main() иногда опускается ради краткости — как и в официальном мануале. Но чтобы запустить такой фрагмент у себя, оберните его в main().

def average(values: List[Float64]) -> Float64:

В Python аннотации типов — подсказка для человека и линтера; интерпретатору на них всё равно. В Mojo тип — это указание компилятору, как разместить значение в памяти и какие машинные инструкции сгенерировать. Без типа компилятор не может собрать эффективный код, поэтому типы аргументов и возвращаемого значения обязательны.

Именно отсюда берётся скорость: Float64 — это не объект с заголовком, счётчиком ссылок и таблицей методов, как float в CPython, а восемь байт в регистре процессора.

🐍 Python
def average(values):
return sum(values) / len(values)
🔥 Mojo
def average(values: List[Float64]) -> Float64:
var total = 0.0
for value in values:
total += value
return total / Float64(len(values))

Аннотация -> Float64 — это не документация, а контракт: компилятор проверит его на этапе сборки, а не в момент падения программы у пользователя.

var total = 0.0

Первое присваивание объявляет переменную, и перед ним пишется var:

var count: Int = 0 # с явным типом
var count = 0 # тип выведен из значения
count = 1 # это уже не объявление, а изменение значения

Присваивание без var при первом упоминании, как в Python, в Mojo 1.1 не компилируется:

error: implicit declaration of 'count' is not allowed; add 'var' to declare a new name

Так что var перед первым присваиванием обязателен.

mojo temperature.mojo компилирует и сразу запускает программу — удобно при разработке. Но Mojo — компилируемый язык, и результат можно получить в виде обычного исполняемого файла:

Окно терминала
uv run mojo build temperature.mojo
./temperature
Результат

Средняя температура: 22.125

Получившийся бинарник не требует ни интерпретатора, ни виртуального окружения — его можно просто скопировать на другую машину с той же архитектурой и запустить. Для Python-разработчика это, пожалуй, самое непривычное ощущение от языка.

error: expected type in function signature
Что это значит

У аргумента функции не указан тип. Компилятор дошёл до имени аргумента, ожидал двоеточие и тип, но не нашёл их.

Как исправить

Допишите тип: def average(values: List[Float64]) -> Float64:. Привычка из Python писать def average(values) здесь не работает.

error: 'fn' has been removed; use 'def' instead
Что это значит

Вы используете ключевое слово fn, оставшееся от старых версий языка.

Как исправить

Замените fn на def. Семантика при этом не меняется: в Mojo def ведёт себя ровно так, как раньше вёл себя fn — в частности, функция не считается способной бросать исключения, пока вы явно не напишете raises.

🎯 Проверь себя

Почему в Mojo нельзя писать код на верхнем уровне файла, как в Python?

Потому что Mojo — компилируемый язык, а не интерпретируемый: у программы должна быть определённая точка входа, с которой начинается выполнение собранного бинарника. Эту роль играет функция main().

Чем аннотация типа в Mojo отличается от аннотации типа в Python?

В Python аннотация ни на что не влияет во время выполнения — это подсказка для человека и инструментов. В Mojo тип определяет представление значения в памяти и генерируемый машинный код, поэтому он обязателен и проверяется компилятором.

В чём разница между `var x = 0` и `x = 0` внутри функции?

var x = 0 объявляет новую переменную, а x = 0 меняет значение уже объявленной. Если x ещё не объявлена, x = 0 в Mojo 1.1 — ошибка компиляции: неявных объявлений, как в Python, больше нет.

Дальше — переменные: почему каждое новое имя объявляется через var и что происходит с переменной за пределами блока. А за ними — система типов: почему Int в Mojo не то же самое, что int в Python.

Примеры проверены на Mojo 1.1.0

Тексты курса — CC BY-NC-SA 4.0, код примеров — Apache 2.0