注意 ここにある内容はpony2.x時代にドキュメントに書かれていた物なので、もう古い可能性が高いです。最新の情報は公式ドキュメントを参照してください。
はろぽにー₍₍ (ง´・_・`)ว ⁾⁾
ということで引き続きPonyの機能を見ていきます。
Type
本家だとこの編です。 http://tutorial.ponylang.org/types/static-vs-dynamic/
Ponyは静的型付け&null無しな言語です。 CやC++のコードを呼ぶと残念ながらその部分の型安全性の保障は無くなってしまいます。
Class
Ponyのクラスには継承はありません。代わりにtraitやgoのinterfaceのようなものがあります。
class Wombat let name: String var _hunger_level: U64
のように宣言します。Ponyでは大文字で始まるものは常に型を表します。
let/varはお察しの通り。_
で始まるフィールドはプライベート(同じ型からしかアクセスできない)です。*1
U64のようにかなり厳密な数値型を用意しているのも特長だと感じました。
コンストラクタはnewさえつければ名前をつけることができるので以下の様な便利なコンストラクタを宣言することが出来ます。
class Wombat let name: String var _hunger_level: U64 new create(name': String) => name = name' _hunger_level = 0 new hungry(name': String, hunger': U64) => name = name' _hunger_level = hunger'
name'
のような'
は意味ありげですが、そうすることができる以上の意味は無いそうです。わりと便利そう。
functions
関数はfun
というキーワードで宣言することが出来ます。(結果の型を省略するとNone
という型になります。*2
class Wombat var _hunger_level: U64 new hungry(hunger': U64) => _hunger_level = hunger' fun hunger(): U64 => _hunger_level fun ref set_hunger(to: U64 = 0): U64 => _hunger_level = to
set_hunger
のようにfun ref
とするとメソッドレシーバがreference typeのときだけ(= オブジェクトがmutableなときだけ)呼び出すことが出来るメソッドを定義することができます。このようなレシーバのmutableやimmutableを指定するref
などがreference capabilityと呼ばれる概念です。
ちなみにreference capabilityが指定されていないhunger
メソッドではbox
というreference capabilityが指定されたことになります。box
は「読みはするけど、書きはしない」といった参照を表します。
ちなみにrefの指定を忘れると
/Users/matsu_chara/Documents/sand/helopony/main.pony:9:53: cannot write to a field in a box function fun set_hunger(to: U64 = 0): U64 => _hunger_level = to
のように怒られます。カタアンゼ...キャパビリティセーフ!
Actor
actorはclassと似ていますがbehaviorという非同期メソッドを持っている点が異なります。
behaviorはbe
というキーワードで宣言されます。またbehaviorを呼び出すと常にレシーバそのものをすぐに返却します。
下記がアクターの例です。
actor Aardvark let name: String var _hunger_level: U64 = 0 new create(name': String) => name = name' be eat(amount: U64) => _hunger_level = _hunger_level - amount.min(_hunger_level)
Ponyのランタイムは独自のスケジューラを持っているのでたくさんbehaviorを呼び出すことが出来ます。スケジューラはデフォルトでCPUコアと同じスレッドを持っていて、その数だけ並行に処理が行われます。(ただしアクターモデルなので一つのアクターはSequentialに処理を行います。)
さきほど出てきたrefやboxのような型修飾子を使いこなせばcapabilities secure type system
の力を借りることができるので、安心して色々な処理を平行に行うことが出来るそうですね。₍₍ (ง´・_・`)ว ⁾⁾
ちなみに1アクターは256byteらしいのでたくさん作りまくれそうです。
Subtyping
Ponyでは宣言的部分型も構造的部分型もサポートされています!
宣言的部分型にはtrait
を使います。Ponyのtraitは変数を持てません。以下のように使うことが出来ます。
trait Named fun name(): String => "Bob" class Bob is Named
構造的部分型にはinterface
を使います。これはgoで使われているものに近いものです。
interface HasName fun name(): String
Type Alias
Ponyのtype aliasはunion typeやintersection typeを表現できます。
primitive Red primitive Blue primitive Green type Colour is (Red | Blue | Green)
interface HasName fun name(): String interface HasAge fun age(): U32 interface HasAddress fun address(): String type Person is (HasName & HasAge & HasAddress)
良さそうですね。
以下のように複雑な型を表現しながら型変数に制約を加える事も出来ます。
type Map[K: (Hashable box & Comparable[K] box), V] is HashMap[K, V, HashEq[K]]
この場合K
はHashable box
でComparable[K] box
でなければなりません。boxのようなreference capabilityが指定されているのがPonyっぽくておもしろいですね。
終わり₍₍ (ง´・_・`)ว ⁾⁾
ということで、今回はここまでです。これいつまでやるのか謎ですがreference capabilityがなんなのか気になるのでそのへんまでは勉強したいです₍₍ (ง´・_・`)ว ⁾⁾