虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Pony言語を触ってみよう前編

こんにちは。虎の穴ラボのY.Fです。

突然ですが、自分の趣味の一つとしてマイナーな言語やフレームワークに触るというのを持っていたりします。 その一環として、今回はPonyと呼ばれるプログラミング言語について紹介して見たいと思います。
ドキュメントはこちら www.ponylang.io

本当は一回の記事に収めるつもりでしたが思いの外長くなったので前編後編としています。(後編は後日)

Pony言語とは

公式ドキュメントによると、以下の特徴がある言語とされています。

  • オブジェクト指向、アクターモデル、静的型付け
  • 型安全
    • 数学的証明によって担保される型安全
  • メモリ安全
    • タングリングポインタやバッファオーバーフローが起きない
  • 例外安全
    • 実行時例外が存在しない
  • データ競合フリー、デッドロックフリー
    • ロックやアトミック系操作が存在せず、型システムによってコンパイル時にデータ競合が無いことが保証される
  • ネイティブコード生成
    • AOTコンパイルされ、インタプリタやVMなどは必要ない
  • C言語との高い親和性
    • Cのライブラリをそのまま呼び出せる

Ponyはこうした特徴をアクターモデルと参照値の管理を通して担保しています。

チュートリアルのドキュメントもしっかりしたものが用意されています。 tutorial.ponylang.io

ただし、Why not Pony? の部分に書かれているように全く安定していません。 本番に利用するのはまだちょっと厳しいかと思います。

導入

では、チュートリアルの中身に少し触れてみたいと思います。

ponyupというツールチェインがあるのでこちらを使います。 github.com

$ brew install libressl
$ sh -c "$(curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/ponylang/ponyup/latest-release/ponyup-init.sh)"

コマンド実行時に表示されるパスを .bash_profile などに書き込みます。

export PATH=/path/to/.local/share/ponyup/bin:$PATH

ponyupを使ってponyをインストールします。まだ1.0になってない言語ですので、nightlyを入れてみようと思います。

$ ponyup update ponyc nightly

名前から推測できるようにRustのrustupと似たような使い心地ですね。 これで ponyc コマンドが使えるようになりました。

Hello World

定番のHello Worldをやってみます。特に面白みは無いですが、最初の一歩としては良しとします。

任意のディレクトリに tutorial ディレクトリを作成し、更にその中に helloworld ディレクトリを作ることにします。また、ファイル名は main.pony にします。

$ mkdir tutorial
$ cd tutorial
$ mkdir helloworld
$ cd helloworld

main.ponyの中身を以下のようにします。

actor Main
  new create(env: Env) =>
    env.out.print("Hello, world!")

この状態で、ponyc コマンドを実行するとコンパイルされ、バイナリが吐き出されます。

$ ponyc
$ helloworld
Hello, world!

少し解説すると、classっぽく使ってる actor Main の部分は非同期処理が含まれる可能性を示しています。
Ponyには別途classキーワードも存在しますが、両者の違いは非同期メソッドを持てるか持てないかになるようです。
また、MainとなっているのはC#やJavaのメインクラスと同じ理由です。

文法について

ざっくりドキュメントをまとめると文法は以下のような感じです。

  • classとactorが存在する
    • 前者が非同期処理なし、後者があり
  • コンストラクタは new hogehoge で定義
    • 呼び出し方は Hoge.hogehoge(fuga)
  • varは変更可能なフィールド
  • letはreadonlyなフィールド
    • C#だとかのreadonlyと同様にコンストラクタでのみ初期化可能
  • プライベートメソッド/フィールドは _ をつける
  • 継承はない
  • メソッド、フィールド、ローカル変数の類は小文字開始、それ以外は大文字開始
  • 列挙型の要素などに使える Primitive と呼ばれるものがある
    • メンバを持たず、変更不可能な class のような形
    • また、プログラム上で単一
    • Rubyのシンボルとかのようなものか?
    • BoolU32 など型として使われるものもPrimitiveの一種
    • メソッドは持つことができる

