すひです。

先週のセミナー@秋葉原で、公式ページの

    o 他の言語との比較

を書き直そうかと思っている、という話が出ました。
関連すると思われる ruby-talk の記事を訳して流します。
(Reference: が変かも…)

ご笑覧の上、訳し間違いや勘違いあれば、指摘ください。
特に、まつもとさんの文の意図が汲めていますかどうか…(^_^;)

\cle さんへの連絡をとってませんが、そこそこ文が固まって
公式 Web にでも載せられる水準になったところであらためて、
と思っています。

======================================================================
[ruby-talk] Pythonとの比較  {あらたに訳者の書いたことはこの括弧で囲む}
======================================================================
Subject: [ruby-talk:00895] Re: Contrast Ruby and Other Languages
>From: Clemens Hintze <clemens.hintze / alcatel.de>
Date: Mon, 1 Nov 1999 14:17:10 +0100 (MET)
In-reply-to: [ruby-talk:00893]

ども。

リクエストにお答えして、(Pythonとの)比較の文を読み返してみました。
「間違っている」というわけではなかったですが(1件例外はあります)、
そうはいっても、もっとうまく書けるような気はします。

以下が私からのコメントです。
 {和訳では公式ページを引用していますが : の項目は無かったので追加しました}

| オブジェクト指向言語としてRubyと対象領域がオーバーラップする Pythonを
| Rubyと比較すると: 

|  OOPが不徹底 

これが、いま言った唯一の間違い(と思うもの)です。
というわけでこの意見に賛成しようとは思いません。
Python の OOP は徹底しています。いるんですが…
続きはこの後で。

:   情報が隠蔽されない

ここでの(OOP としてちゃんとした?)情報隠蔽=カプセル化というのは、
それを掛けたときに、外界からそのデータに一切アクセスできないようなもの。
そう言いたいんでしょうか?
そうだとしましょう。それなら言いたい。
こんなものは OOP の特徴なんかじゃないっっ!!
ホントのこと言えば、Ruby だってそんなこと出来ちゃいないですよ。
誰にでも、(プログラムを)動かしてる真っ最中にだって、
インスタンス変数にもアクセスできるように、ってメソッドを導入するために、
深くも考えずにクラスやオブジェクトの拡張ができるわけです。

|   いくつかのデータ(数値,リスト,辞書,文字列など)は真のオブジェクトではない 

これもまた、OOPの特徴をあらわすものではないです。
これをもって、Python の OOP のことを、OOP として不完全とは言えません。
言えるのは、Python が、「言語(OOL)として」不完全だ、ってとこまででしょ(^_-)

|   拡張モジュールでCで記述されたデータも真のオブジェクトではない 

これもそう、私見では OOP 不完全の印ではありません!
玉に瑕、といったら(Pythonの)誉めすぎでしょうか。
Smalltalk でもおんなじように、C でクラスを書きたくても書けない
バージョンがあったことを覚えています。(Smalltalk V (DOS) だったっけか -_-;)
まぁ Smalltalk に限った話ですけど。そうは言っても Smalltalk は
今日に至るまで *complete* OOP であったのではないかと思いますが(^_^;)

|   インスタンス変数のアクセスの際にいちいちself.をつけるのが面倒 

お目汚しですが、悪魔な弁護をします。
こういう比較には、もっと注意を払うべきではないでしょうか?
確かな土台にふんばることを止めたなら、待つのはただ沈没です。

くどいですが、いちいち self. がついているから
不完全{typo無視}な OOP だ、とはいえないのです。
結局、Python の OOP にボロ(だという証拠)は出てこなかったわけです。
ですから以上の指摘はまとめて捨て捨てしましょう。
残すのなら、Ruby の OOP と Python の OOP との違いと、
互いの利点とだけ、とするならよいでしょう。

|  関数がfirst class object(もちろん欠点ではない) 

ときどき、Ruby もこうだったらなぁ、と強く思うことがあります。
でもまぁ、それがなくても、生きてはゆけます。

|  del, lenなどがオブジェクト指向ではない(__len__とかあるけど…) 
|  スーパークラスのメソッドの呼出がかっこ悪い 
|  クラスメソッドがない(モジュールの関数で代用できるけど) 
|  long integerとsmall integerの相互変換がない 

言い方を直すほうが良いのでは?
たとえばこう: 
Python のユーザは、Python の内部表現に逆らえない。
整数で扱っているものの値があまりに大きくなったときは、
どうしても、ユーザーがそれを多倍長整数へと直さなくてはいけない。

|  真のGCがないので 
|        メモリリークが起きやすい 
|        拡張モジュールの記述がちょっと面倒(INCREF,DECREF)
:        (1.5になって少しはマシになったかな?)

