■_
月に一度のアレでした。 名古屋は来週の模様 tapl-nagoya - Front Page
で、今回は18章のあたりをやっていたのですが、「Open Recursion」のあたりで 結構盛り上がりました(というかわたしがわからんことを訊きまくっていたわけなんですが)。 オブジェクト指向プログラミングの特徴として以下のような5項目が挙げられていて (各項目の説明は割愛。知りたい人はTaPl参照)、
- Multiple representations
- Encapsulation
- Subtyping
- Inheritance.
- Open recursion.
わざわざ「open」とくっついている 「recursion」ってなんじゃらほい。と。 説明として
Another handy feature offered by most languages with objects and classes is the ability for one method body to invoke another method of the same object via a special variable called self or, in some languages, this. The special behavior of self is that it is late-bounded, allowing a method defined in one class to invoke another method that is defined later, in some subclass of the first.
とはあるのですが、それだけ読んでてもなにがなにやら。 「外に開かれている」というのがぴんとこないのですよねえ。
Open Recursion | Lambda the Ultimate Open Recursion I've been contemplating an embedded DSL. It strikes me how incredibly useful open recursion would be for what I want to achieve, to the point that I might want to give the technique some kind of explicit support and encouragement. Curious to see what had already been done, a quick google search turned up Closed and Open Recursion by Ralf Hinze. Open recursion Another handy feature offered by most languages with objects and classes is the ability for one method body to invoke another method of the same object via a special variable called self or, in some langauges, this. The special behavior of self is that it is late-bound, allowing a method defined in one class to invoke another method that is defined later, in some subclass of the first.
ところで、型理論で2005年頃にあった飛躍的な進歩ってなんざんしょ Dependent type - Wikipedia, the free encyclopedia
んで、open recursion 絡みの説明で出てきたクラス定義の数々。
setCounterClass = λr:CounterRep. fix (λself: SetCounter. {get = λ_:Unit. !(r.x), set = λi:Nat. r.x:=i, inc = λ_:Unit. self.set (succ (self.get unit))}); setCounterClass : CounterRep → SetCounter
setCounterClass = λr:CounterRep. λr:SetCounter. {get = λ_:Unit. !(r.x), set = λi:Nat. r.x:=i, inc = λ_:Unit. self.set (succ(self.get unit))} setCounterClass : CounterRep → SetCounter → SetCounter
↑には実は問題があって、それは↓のようにサブクラスを定義すると…
instrCounterClass = λr:InstrCounterRep. λself: InstrCounter. let super = setCounterClass r self in {get = super.get, set = λi:Nat. (r.a:=succ(!(r.a)); super.set i), inc = super inc, accesses = λ_:Unit, !(r.a)}; instrCounterClass : InstrCounterRep → InstrCounter → InstrCounter
newInstrCounter = λ_:Unit. let r = {x=ref 1, a=ref 0} in fix (instrCounterClass r); newInstrCounter : Unit → InstrCounter
この問題を解決するのにはいくつか方法があって(三つ挙げられていた)、 たとえば thunk を持ち込んでこう。
setCounterClass = λr:CounterRep. λself: Unit→SetCounter. λ_:Unit. {get = λ_:Unit. !(r.x), set = λi:Nat. r.x:=i, inc = λ_:Unit. (self unit).set(succ((self unit).get unit))}; setCounterClass : CounterRep → (Unit→SetCounter) → Unit → SetCounter
買ったはいいけど積んだままになっている人は一度来てみるといいんじゃないかな?
(Advanced…をどうするかは決まってないんだけどねw)