注意 ここにある内容はpony2.x時代にドキュメントに書かれていた物なので、もう古い可能性が高いです。最新の情報は公式ドキュメントを参照してください。
はろぽに〜₍₍ (ง´・_・`)ว ⁾⁾ 今回で最終回です。
Capability subtyping
reference capabilityが付いている時のサブタイピング関係について見ていきます。
Simple substitution
まずは^
や!
などが無い場合について考えます。
サブタイピング関係 | 説明 |
---|---|
iso <: trn | isoはread/writeユニークで、trnはwriteユニークなので、isoの方が制約が強いです。そのためisoはtrnのサブタイプです。 |
trn <: ref | trnはmutableでwriteユニークです。refはmutableなので、trnの方が制約が強いです。そのためtrnはisoのサブタイプです。 |
trn <: val | trnではwriteが可能ですが、writeする権利を諦めればglobal immutableになるので、trnはvalのサブタイプとなります。(例1) |
ref <: box | refは他のアクターではread/writeされないことを保証します。boxは他のアクターではwriteされないことを保証します。そのためrefはboxのサブタイプです。 |
val <: box | valはどのアクターもwriteしないことを保証します。boxは自分のアクター以外でwriteされないことを保証します。そのためvalはboxのサブタイプです。 |
box <: tag | boxは他のアクターでwriteされないことを保証します。tagは全く何も保証しないので、boxはtagのサブタイプです |
例1:
var s: String val = recover trn String().append("test") end
また上記の関係では全て推移律がなりたちます。つまりiso <: trn
, trn <: ref
なのでiso <: ref
となります。
Aliased substitution
次はiso!
のような型について考えます。iso!
はisoをconsumeせずにaliasingした場合に出てきます。
サブタイピング関係 | 説明 |
---|---|
iso! <: tag | isoと違い、iso!はtagのサブタイプです。すでにisoによってread/writeユニークな参照があるので、一切のread/writeが許されません。そのためiso!はtagのサブタイプになります。 |
trn! <: box | writeユニークなtrnの参照が既に存在しているので、trn!はrefのサブタイプではありません。boxであればwriteユニークは守られますのでtrn!はboxのサブタイプだといえます。 |
ref! <: ref | refは他のアクターに渡さなければreadもwriteも可能なのでref!もrefと同じように扱うことが出来ます。 |
val! <: val | valは変更されないことを保証しており、readは自由にできるのでval!もvalと同じように扱うことが出来ます。 |
box! <: box | boxもreadする参照が増える分には構わないので同様にboxと同じように扱うことが出来ます。 |
tag! <: tag | tagは何も保証されていないのでtag!もtagと同じように扱うことが出来ます。 |
Ephemeral substitution
最後にiso^
のような型について考えます。iso^
はiso
な参照をconsumeした際に出てきます。
サブタイピング関係 | 説明 |
---|---|
iso^ <: iso | isoな参照はconsumeされているのでiso!と違いiso^はisoのサブタイプとして扱うことが出来ます。 |
trn^ <: trn | trn^もiso^と同様の理由でtrnのサブタイプです。 |
ref^ <: ref^, ref^ <: ref, ref <: ref^ | ref^とrefは完全に交換可能に扱うことが出来ます。 |
val^, box^, tag^ | refと同じように完全に交換可能です。 |
ref^, val^, box^, tag^
のような型は^
無しの型と交換可能なので本来不要なはずですが、reference capability recoveryやgenericsについて考えるときに必要になるようです。
Arrow types
今まではoriginのreference capabilitiesがわかっていることを前提に説明を行ってきましたが、 originのreference capabilitiesが未定の場合もあります。その場合は(未定のorigin ×field)のreference capabilitiesを見て適切な型を自動で決めてくれるviewpoint adapted typeを使う必要があります。 viewpoint adapted typeはPonyでは arrow type と呼ばれています。
Using this-> as a viewpoint
boxなレシーバーで読めるメソッドはrefやvalなレシーバーからも呼ぶことが出来ます(ref, val <: boxなので)
下記の例を考えてみましょう。
class Wombat var _friend: Wombat ref fun friend(): this->Wombat => _friend
friendメソッドの返り値のreference capabilityはboxレシーバーから呼ぶとboxになります。
refレシーバーから呼ぶとref, valレシーバーから呼ぶとvalのように、全てにおいてboxを返すのではなくレシーバーによって柔軟に型を決めて欲しいときがあります。それを実現するのがarrow typeです。this -> Wombat
のように書くと "レシーバーからみた Wombat ref
"が返ってきます。
Using a type parameter as a viewpoint
genericsをまだやっていないので詳細はわかりませんが
class ListValues[A, N: ListNode[A] box] is Iterator[N->A]
のように書くとN
から見たA
のreference capabilitiesを持つAが帰ってくるようなIteratorを指定することが出来るらしいです。
(N
はboxと指定されていますが、サブタイピング関係から実際にはval
やref
になる可能性があります。)
Using box-> as a viewpoint
上で少し解説しましたがgenericsにおいて、未定だけどとりあえずreadできる権限がある型はboxと指定することができます。
標準ライブラリの例を紹介します。
interface Comparable[A: Comparable[A] box] fun eq(that: box->A): Bool => this is that fun ne(that: box->A): Bool => not eq(that)
Comparable[A]
の中でeq
, ne
が定義されています。eq
, ne
はA
をreadできる何かという意味でbox -> A
と指定されています。
実際にはどのようなreference capabilityでも構いませんがreadだけ出来ることを保障したい場合はこのように指定することができます。
終わりに
ドキュメントはまだ続くのですが、ここからは空白ページが目立つようになるので一旦お休みしようと思います。(genericsとかの解説がまだ無いので色々機能が使いこなせていなさそうです) 色々書きましたが特に自分自身がponyに詳しいわけでもなく公式のドキュメントを見て個人が勉強した記録みたいな感じになっていましたが、何かの役に立てばと思います₍₍ (ง´・_・`)ว ⁾⁾