大事な大事なポイントです!!

|  tuppleとlistが機能的に重複する(もちろん考え方の違い) 
|  関数オブジェクトを引数にするより,イテレータの方がきれい 

ここは異論があるでしょう(わたしは賛成^_^)。
「イテレータ」のからみで言っている内容の釈明が必要でしょう。
この用語ですが、そんなに好きではないです。
わたしにとってイテレータっていうのは、
ものの集まりの中にある要素すべてを遍歴して、
それら(と|に)何事かをするようなメソッドです。
(ここで、何事かするっていうと、ほかのメソッドを呼ぶ、ということになるのか?)

ほかの仕方で定義をくだすとすれば、イテレータとは、
C++風に言うところの、
    あるひとまとまりになったものの内部に格納されている要素を
    次から次へと配達するオブジェクト
です。

だから、そういう意味では、
Array#collect だって Array#find だってイテレータなわけです。
その一方で、File#open なんかはイテレータではないけれども、
何事かをなすために、ブロックを受け取ることができます。

それはさておき、「イテレータ」って言葉が好かないわけは他にもあるんです。
言い換えて、'has_block?' のように言えるのなら、まだうなずけます。

|  結局宣言がある(global) 
|  Rubyより遅い(改善されたかな?) 

ここは特にありません。

言いたいことは要するに、RubyのどこがPythonより優れているのか、それを
説明する方が、Pythonの弱点を論うよりマシではないか、ということです。
(心理的に、です。私の欠点はドコソコ、なんて言わないで、あなたの
どこが私より優れている、と言って欲しいように^^;;)


ちょっと私案を書いてみます。(例によってくどくど調ですが…^_^;)

Python は Ruby と対象領域がオーバーラップしています。
Ruby ユーザーから言わせてもらえれば、ただ単に違っているだけの点もありつつ、
Python より遥かに優れている点も、Ruby にはある。そう言いたい。
以下の弁、とくと御覧じろ: 

o Ruby は、徹底的に OOL です。
  Ruby の世界では、そこにある全てがオブジェクトです。
  この意味では、Python や Perl の OO は徹底してはいません。
  むしろその徹底さは Smalltalk のそれです。
  例を挙げれば、数字の 1 は、Fixnum クラスのインスタンスです。

o Ruby の OO は、徹底的であるとともに、
  あとから改良を施すこともできるように、注意深く設計されています。
  たとえば、Ruby は、(プログラムを)動かしてる真っ最中においても、
  クラスや、オブジェクトにさえも、メソッドを追加することができます。
  どういうことかというと、もし必要があれば、
  あるクラスのインスタンスが、同じクラスの別のインスタンスと別の
  振る舞いをしても構わない、ということです。

o Ruby の継承は、訳あって、単純継承だけです。
  ただし、Ruby は「モジュール」の概念をわきまえています。
  (Objective-C でいうカテゴリ。)
  モジュールとは、ひとまとまりになったメソッドです。
  すべてのクラスは、モジュールをひとつインポートすることができて{typo無視}、
  クラスの中のメソッドを、そのモジュールの自由にさせられるようになります。
  この方が多重継承よりずっと分かりやすい、という考えもあります。
  多重継承は複雑で、単純継承ほど頻繁には使われないですね。
  (厳しい型チェックのせいで多重継承するしか選択肢がない某
   C++は別ですよ。考慮の外。)

o Ruby には真の手続きオブジェクトがあります。
  (これは Python の lambda よりずっと扱い甲斐があります。)

o Ruby のメソッドは、クラスと分離することができないので、
  ほかのクラスに手渡すことができません。
  パフォーマンスから来る理由で、どこのクラスにコンパイルされたかによって
  メソッドのコンパイル表現は、そのクラスにとても大きく束縛されます。
  しかし手続きオブジェクトを使えば、結果的に同じことができます。

o Ruby ではブロック{いわゆるイテレータ・ブロック}が使えます。
   (次のどちらかで囲まれたコード:(1) { 〜 } (2) do 〜 end )
  ブロックは、メソッドに渡したり、それをもとにした手続きオブジェクトに
  変換したりすることができます。

o C による拡張は、Ruby に対して
  メソッドまたはクラス(ときに双方)を定義します。
  さらに C で書かれたクラスを Ruby で書かれたクラスの親にすることもできます。
  (Python では型・クラスの衝突がありますが、Ruby ではその心配は無用。)

o Ruby には、真のごみ集め機構があります。
  あらゆる Ruby のオブジェクトと共に使えます。
  INCREF も DECREF も、ひとつも使わなくて構いません。
  あぁなんて健康増進によろしいんでしょう(^-^)

