こんにちは。虎の穴ラボの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のシンボルとかのようなものか?
Bool
やU32
など型として使われるものも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を定義してます。
new
や fun
ではなく be
キーワードで定義されるメソッドが非同期メソッドになります。
非同期処理の仕組みとしては、ErlangやAkkaなどと同じ、アクターモデルとなっています。
また、actor内での呼び出し順は非同期メソッドだからといって順不同にはなりません。
つまり、 Main
アクターの中にある This is printed first
→ This is printed last
という呼び出し順と、 Hoge
アクターの中にある Hoge init
→ eat
という呼び出し順は逆になることはありません。
ただし、互いのアクターは別々に動作するため、 This is printed first
→ Hoge init
→ This is printed lat
→ eat
のように入り乱れる可能性はあります。実際にお試しいただくと実感できると思います。
詳しくはチュートリアルのアクターの章を参照ください。
サブタイピング
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