けいじゅ@いしつかです.

In [ruby-dev :35863 ] the message: "[ruby-dev:35863] Refactoring of
enumerating prime numbers ", on Aug/16 14:11(JST) "Yugui (Yuki
Sonoda)" writes:

>Yuguiです。

>mathn.rbに収録されているPrimeクラスの使い勝手がいまいち良くないので改善
>を提案します。直したいのは3点です。
>
>1. mathn.rbに入っている
>2. インスタンスを生成する必要がある
>3. そもそも独自のクラスが必要か?

インターフェースの側面, 機能の側面, 実現の側面から見てみたいと思います.


まず, インターフェース上の側面から.

>== mathn.rbに入っている
>素数列挙は整数に閉じた計算でも必要になるものなので、mathn.rbがもたらす
>  int / int => rational
>は嬉しくないことがあります。

分からないことはないです.

ただ, そもそも, Prime は 元々, 素因数分解のために mathn.rb に入ってい
るもので, mathn.rb に同梱されているからこそ標準添付になれたもので, そ
れ単独で標準添付になれたかどうか? たぶん, なれなかったでしょう.

>ですから、素数を列挙する機能はmathn.rbに含まれているべきではありません。
>添付のパッチでは仮にlib/math/prime.rbというファイルに追い出してみまし
>た。

そのあたりが, lib/prime.rb でなく lib/math/prime.rb という遠慮になって
いるような気がします.

いまさら, 分けたら標準添付からはずせともいわれないと思いますので, 場所
(ファイル名)はともかく分けてもよいと思います.


>== インスタンスを生成する
>素数列挙機能は現在は次のようにして使う必要があります。
> Prime.new.each do |prime|
>   # do something
> end
>要するに、Primeオブジェクトは素数列挙に対する外部イテレータです。
>これは少し奇妙に思えます。

全然奇妙でもないと思いますが? 概念的には, Primeインスタンスが素数の集
合を表していると考えているからです. その素数集合から数え上げていると考
えているのでこのようなインターフェースになっています.

>次のように書きたいです。
> Prime.each do |prime|
>   # do something
> end

それは, インターフェース上の問題で, 利便性からそいうものがあってもよい
気がしますが.

for prime in Prime
  # ...
end

って書くとおかしい気がするので, あくまでもそのようなインターフェイスも
用意するのがよいと思います.


>== そもそも独自のクラスが必要か
>こうなると、Primeという独自のクラスが必要かどうかが疑問になってきます。
> Integer.each_prime do |prime|
>   # do something
> end
>
>でよいのではないでしょうか。Primeという別個のクラスが用意されていたのは
>外部イテレータを提供するためにインスタンスを生成する必要があったのだと思
>われます。Enumeratorが組み込みになった今、素数列挙機能はIntegerクラスに
>付加するのが自然だと思います。

> Integer.each_prime do |prime|

がインターフェイス上欲しいってのを否定するつもりはないです. 積極的に肯
定する来もないですが.

次に, 機能的側面から.

Enumeratorと外部イテレータとしてのPrimeインスタンスですが, Enumerator
はスレッドの境界を越えられないという制約がありますので, そのような制約
のないPrimeからわざわざダウグレードする必要はないです.

次に, 実装的側面から, Yuguiさんの実装はでは, Integerのクラス変数として

  @@primes
  @@next_to_check
  @@ulticheck_index
  @@ulticheck_next_squared

とうが, 導入されていますが, これはとても許せないですね. Integerのクラ
ス変数としてはふさわしくないと思います.

> 今はEnumerable::Enumeratorがあるのですから、外部イテレータ生成のためだけ
> に奇妙な振る舞いをさせる必要はありません。また、Rubyライブラリとしては内
> 部イテレータをまず提供するのがより自然ではないでしょうか。

とありますが,

現行のPrimeから内部イテレータを実現する方法とYuguiさんの内部イテレータ
からEnumertorを利用する方法とどちらが自然かといえば, 外部イテレータを
実現するためにFiberを用いている方がよっぽど不自然だと思います. 牛刀っ
て感じがします. さらに, 上記で述べたように機能的に劣るものに置き換える
理由はないと考えます.

私の結論としては:

* mathn.rb から 分離独立させる => 賛成
* Prime.each の導入 => 賛成

* Integer.each_prime の導入 => 必要性はあまり感じない

* 実装に関して => 現状のままでよい.

です.


__
---------------------------------------------------->> 石塚 圭樹 <<---
---------------------------------->> e-mail: keiju / ishitsuka.com <<---