o C による拡張ライブラリを Ruby で書くのは、
  Python で同じことをするのより簡単です。
  それはごみ集めがあるせいもあり、精妙な API 拡張のためもありましょう。

o Ruby では、整数を使うのに、内部表現がどうなっているのかを
  気にしなくてよいし、気にしてはいけない、とさえ言えます。
  小さな整数(クラス Fixnum のインスタンス)も、大きな整数(Bignum)も、
  存在はしていますが、どちらかが使われる、という話になっているので
  気をもむ必要はありません。
  じゅうぶん値が小さければ Fixnum になるし、そうじゃなければ Bignum に
  自動で移り変わります。ただ何も考えず{整数として}使っているだけで OK!

o Ruby には、一切、宣言というものがありません。
  ただ、変数への名前のつけかたには決まりがあって、
  変数の有効範囲がどこまでかによって名乗り分けます。
    (例) @var  はインスタンス変数
         $var  はグローバル変数
          var  は単なる局所変数
  したがって、インスタンスのメンバー全部の先頭に、いちいち
  self. をつける必要がありません。

o Python のクラスをどれでも、ほぼシームレスに Ruby で使えます。
  そういうからくりの C 拡張ライブラリがあるんです(^-^)


何点か言わなくちゃいけないこと(絶対あるはず)を忘れちゃったんですが、
これだけくどくど書いたので、なにかしらお役に立てることが言えたんじゃ
ないかと思ってます (*^_^*)

\cle

======================================================================
Subject: [ruby-talk:00900] Re: Contrast Ruby and Other Languages
>From: matz / netlab.co.jp (Yukihiro Matsumoto)
Date: Tue, 02 Nov 1999 16:39:11 +0900

まつもと ゆきひろです
どうも。

In message "[ruby-talk:00895] Re: Contrast Ruby and Other Languages"
    on 99/11/01, Clemens Hintze <clemens.hintze / alcatel.de> writes:

|> - incomplete OOP 
|
| これが、さっき言った唯一の間違い(と思うもの)です。
| というわけでこの意見に賛成しようとは思いません。
| Python の OOP は徹底しています。いるんですが…

「不便な OOPL」だったらどうですかね?

| だから、そういう意味では、
| Array#collect だって Array#find だってイテレータなわけです。
| その一方で、File#open なんかはイテレータではないけれども、
| 何事かをなすために、ブロックを受け取ることができます。

この感覚は分かります。どうもイテレータという用語は濫用されがちですね(^_^;)

| それはさておき、「イテレータ」って言葉が好かないわけは他にもあるんです。
| 言い換えて、'has_block?' のように言えるのなら、まだうなずけます。

日本語のメイリングリストでは言ったことがある([ruby-list:13757])んですが、
気に入った名前がありさえすれば、別の名前をつけてもいいですよ。
(気に入らなかったらそれまでですけど。)
こんなのはどうでしょう?

  block_given?
  with_block?
  has_block?
  have_block?

Ruby のライブラリでは使う英単語は「活用していない形」としているんで、
`has_block?' とするよりは `have_block?' がいいですね。

どう思います? どれが一番いいですかね? それとももっといい案があります?

|Here is my trial (beeing too verbose as I ever am ... ;-):

うーん、これは… いいんです… いいんですけど‥

元々、単に先達への敬意を表してリストに入れただけの積もりだったんです。
他の言語に対して Ruby はこう、と PR するページを、と思っていました。
とりあえずは、こんな感じで付け加えてみます:

  * クラス・インスタンスでないオブジェクトがある
    Type/class 混合のせいでオブジェクトを uniform に扱えない
    C の拡張ライブラリがクラス・インスタンスを生成できない
  * C で定義したクラスを継承できない
  * クラスの大部分をスクリプトで定義し、残りを C で定義するのはつらい
  * 真の手続きオブジェクトがない (lambda をつかえば無名関数は作れるけれど)