Actorについて

上記で書いたようにactorは非同期処理を持つことが出来ます。

actor Hoge
  new create(env: Env) =>
    env.out.print("Hoge init")
    eat(env)

  be eat(env: Env) =>
    env.out.print("eat")

actor Main
  new create(env: Env) =>
    Hoge(env)
    call_me_later(env)
    env.out.print("This is printed first")

  be call_me_later(env: Env) =>
    env.out.print("This is printed last")

非同期であるということがわかりやすくなるように二種類のactorを定義してます。

newfun ではなく be キーワードで定義されるメソッドが非同期メソッドになります。
非同期処理の仕組みとしては、ErlangやAkkaなどと同じ、アクターモデルとなっています。

また、actor内での呼び出し順は非同期メソッドだからといって順不同にはなりません。 つまり、 Main アクターの中にある This is printed firstThis is printed last という呼び出し順と、 Hoge アクターの中にある Hoge initeat という呼び出し順は逆になることはありません。
ただし、互いのアクターは別々に動作するため、 This is printed firstHoge initThis is printed lateat のように入り乱れる可能性はあります。実際にお試しいただくと実感できると思います。

詳しくはチュートリアルのアクターの章を参照ください。

tutorial.ponylang.io

サブタイピング

traitによる宣言的部分型と、interfaceによる構造的部分型があります。

trait Named
  fun name(): String => "Bob"

class Bob is Named

interface HasName
  fun name(): String

class Larry
  fun name(): String => "Larry"


actor Main
  new create(env: Env) =>
    let bob: Named = Bob
    let larry: Larry = Larry
    trait_call(bob, env)
    // 構造的部分型によってnameメソッドがありさえすれば呼べる
    interface_call(larry, env)
    interface_call(bob, env)

  fun trait_call(n: Named, env: Env) =>
    env.out.print(n.name())

  fun interface_call(n: HasName, env: Env) =>
    env.out.print(n.name())

trait_callは引数の型として Named トレイトを指定しています。これは通常の継承のように Named のサブタイプとして指定されているものなら引数に渡すことが出来ます。 interface_callは引数の方としてinterfaceを指定しています。そのようにすると、 HasName インターフェースが持つ name メソッドを持つオブジェクトなら引数にわたすことができるようになります。

まとめ

非同期処理が actor でめちゃくちゃ簡単に実装できるのはちょっと新感覚です。
前編としては、主に文法周りの紹介で終わりました。Pony言語が本領を発揮するのはこのあとの安全性の部分だと思うので、ぜひ後編にもご期待ください。

P.S

虎の穴ラボ主催のオンラインライトニングトークイベントを 7/29(水)19:30〜 開催します!
今回もフリーテーマとなっており、ITに関連する内容であれば、何でも大歓迎ですので、初心者の方も練習の場として、お気軽にご参加ください!
connpassにて参加受付中です!
yumenosora.connpass.com

虎の穴ラボでの開発に少しでも興味を持っていただけた方は、採用説明会やカジュアル面談という場でもっと深くお話しすることもできます。ぜひお気軽に申し込みいただければ幸いです。
カジュアル面談では虎の穴ラボのエンジニアが、開発プロセスの内容であったり、「今期何見ました?」といったオタクトークから業務の話まで何でもお応えします。

カジュアル面談や採用情報はこちらをご確認ください。
yumenosora.co.jp

また、毎週火曜、木曜にはTora-Lab Meetup!と称して虎の穴ラボのエンジニア・採用担当とお話できる機会を設けさせていただくことになりました。
虎の穴ラボに興味がある、エンジニアや採用担当に質問したいことがある、などどなたでもご参加下さい。
news.toranoana.jp

さらに、弊社では新型コロナウイルス感染症終息後もフルリモートを継続導入することになりました!
地方在住のまま働きたい人など、上記Meetupやカジュアル面談、面接すべてリモート対応していますので、ご興味のある方はぜひいずれか応募してみてください! prtimes.jp