top recent

クロージャとオブジェクト

関連ページ

クロージャとオブジェクト:オブジェクトの定義

目次

  1. Objects === Closures (mod Syntax)...
  2. てゆーか...
  3. 同意。...
  4. 順不同になりますが...
  5. 逆にSchemeのClosureのほうが、...
  6. えーと、申しおくれましたが"Schemer's Way"の作者です。...
  7. 話がこんがらがって来たので整理しますね。...
  8. 通りすがりの者ですが、くちばしを突っ込んでみます。...
  9. オブジェクトの定義...
  10. オブジェクト指向と OOA と OOP...
  11. そういや当然だがclosureにはメンバ変数がないなあ...
  12. 異聞(?) by Smalltalk屋さん...
  13. Generic functionとobjectとclosureと…...
  14. Closure === Object では困る場合...
  15. 違和感っすか…...
  16. Schemerがオブジェクトを使う時...
  17. 非「Class指向」者(^^;がオブジェクトを使う時...
  18. dynamic objectなら...
  19. 実は単なる「参照指向」...
  20. これまでの話を読んでいて思ったんですが、...
  21. それって語順の問題だけではないのでしょうか?...
  22. >21...
  23. 新ページ...
  24. 例えばオブジェクトを「シンボルを引数に取る関数」ととらえて見ると...
  25. 色々試しましたが、結局schemeの場合はシングルメソッドなら...

Objects === Closures (mod Syntax)

(状態管理の2つの方法 (プログラミング)より)

クロージャとオブジェクト、どっちがプリミティブかってことじゃなく、相互に変換可能だっていうのはその通りでしょう 状態管理の2つの方法 (プログラミング)
(プリミティブ競争をしたら純粋なλ算法[[チューリングマシン]]にたどり着いちゃうし)

クロージャとオブジェクトの等価性に関しては、たぶん Guy Lewis Steele, Jr.. "Lambda: The Ultimate Declarative". MIT AI Lab. AI Lab Memo AIM-379. November 1976. が一番まとまっているのではないかと。ここで読めます: http://library.readscheme.org/page1.html

現実的に問題となるのは、言語の提供するモデルが
- 自分の解きたい問題領域に対してどのくらいサポートしてくれるか
- 自分の解きたい問題領域に対してどのくらいカスタマイズできるか
の2点だと思います。どちらも解きたい問題領域に依存するので一般的な解は無いのでしょう。Lisp系は伝統的にカスタマイズ性重視ですね。逆にC++やJavaなんかは特定のオブジェクト指向モデルを決め打ちしてそれをなるべくサポートする方向で設計しているかr、そのモデル内でやるぶんにはいいけど、別のモデルを使いたくなると不便だと。

[[id:590]] 2002-05-30 23:12:18


てゆーか

Lispと比較したいならば、C++やJavaを出すのは不適切じゃないか?という疑問です。

この種目でOOP国代表選手として選考されるべきは、C++は言うにおよばずSmalltalkでも駄目で、
最低でもRuby、できればJavaScriptやselfやNewtonScriptやLENS(俺のやったことない言語ばっかりだな(笑))でないと
バランスがとれないのではないかと。
たとえばクラスを使わずメソッドを作ってbindすることができる言語でないと…。

結局はC++の呪い(歴史的な)なんだと思うんだけど、Object指向の話をするときに
間違ってClass指向の話をしてしまう人は、多いんだよね。
普通の奴らの上を行きたければ(笑)、それでは駄目なんだと思う。

[[id:613]] 2002-05-31 06:26:47


同意。

スタックフレームをselfでモデル化すればクロージャも継続もオブジェクト。これぞ純粋オブジェクト指向?

[[id:614]] 2002-05-31 06:27:41


順不同になりますが


>答えその1。オブジェクト指向は、「言語の機能」として備えなければならない程プログラミング言語にとって本質的なものじゃない。
>答えその2。オブジェクト指向の実装方法は一つではなく、問題領域に合わせて最適な実装方法は異る。

[[id:615]] 2002-05-31 06:28:46


逆にSchemeのClosureのほうが、

「「言語の機能」として備えなければならない程プログラミング言語にとって本質的なものだ」とか
「実装方法は一つであり、問題領域によらず最適な実装方法は同じ」とかだと、
なぜ言い切れるのか?という疑問、なんですよねえ。
#逆にそう言い切れないならデカイ面(^^;される謂れは無い。

結局、OOPとLisp流とを「同じ土俵」に立たせた上で議論しないと、意味が無いような…

ところで、別の実装方法のClosure、とでもいうようなモノは実在するんでしょうか?

>どっちの言語が「より純粋な」オブジェクト指向かっていう論争

純粋な関数型言語、とかいう言い回しは有ったように思いますが :-P。
それとも、アチラのほうは「論争」になり得ず、(Contextに依存せず(笑))常に一定の答えが出る、ということなのでしょうか?

[[id:616]] 2002-05-31 06:29:59


えーと、申しおくれましたが"Schemer's Way"の作者です。

私の理解では、まずclosureと、(内部に状態を持ち、メッセージを受け取って動作するという意味での)objectとは、どっちがどうではなく全く等価であると。それは上に挙げた論文でGLSが指摘してます。ですから、そういう意味でのobjectをプリミティブとすることは、closureをプリミティブとすることと何ら変わりません。それを実装する方法のバリエーションはここでは問題にしてないです。

問題は「オブジェクト指向」の方です。「オブジェクト指向」と言った時に、「何をもってオブジェクト指向と言うか」「何をプリミティブにもってきたからオブジェクト指向言語と言えるか」という議論には幅があり、その範囲をどう定めるべきかは目的に依存するということです。これに関してはJonathan Reesがわかりやすい文章を書いています:
http://www.paulgraham.com/reesoo.htm

だもんで、内部に状態を持つプリミティブデータが自然にオーバヘッド無く作れて、かつ構文が自由に変更できる言語ならべつにclosureでなくたって構わないでしょう(selfのモデル+マクロとか)。それを使って、Jonathan Reesが挙げているオブジェクト指向の可能な要素のうち自分に必要なものだけを実装するのはそんなに難しくないでしょうから。

あと、「純粋な関数型」と言ったら副作用無し、というのを連想しますね。

-「問題になり得ない」のではなく「していない」のですか?ならば、なぜClosureだけは「しなくてもよい」のか?という話になります。
--…(^^; たぶん実際はそう↑じゃなく、ClosureよりもOOPのほうが(むやみに)広く漠然とした概念を指す語である、ということだとは、思いますが…
--だとすれば、そもそも「OOPを実装(した言語)」という概念が、意味をなさない、という点が問題だということですね。名前付け問題の段階でオカシくなってるから、「SchemeにOOPをつけよう!」なる主張は最初から無意味な議論だと…
--「同じ土俵に立たせる」というより、「OOPという名が指す概念集合の中から、 Closureと同じ土俵に立てる部分を抜き出す」ということかな…

----

再び作者です。なんか混乱のもとが分かってきました。"Schemer's Way" は、ClosureがObjectよりプリミティブである、とは主張していません。たぶん「答えその1」の書き方が悪かったんだろうな。

「オブジェクト指向」というのはJonathan Reesが挙げたいくつかの基本的な言語機能の任意の部分集合です。それらの言語機能をコンパクトに実現できるプリミティブがあれば、「オブジェクト指向」と呼ばれている「もの」---それは人によって異なるのですが---はその上に実装できる、というのが「答えその1」の言っていることです。

で、「たまたま」SchemeはClosureをプリミティブとして持っていた(というより、SchemeはClosureをプリミティブとすることを選んだのですが)、だからそれで好みの「オブジェクト指向」を書けばいいじゃん、というわけです。

だから、closureではないけど同等の力を持つプリミティブを持っている言語があれば、それを使って好みの「オブジェクト指向」を書けばいい。

じゃあそのプリミティブって何か。Actorモデルでの「オブジェクト」でも良いでしょう。ただActorモデルの「オブジェクト」はclosureと同等だとGLSは言っていますが。あるいは別の何か、「ほげほげ」であっても良い。その「ほげほげ」をその言語では「オブジェクト」と言っているかもしれない。ただ、だからといってその言語を「オブジェクト指向」と呼んでしまうと、最初の混乱に逆戻りです。

[[id:617]] 2002-05-31 14:42:38


話がこんがらがって来たので整理しますね。


(1) "Closure" は明確に定義された概念ですが、 "OO" はJonathan Reeが言うように、いくつかの要素のうち、人によって好きなサブセットを抜き出して「これが"OO"たる必要条件」と言っているような状態だ。「同じ土俵」という議論は特定のOOの定義を決めないことには始められない、ということ。これが"Schemer's Way"の「答えその2」の背景。

(2) で、内部に状態を持ち(変更不可であっても良い)、(方法はともかく)メッセージを送れる実体が簡単に作れる、という機能が言語にあるなら、他のOOの要件はsyntactic sugarやライブラリにすぎない、というのが「答えその1」の主張。

(3) 「内部に状態を持ち…という機能」はClosureと等価で、単にsyntaxが違うだけだ、というのがGLSの論文。GLSはActorと言ってるけど。

Schemeは Closureを選んだけど、GLSが言うのとはまた違うアプローチで「内部に状態を持ち…という機能」を実現できないのか、という議論はありでしょう。そこで Closureが一番だ、とは "Schemer's Way" では主張してません。あそこで対象としているのはあくまで (人によって定義の異なる) "OO" という概念です。

で、Schemer's Wayから離れて上のパラグラフの議論を発展させることには多いに興味があります。Closureは変数を持つ関数をfirst classにしたものですから、言語要素として「変数を持つ関数」というのを持ってしまうとそれはclosureか、その機能限定版にしかならないので辛いですね。関数呼び出しという概念を無くして、世の中にあるのは状態を持つ実体でそれらがメッセージを送り合っているのだ、というのは別の候補ですが、それってActorモデルですな。Dictionaryを複数持つ、という形でOOにアプローチしたprologを見たことがありますが、それは結構いいかも、と思っています。

[[id:618]] 2002-05-31 06:31:20


通りすがりの者ですが、くちばしを突っ込んでみます。

クロージャとオブジェクトの等価性についての議論のようですが、
両方を「同じである」と言い切るのは違和感があります。
実際にそれらがどのような場面で用いられるかを考えてみると、
明らかに再利用する上での粒度のようなものが違うように思うのです。

クロージャが「一つの関数とそれが参照する変数の組」であるのと比較すると
オブジェクトは「一つの役割に関連した変数とそれを操作する関数の組」に
なるのではないでしょうか?
あきらかにオブジェクトの方が一段上(優劣の意味でなく)の抽象的な概念を
あらわしていると思います。
このことはクロージャを利用するとオブジェクトと等価なことが出来るという
こととは別のことだと考えます。
Javaの無名インナークラスは、他の言語ではクロージャで実現する部分を
オブジェクト指向的に突き詰めて考えた結果、生み出されたもののように
思います。その意味でJavaはオブジェクト指向に「純粋」であるように
感じます。
(実際に使う側から考えると粒度の小さいクロージャのほうが扱いやすい気がしますが。)

[[id:619]] 2002-05-31 06:31:44


オブジェクトの定義

長くなったのでクロージャとオブジェクト:オブジェクトの定義へ移動しました。

[[id:656]] 2002-06-07 09:13:00


オブジェクト指向と OOA と OOP



ただ「オブジェクト指向」といった場合に何を考えるのかっていうのが
あちこちでだいぶ違うっていうのが知られています.オブジェクトの粒
度についてもそうで,これも分野によってだいぶ違う.

分析/設計分野からオブジェクト指向にふれるとあんまり細かいオブジェ
クトは考えなさそうです.かなり小さくなっても何らかの構造があって,
内部状態に何らかの制約があるようなものまでではないでしょうか.

プログラミングや計算モデルからはいった場合,もっとずっと小さなも
のであってもオブジェクトとして扱いそうです.数値を二つ受け取って
和を返すオブジェクトとか.メッセージを受け取って何かをする何か :-)
っていうのが本質で後はどうでもいい.


クロージャとの等価性っていう文脈で出て来るのは計算モデル的な細粒
度オブジェクトでしょう.メッセージの dispach がどこで行われるかっ
ていうこと以外何も違いがない.

アクターはちょっと違っててこっちはクロージャに継続をいれた系にな
るのかな.call/cc の意味ではなく,最適化される末尾再帰的継続.

- そうっすね。話を発散させないようにそこには触れなかったのですが、そのぶん議論が不正確になっていたかもしれません。


----
ここで言う細粒度オブジェクトっていうの,きちんと考えると関数/クロージャの
自然な拡張になってます.どういうことかというと,

(obj arg ...)

としたとき,
- 関数では引数のパターンにも内部状態にも関係無く処理が決まる.
- クロージャでは引数のパターンは処理に影響を与えない.
- オブジェクトでは引数のパターンで処理そのものが変化する.

もっとも「引数のパターンによって複数の同名のものの中から『正しい』関数/ク
ロージャを選択して評価する評価器」ってのは存在できるわけで,強い型づけの下
だとあんまり意味のある違いにはならないかも?

[[id:622]] 2002-06-02 00:01:15


そういや当然だがclosureにはメンバ変数がないなあ

closureをちょっと工夫してobjectっぽく見立てる、ということを考えて、
ふと思いだした(というか今まで意識してなかったのかよ俺は?)のですが、
closureでそれをやると、もともと「メンバ変数」と「ローカル(?)変数」を
「区別しない」世界から、話がスタートすることになるわけですよね。

oop(恐らくどの部分集合にせよ)に慣れた目から見ると、これってちょっと新鮮です。

- http://www.csl.sony.co.jp/project/Morphe/ なんていかが?


というわけかどうかはさておき、グラフ計算ソフト(仮称)のほうは、
順調にいけばきっと、上記の話とは丁度逆で、
一部のobjectのメンバ変数をローカル変数のように使う、
という系になりそうな雰囲気です。はい。

てゆーか多分できると思うんだけど…
#で、今更awtの連中を"始める"俺。おいおい…
##てゆーかwaba(やsuperwaba)も捨てがたく思ってるし。ぉぃぉぃ…
###それとも LispMe で書かないと呪われるんでしょうか?(ぉ

- closureの関数の外側で定義されている自由変数がメンバ変数にあたるもので、内側で定義する普通の変数がローカル変数にあたるのでは?(→自由変数を持つ関数 (プログラミング言語)参照) --SHIMADA

-なるほろ。一番内側の関数の変数は外から全然見えないからlocal変数のようなものであり、更に内側に別の関数があればソイツからアクセスできちゃうのでメンバ変数みたいだ、と。-戯
--継続を外に持ちだす手段を用意しなければ、local変数の寿命も一回づつコッキリになる(処理系から見れば、不要だと判るから作られないか、作ってもGCされるか…)、ということでしたよね?

--scopeと寿命が同時に制御できる、という感じですかねえ?
---だとするとoop屋の違和感がそこに集中(殺到(^^;)するかも。oop人はscopeと寿命を如何に切り離す(直交にする)か?に神経そそいでいた節が有るので(^^;
---scheme(など)では、その直交さは、どうやるとうまく醸し出せますか?
---やっぱり、「継続」の2文字で説明は終り、ですか?(ぉ

--JavaScriptでprivateメソッドを実現するために、Local手続きの参照を使う、という話がどっかに有ったが、それと似てる?

signature: 戯

[[id:623]] 2002-09-11 15:02:39


異聞(?) by Smalltalk屋さん

なんか今回ここで議論されてた雰囲気と、おもいっきり違う意見であるような気がするコレ。
http://www.sra.co.jp/smalltalk/SML/2001-2827/mails/2101-2200/2168.txt

えええ?LispってRichなのですか?

[[id:635]] 2002-06-05 01:36:55


Generic functionとobjectとclosureと…


in オブジェクトの定義(クロージャとオブジェクト:オブジェクトの定義)
> あと、objectに対置すべき概念はclosureではなく、Generic Functionではないだらうか?

んー、gfもメソッドを束ねるobjectでありますが、したがってclosureをプリミティブとする立場からはgfもclosureで容易に表現出来てしまうので… (もちろん、それを「closureで実装してみせただけ」と考えることもできますが)

確か、yasosというScheme上のobject指向拡張が、closureを用いてエレガントにgfを実装していました。gfもobjectもclosureになります。

----
>それを「closureで実装してみせただけ」と考えることもできますが
はい、そう思います。;-)




signature: Schemer

[[id:640]] 2002-06-05 07:56:38


Closure === Object では困る場合


自分でclosure=objectだと主張しておいてなんですが、それでは困る場合というのも思い付いてしまいました。言語的に「全てはオブジェクト」とする場合、すなわち 1+1は オブジェクト '1' に '+ 1' というメッセージを送っているんだ、と考えたい場合、当然 '1' はLisp的にはクロージャではないんで、このモデルは使えませんな。

もちろんchurch numeralみたいにして数値も全てclosureで表現してしまうこともできますが、それじゃ全てのメカニズムをチューリングマシンで表現するのと同じだし。CLOS的にプリミティブデータ型でもディスパッチできるようにすることもできますが、それも実装できるということを示しているにすぎないわけで。

object == <stateを持ちメッセージを受け取って動作するもの>

とすれば、それは構文的なサポートや組み込みのメソッドディスパッチ機能を別にしてclosureと等価ですが、

object == <言語内で扱える全てのもの>

とする徹底したOOだとそんなことはない、のか。

signature: Schemer

----
それはJavaにintとjava.lang.Integerとが有るのと似たようなものでしょうか?(^^;

あとimmutable objectの立場をどう捉えるか?って話もありそうだし。

----
計算モデルと言語の実装が混ざってるんじゃないかと.別に 1 が closure
でも構わないのでは.ほんとにそう実装すると激しく効率が悪いから実際に
はふつうに数値として扱ってみるっていうぐらいの話で.

immutable object は関数ととらえられる.closure でもいいんだけど,そ
れ自体は変化しないという性質や,それゆえにコピーしてばらまいても誰も
困らないっていうのを表現するには便利そうだ.

....ここで関数だの closure だのいってるのは全部引数のパターンで内部
動作が変わっても良いっていう変な拡張が入っているので念のため.

[[id:641]] 2002-06-07 10:23:01


違和感っすか…

オブジェクトの定義(クロージャとオブジェクト:オブジェクトの定義)
>OO的にみて、Schemeのアプローチがどんなふうに違和感があるのか

うーんどうなんだろ?(^^; -戯

の前に片付け。
まずプリミティブ論争は、"aを使って(無理(?)なく)bを作れるなら、bは非プリミティブだ"と言える(だよね?)ことから、
たとえばprototype oopからclass oopを作れる以上はclassは非プリミティブだ、くらいには言えるかな。
そうやって非プリミティブを疊んでいくことは、なんとなくできるような気が。

あとC++みたいな静的な方向については、完全に別方角の話っすね。
字面的にC++文法を解する言語はなんぼでも作れても、C++の本質(笑)は
自由度じゃなくむしろ静的であるという不自由度に有るでしょうから、
あれを語ってもしょーがないとしか(俺には)思えない。
つまりJavaScriptやSchemeでC++エミュレータを作っても嬉しくもなんともない。

で、こういう(今の俺の)思考ベースだと、本当にまだ違和感が残っているのかどうか?は、実は怪しいです(ぉ

片付けはともかくとして。
やっぱり、状態の塊がプログラムと別の所に存在してるかんじ、ですかね、
oop好きのホームポジションは。

wiliki:Scheme:オブジェクト指向表現 より
>「イマジネーションの刺激」

乱暴にいえば俺はこれを「児戯」だと思っています(^^;。
子供の遊びのレベルの思考をプログラミングに持ちこむという。
それをやっても大丈夫(?)であるという性質が、oopの思想(?)的本質かなーと。

もっと乱暴に言うならば、パズルをパズルじゃなくする効果、というか。

それのために具体的に何をしたかってーと、プログラムの「動く」部分と「動かされる」部分とを、露骨に分けちゃった、と。
両者を同時に考える必要が無くなったから、こんがらがりにくい、と。

で、こういう性質がScheme側にもまた有るのかどうか?は、俺は今のところ知りません、と(^^;

[[id:654]] 2002-06-07 02:30:44


Schemerがオブジェクトを使う時

違和感っすか… (#15)
「状態の塊」というモデルは、Schemerである私も好きです。というか、普段書くSchemeコードでもオブジェクトは使いまくりなんですわ。CLOS風のやつですが。

どういうところでオブジェクトを定義する場合とクロージャで済ます場合とを分けてるかとつらつら内省すると、作られる状態があるロジックでローカルでかつあまり複雑でない場合、なんかはいちいちオブジェクト定義をするのがめんどくさいからクロージャを使う。逆に、状態の塊がグローバルにあっちこっちで参照される場合はクラス定義しちゃう。

ジェネリックなアルゴリズムを書く時に、状態に関係するメソッドが2〜3個以下でかつ将来も増えなさそうな時は(例えば終了判定メソッドend?と次を取って来るメソッドnextとか)、いちいちジェネリックファンクションを使わずに、状態を共有するふたつのクロージャを取るように書く。

オブジェクトを取るように書くと、渡されるオブジェクトがend?とnextというメソッドを持つというプロトコルを守らなければならんわけですが、そういうふうに名前を規定しちゃうのがなんとなく嫌なんですよね。もし他で作られたオブジェクトライブラリを持ってきて、そいつがfinished?とget-nextというメソッドを持っていたとしたら、facadeクラスを作らなくちゃならないわけでしょ。そういう意味では、Schemerの思考は無名指向、なのかも。

もちろん、アルゴリズム中で状態に対して5個も10個もメソッドを適用しなくちゃなくなったら、素直にジェネリックファンクションでやります。

単なるデータ構造の扱いにも、同型の指向が見て取れます。2〜3個の要素を持つデータ構造で、処理の最中にローカルに表れるようなものはリストを使う。要素が多かったりグローバルにやりとりされるものなら構造体にする。

どこでスイッチするかというのはかなり曖昧で、最初は無名クロージャやリストで作りはじてみたけど、だんだん大きくなってきたらクラス定義にスイッチすることも多いです。そういう意味で、Schemerの頭の中でクロージャとオブジェクトがシームレスにつながっているんです。オブジェクト指向の枠組は、便利なライブラリとして使うという感覚です。

状態を見たらまずオブジェクトを考える、という立場とはずいぶん違う作法だと思います。

[[id:655]] 2002-06-07 07:29:28


非「Class指向」者(^^;がオブジェクトを使う時

> Schemerがオブジェクトを使う時 (#16)
>状態を見たらまずオブジェクトを考える、という立場とはずいぶん違う作法だと思います。

うーん、ObjectとClassは違うので、状態を見たらまず「Object」を考えるってのはその通りだけど、
そのとき同時に、「Class」を、つまりその状態を収めるべき器の「かたち」を、考えてしまうか?というと、
そうとは限らないかも。-戯

こっちも、まず、配列だのHashtableだのの、その辺に転がってる(笑)既存の有りモノのCollectionに
放り込んで事足りるんじゃないか?と考えるってのは有りますね。

で、そのCollectionに特異メソッドをつけられる(そういう言語)なら儲け物、というか、
そうでないと嫌だなあというか。

状態の構造自体が結構ややこしいとかだと、そろそろClass作ろうかな、ってとこですかね。
話がややこしくなってきて、そのややこしいことをソレ自体に任せたいときに、
そのややこしさを「象徴」する名前(つまりSymbolですが)を
そのClass(やそれに内蔵されるMethod)の名として、与える…

以上、状態の構造のScope(いや寿命か?)についての、俺の発想でした。
そういう意味では無名指向にもあまり抵抗はありませんね。

>2〜3個の要素を持つデータ構造で、処理の最中にローカルに表れるようなもの
>はリストを使う。要素が多かったりグローバルにやりとりされるものなら構造体にする。

データのScope(いや寿命か?)については、まぁあんまり区別しないですね。
GCが出来るようになった瞬間(^^;から、ObjectをLocalオンリーで使うことに抵抗を
感じる必要(つーか必然:問題は処理効率ダケになるので)性が無くなった、という印象。
まぁC++のScope縛り方式でも同じですが。

>オブジェクト定義をするのがめんどくさいから

その場で作れるprototypeな言語(rubyみたいに、データメンバだけその場で(ちょっと違うけど)、でも可)なら、
面倒な「定義」という行為が介在する、という印象は無いですね。

あ。データじゃなくメソッドのほうの問題でしたか。
うーん。「無名メソッド」かあ。どうしよっかな。OOPだとデータの「中」にメソッドがあるという構造なんで
名を介さず直接指すのは難しいかな。データじゃなくルーチンに対するIteration
(DesignPatternだとVisitorとかいうんでしたっけ??)という形で無名化を可能にする、
ってのは無理があるかな…

あ。待てよ。ヒントはこれかな> DelphiのMethodPointer (Delphi)
Javaでも(俺は)無名クラス大好きですぅ。でも無名メソッドは不可能なのでイライラすることは有ります。
MS J++のDelegates論争ってのが有りましたが、あのとき本家Javaはみすみす、
ちょっとした自由度(上行け度)を喪失しちゃったような気がする俺。

----
考えたら、「非Class指向」じゃなく、非「Class指向」だな。反ClassというほどClassを嫌ってはいないんで。 -戯

[[id:664]] 2002-06-07 17:37:46


dynamic objectなら

非「Class指向」者(^^;がオブジェクトを使う時 (#17)
dynamic objectなら、構造をあらかじめ考えないでも使えるフレキシブルデータコンテナとして使えるという点はそうだと思いまする。

メソッドの方ですが、確かにMethodPointerみたいなことができれば、名前付きメソッドの世界を無名メソッドの世界にマップすることができますね。

クロージャが環境を閉じ込んでいるのに対し、MethodPointerはオブジェクトを閉じ込んでいると。さらにネストしたフレームをインスタンスの継承チェインと対比すれば、クロージャと同じ粒度でオブジェクトをプリミティブとするフレームワークが出来ますね。

うーん、目から鱗。 -Schemer

[[id:665]] 2002-06-07 18:09:29


実は単なる「参照指向」

…だったりはするまいか?(^^;>両者
-戯

[[id:666]] 2002-06-07 18:10:53


これまでの話を読んでいて思ったんですが、

objectがclosureで表現可能かどうかというよりも、
それがfast class objectなのかどうかが重要だと感じました。

schemeの作りを見ると、例えばquoteされたリストを、
「オブジェクト指向としてのオブジェクト」と見る事が
できないのは自明だと思います。

特に(object message)形式を考えると、

('(...) message)
こんなことはできない。(左辺は評価不能)
quoteされたリストは、いわば定数と同義なので、
((make-object '(...)) message)
などとして「オブジェクト指向としてのオブジェクト」へ
マップしなおさないといけない。

その他残された手段は、generic-functionに頼るか、
(message '(...))

これでも通る様に、
('(...) message)
内部eval/applyを修正するほかない。

((make-object '(...)) message)
この、マップするという「段階を踏む」という事実が、
オブジェクト指向派の人が納得していない部分だと思います。
これは左辺に名前が必要なマクロでは解決できませんし。

また、「オブジェクト指向としてのオブジェクト」をclosureで
表現するとなると、procedure?と区別できる様な、object?という
述語は完全に作れません。

結論としては、schemeも「オブジェクト指向としてのオブジェクト」をfast class objectにしてしまう(またはそういう処理系を使う)のが解決策(妥協策?)に見えますが、どうでしょうか。- baba3

----

まあ、Closure === Object では困る場合 (#14) で私が言おうとしたのもそんなことです。
確かにGLSらはActorを実装しようとして「継続渡しにすればクロージャと一緒じゃん」と気づいたわけですが、当時はまだすべてをオブジェクト(メッセージを受け取る主体)とするところまではいかなかった、というところでしょうか。

Arcではリストやベクタもapply可能になっていますね。 -Schemer

[[id:674]] 2002-06-10 13:56:56


それって語順の問題だけではないのでしょうか?

> これまでの話を読んでいて思ったんですが、 (#20)
> ('(...) message)
> こんなことはできない。(左辺は評価不能)

MethodのReceiverが語順的に最初になる、というのは
文法の問題でしかないような気もします。

マイナーですが主語つーかReceiverが頭に来ない言語も有りますし、
有っても「別に悪くない」と思います。

messageが、引数をObjectだと見なして「から」Method本来の処理をする、というように
数珠繋ぎな関数になっていれば、事足りたりしませんか?

そして、そういう数珠繋ぎ関数を作るという毎度毎度の手間は、
マクロとやらを使うとかなり自動化出来たりするものであったりは、しますか?

#的外れだったらご免なさい。暇があったらScheme覚えて確認したいんですが… -戯

[[id:675]] 2002-06-10 12:43:06


>21

数珠繋ぎというのがよくわかりませんが、
generic-functionの様なディスパッチのことを言ってるんであれば、
マクロにする必要はないと思います。
マクロを使うべきところはgeneric-functionを定義する段階などで、
適当な構文に当てはめたいという様な場合でしょう。

;トップレベル環境のシンボル'printを、generic-functionとして使用宣言する
(generic-function print)

この場合、トップレベル環境のシンボル'generic-functionに
バインドされた値がマクロ本体となります。

マクロは普通、静的にしか作用しません。
ある決まった処理を1文で表すときに、closure関数では不都合が出る場合に使います。(define ==> define-classの拡張など)
これはC言語のそれと変わりありません。ただし、マクロ展開式を
そのままLISP関数群で記述できることがCとの大きな違いです。-baba3

[[id:680]] 2002-06-11 00:42:52


新ページ

プログラミング言語:高階関数
[[プログラミング言語:Lisp:マクロ]]

[[id:684]] 2002-06-11 13:02:58


例えばオブジェクトを「シンボルを引数に取る関数」ととらえて見ると

スロット(メソッド及びメンバ変数)へのアクセスはシンボルに対する関数適用
とみなすことができる。

SMLっぽい架空言語での例:

Human :new
==> #<Function: String -> Integer -> Function>
// 関数 Human をシンボル new に適用すると、カリー化された関数を返す。

Human :new "Smith"
==> #<Function: Integer -> Function>

val aHuman = Human :new "Smith" 25
==> #<Function: Symbol -> 'a>
// オブジェクトはシンボルを引数にとり任意の型の値を返す関数

aHuman :name
==> "Smith"
// 文字列を返す

aHuman :age
==> 25
// 整数を返す

aHuman :greeting
==> #<Function: String -> String>
// 関数を返す(=メソッド)

aHuman :greeting "Hello"
==> "Hello, I am Smith.\n"
// メソッドの実行(1)

aHuman :greeting "Good morning"
==> "Good morning, I am Smith.\n"
// メソッドの実行(2)

…こんな文法なら「語順が不自然問題」も「ディスパッチがうざったい問題」も解決!

[[id:913]] 2002-08-02 02:56:29


色々試しましたが、結局schemeの場合はシングルメソッドなら

お手軽に定義できて表記的にも一番無難な、

(object 'mesage)
((make-object 定数) 'mesage)

で十分な気がします。
(object?の述語のunique視問題は残りますけどね。)

-バリエーション
1)高階呼び出し
((object 'mesage) args)

2)dispatchをあらかじめ済ませてから呼び出し
(define object.mesage(object 'mesage))
(object.mesage)

3)直呼び
(object 'mesage args)

マルチメソッドがどうしても必要な局面ってあんまりなさそうだし。
定義する手間を考えると、generic-functionは大袈裟な気がします。
この方式でもメソッドの返す値を高階にするのか、
直呼びかで別れるとは思いますが。 -baba3

[[id:1168]] 2002-09-11 17:53:46


top recent

HashedWiki version 3 beta
SHIMADA Keiki