いただいた文章はいくつか `What's Ruby' のページに使わせて頂きます。

                                                        matz.

======================================================================
Subject: [ruby-talk:00901] Re: Contrast Ruby and Other Languages
>From: Clemens Hintze <clemens.hintze / alcatel.de>
Date: Tue, 2 Nov 1999 10:41:01 +0100 (MET)

まつもとさんは書きました:

> どうも。
> 
> In message "[ruby-talk:00895] Re: Contrast Ruby and Other Languages"
>     on 99/11/01, Clemens Hintze <clemens.hintze / alcatel.de> writes:
> 

[...]

> 
> 「不便な OOPL」だったらどうですかね?

うー、むー、ぬぬぬ。難問だ、難問ですよこれは…

Python OOP は、本質的に便利じゃありません。
Perl のやつならもう、そう口に出して言っちゃえます。
でも Python の方は、自分にとってつらいのはたったの2点なんですよ…
うざったい'self.'と、親クラスのメソッド呼び出しが美しくないことです。
あとのところは、Perl ほかモロモロの敵じゃないですね。

それじゃどうする、って言われても… どう言ったもんだか (=_=)

[...]

> この感覚は分かります。どうもイテレータという用語は濫用されがちですね(^_^;)

よかった(^ー^)
いま Python 信者と議論しているんですが、その方は、
Perl はげろげろで、Ruby は気にしていて、
文法のよく似た点については認めてくれるものの、
そーゆー理由で Ruby を放り投げてしまうんです。

Ruby の世界での「イテレータ」と、その他の世界での「イテレータ」の
違いを、その方にカンタンに説得することはできませんでした。

[...]

>   block_given?
>   with_block?
>   has_block?
>   have_block?
> 

[...]

> どう思います? どれが一番いいですかね? それとももっといい案があります?

have_block? が一番いいですね。でも意味からすると、
with_block? が一番はっきり伝えられているように思います。
私見ですが…
メソッドはブロックを持たないが、ブロックと一緒に呼ばれる… (-_-)
そういう意味では、block_given? と呼ぶ方がふさわしいような…
あー、決めがたい。

コードで見てみることにしましょうか:

    def greet(whom)
       if have_block?
          yield
       else
          print "Hello "
       end
       print whom
    end

    def greet(whom)
       if with_block?
          yield
       else
          print "Hello "
       end
       print whom
    end

    def greet(whom)
       if block_given?
          yield
       else
          print "Hello "
       end
       print whom
    end

うん、よし。'block_given?' の勝ち。
(好きではないけど、自分にとっては意味が一番はっきりしています。)

[...]

> 元々、単に先達への敬意を表してリストに入れただけの積もりだったんです。
> 他の言語に対して Ruby はこう、と PR するページを、と思っていました。
> とりあえずは、こんな感じで付け加えてみます:
> 
>   * クラス・インスタンスでないオブジェクトがある
>     Type/class 混合のせいでオブジェクトを uniform に扱えない
>     C の拡張ライブラリがクラス・インスタンスを生成できない
>   * C で定義したクラスを継承できない
>   * クラスの大部分をスクリプトで定義し、残りを C で定義するのはつらい

これは本当ですか?
確か、ExtensionClass とか、そういう名前の拡張があります。
確かにできるかどうか、簡単かどうか、はっきり分からないあたりは、
おっしゃることももっともだと思いますが。
この拡張で、Python のクラスと連結した拡張ができるようになるように思います。

でも使ったことないから自信ないです。ちょっと待って…

Python の Web ページを見てみました。それで良かった!
引用を示します。

___以下引用___
Extension Classes ― Python を、もっとクラスっぽく拡張するための仕組み。
                   (Jim Fulton, Digital Creations)

 この仕組みを使えば、拡張機構を書くのに、C や C++ が使えます。
 そして書いたオブジェクトは、Python のほかのクラスの扱いと同等になります。

      o それらは Python のサブクラスになり得ます。
      o Method documentation string {訳語わかりません…} への
        アクセスができます。
      o さらに、新たなインスタンスを直接つくるのに使うこともできます。

   拡張クラスは、拡張されたメソッド結合プロトコルをサポートします。
   これは、メソッドの型と、それをcallする記号をサポートするためです。
___引用おわり___{typo無視}

つまり、言えるのは、上に挙げた諸点は、
  Python のインタプリタの核の部分では間違っていない
ということです。そして、Ruby におけるほど簡単なものではないこと。
これは確か (^^)

[...]

> 
> いただいた文章はいくつか `What's Ruby' のページに使わせて頂きます。

ぐはぁ(吐血) 綴りとかは大丈夫ですか??

チェックまだなら、直したいところがあるんですが… {原文参照時に注意のこと}

... to add methods to a class, or even an instance during runtime. 
                                      ^ to

... class can import an module and so becomes all it methods for ...
                                 gets ^^^^^^^     ^^ its

Ruby features block in its syntax ...
              ^^^^^ blocks

... to care about maintaining reference count in extension libraries. 
      ^ take                            ^^^^^ counts

ついでに、こういうのも取り入れてもらえますか?

o Ruby のスレッド機構は OS に依存していません。どういうことかというと、
  Ruby ならたいていのプラットフォームでスレッド機構を、
  その OS がサポートしているかどうかに拘わらず、使うことができると
  いうことです。マルチスレッドだってできます。(MS-DOS でも動きます^_^;)

> 
>                                                         matz.

\cle

======================================================================
以上。
-- 
SUGIHARA Hiroshi
maili31s / clio.ne.jp