LoginSignup
137
128

Pythonの35000倍速い新言語Mojo🔥 に触れてみた【基礎編】

Posted at

Mojo🔥とは

PythonのシンプルさとRustのスピードとメモリの安全性を組み合わせた、新しいプログラミング言語。

Pythonの35000倍速いとされており、Pythonの弱点である「遅さ」を補うと期待されている。また、書き方もPythonと似ているので移行もしやすいです。

そんな言語が2023年10月19日より、Appleシリコン搭載Macに対応したとのことで、早速触ってみました。

本家のドキュメントはここにまとまっています。

Mojo🔥のセットアップ

ターミナルやVSCodeで使えるようにセットアップが必要です。

以前記事にまとめたので、そちらをご覧ください

Mojo🔥の基本

主にPythonとの比較をしながら書いていきます。

前提

・Mojo🔥はコンパイル言語であり、他のコンパイル言語たち同様、エントリーポイントとして main() が必要
・Pythonのすべての構文とセマンティクスをサポート(Pythonの書き方でも実行可能)

変数 var, let

var x: Int = 1
let y: Int = 2

varは可変な変数、letは不変な変数の定義に用います。Intなどの型タイプは省略も可能です。

関数 : def → fn

Python:

def main():
    x = 1
    x += 1
    print(x)

Mojo🔥

fn main():
    var x: Int = 1
    x += 1
    print(x)

ただ、defのままでも実行できます。fnにすると型の安全性を強制するようにできます。

なので、fnの中でvarなどを削除するとエラーになります。

また、関数に引数や返り値を設定する場合は、型タイプを明記する必要があります。書かないとエラーが出ます

・OKな例

fn add(x: Int, y: Int = 1) -> Int:
    return x + y

・ダメな例

fn add(x, y):
    return x + y

引数のデフォルト値の設定方法はPythonと同じです

borrowed と inout と owned

関数の引数はimmutableな変数(変更不可)として読み取られます。
従って、以下はエラーになります

fn add(x: Int, y: Int) -> Int:
    x += 1
    return x + y

borrowedはそのことを明記する(保証する)役割らしいです
→関数がそのオブジェクトの所有権を持たず変更しないことを保証している
※borrowedは、特に何も書いていない上のfn add() と同じ挙動になります。
→デフォルトでborrowedが省略されていると考えれば良い?

fn add(borrowed x: Int, borrowed y: Int) -> Int:
    return x + y

さらに、inoutというものがあります。

fn add(inout x: Int, inout y: Int) -> Int:
    return x + y

inoutとして設定すると、引数をmutableな変数(変更可能)とできます。そして関数内部で加えられた変更は外部にも影響します。

fn main():
    var a = 1
    var b = 2
    let c = add_inout(a, b)
    print(a)
    print(b)
    print(c)


fn add_inout(inout x: Int, inout y: Int) -> Int:
    x += 1
    y += 1
    return x + y

これを実行すると、

2
3
5

となります。aは元々1, bは2でしたが、fn add_inout() の中で1ずつ足されたので、それぞれ2, 3になっています。

ownedは、引数をmutable(変更可能)とするものの、関数の外には影響を与えないとするものです。
先ほどのコードでinoutをownedに変更すると、

fn main():
    var a = 1
    var b = 2
    let c = add_inout(a, b)
    print(a)
    print(b)
    print(c)


fn add_inout(owned x: Int, owned y: Int) -> Int:
    x += 1
    y += 1
    return x + y

結果は

1
2
5

となって、aもbも変更されていないことがわかります。

クラス class → struct

完全に静的なclassのようなもので、メソッド、フィールド、オーバーロード、デコレータなどを定義できます。

struct MyPair:
    var first: Int
    var second: Int

    fn __init__(inout self, first: Int, second: Int):
        self.first = first
        self.second = second

    fn dump(self):
        print(self.first, self.second)

fn main():
    let mine = MyPair(2, 4)
    mine.dump()

第一引数にself を渡すところや__init__() を定義するところはPythonのclassと同じです

出力は

2 4

となります。Pythonのclassと違うところとして、__init__() で定義するself.firstself.second は事前にvar first: Int と定義しておく必要があることが挙げられます。これがないとエラーになってしまいます。

error: 'MyPair' value has no attribute 'first'
        self.first = first + 1

また、__init__() の引数はinoutとして渡します。

これは、イニシャライザはオブジェクトの初期化を担当する部分であり、このメソッド内でselfオブジェクトを変更するので引数はmutableでなければなりません。したがってborrowedは適しません。

さらに、selfオブジェクトを変更してこのメソッド外においてもその変更を適用させたいのでownedも適しません。したがって、inoutとする必要があります。

まあ、一言で言えば、「selfはインスタンスを示すので、__init__で行われるインスタンスの初期化をクラス内の他のメソッドでも適用させたいため、inoutとする」ということです。

Pythonライブラリを使う Python integration

ドキュメント通りのコードを実行するとエラーが出る。。。

numpyをうまく読み込めないっぽい。色々調べたけど治らず。
まだ情報が少ないからこういう問題が発生した時の対処が大変です。。

最後に

まだまだMojo🔥は発展途中の言語で、ドキュメントにもそのことは繰り返し書かれていました。Pythonに似ていて書きやすいので今後の発展が楽しみです。

次はPythonとの速さの比較の記事を書こうと思っているので、読んでもらえたら嬉しいです!

また、X(Twitter)では日々データサイエンスやAIに関する勉強記録・情報発信をしています。フォロワーはもうすぐ5500人に到達します。

少しでも刺激になるようなことを発信できたらいいなと思っているので、気になった方は見てみてください🔥

では👋

137
128
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
137
128