あおきです。
反応遅くなってすみません。

  In mail "[ruby-dev:8833] Re: [REQ] Array#each{|a,b,...|},
 Array#shift/pop(num)"
    Kazunori NISHI <kazunori / swlab.csce.kyushu-u.ac.jp> wrote:

> 西@九大です。

> > 欲しいものだけ(extract)を実装するだけではなぜだめなのか、ということです。
(略)
> 全機能を実装する理由はありませんが、同じくらい、現在の要求がある機能だ
> けを実装した方がよい、という理由も見あたりません。で、恐らく問題の本質
> である、それは本当にいい機能か?(extract+αの機能を持たせるべきか?)に
> なる訳ですね。

そうですね。
(本質、二段落下に続く…)


> 盲信というか、ライバル心と言えるかもしれません。Ruby(Array)になくて 
> Perl(splice)にある機能が存在するのも悔しいので、条件反射的に splice の
> 全機能を求めてしまった感があります。軽率でした。

そういうものなんですか…。
ぼくはむしろ「XXX にあるから」というような理由がつけられると
意地でも阻止したくなります  (^^)
(今回も「Perlにあるから」というところに最初にムカッときて
 それから反論を考えたというのが実態だったりして。)


(ざくっと略)
> > extract してさらに []= するとき(つまり、splice 本来の目的として)
> > ですよね。そんな機会がそう頻繁にあるんでしょうか?(いやない。)
> 
> あーん、ここまで折角、もの凄く論理的なよい文章だったのに、何でこの大事
> な部分を反語調で片付けようとするのですか!?(泣)。

むむ、それではもう少し説得力をもたせるために統計をとってみました。

/usr/lib/perl5/ で find + grep splice してみると、31個の splice が
みつかりましたが、そのうち代入を用いているのは一回だけ。
返り値を使用しているのは二回。代入と返り値が同時に使用されることは
一回もありませんでした。
(ちなみにぼくの環境では大部分が IM で使われていました。)
つまり、splice は範囲のある削除の用途で使われることがほとんどであり、
Ruby では範囲のある delete_at と slice! が採用されれば splice は
全く不要であると言ってよいでしょう。
(同時に、範囲のある削除を導入する必要性も指摘できる。)

おまけに、Pod/Functions.pm には

  splice  ARRAY   add or remove elements anywhere in array
                     ^^^^
という記述を発見。これは Perl を使ってる人自身の意識を如実に
反映しているのでは?

ということで納得していただけましたでしょうか。

---
以下余談

今回の問題を通して「メソッドの仕様が適切である」とはどういう
ことか、基準はなんなのか改めて考えなおしてみたのですが、結局
「オブジェクト指向入門」に示されている基準がかなりよいのでは
ないかと思いはじめました。それは、

「メソッドはファンクションかプロシージャである」
「プロシージャはオブジェクトの状態を変化させる」
「ファンクションはオブジェクトの状態を変化させずに値を返す」

…ということです。
この基準がいいと思うのは単にオブジェクト指向入門に書いてあったから
ではなく、実際 Ruby のライブラリにあてはめて考えてみるとなかなか
うまくいくからです。
ただ、この基準にてらしてみると、slice! のような機能はファンクション
ですから同時に要素を削除していて(=状態を変化させる)、よくないことになります。
IO#read なども同様によくないメソッドになります。
逆に、delete_at はプロシージャ的メソッドですから、返り値を期待するのは
よくないことになります。

しかし、実際にこのような Ruby の仕様は使いやすく、自然と感じられます
(ですよね?)。この矛盾をどう埋めるのがよいかと考えたところ、
「名前がルール違反をすることを明確に示していればよい」のではないかと
いう結論にたどりつきました。
つまり、基本的にはメソッドはプロシージャかファンクションで、それぞれの
役割を正確にはたさなければいけないのだけれど、名前からあきらかである
ときには、ファンクションがオブジェクトの状態を変化させてもよい
(「!」でおわるメソッドが代表的)、プロシージャ的メソッドに特定の
返り値を期待してもよい(read など)、ということではないか。
また、そういうメソッドは自然に感じられるのではないか。ということです。

まとめると、(ぼくが考える) Ruby において自然/適当なメソッドとは
以下をみたすメソッドということになります。

1  メソッドはファンクションかプロシージャである。
2  ファンクションはオブジェクトの状態を変化させずに返り値を返す。
   ただし名前がそれを明示するときは変化させてもよい。
3  プロシージャはオブジェクトの状態を変化させる。
   ただし名前かそれを明示するときは特定の返り値が期待できる。

という前ふりをおいてあらためて splice について考えてみると
(しつこい)、名前から想定されるのはプロシージャ的機能であり、
特定の返り値を期待すべきではない。名前がそれを明示していれば
返り値を期待できるが、splice はそうではない。歴史的理由によっても
暗示されない。よって splice は適切なメソッドでないと結論します。


> > そう頻繁に使われるとも思えないメソッドふたつのくみあわせを
> > ひとつにするために標準の機能としてsplice メソッドを用意する
> > 必要はないと思います。
> 
> 問題なのは、任意の2つのメソッドの組み合せでなく、少しは使われる可能性
> のある一連の2つのメソッドである、という事。そして、他言語に存在する以
> 上、全くの無意味なメソッドだとは思い難い、というのが私の意見です。(あ
> るかな?と思ってあった時や、ここにはコレがまさにピッタリ!と感じた時に
> 落ちる鱗もあるんです)。
>
> 後は、「無意味でない、でも頻繁に使われる事もない」というメソッドを標準
> で実装するかどうか、という問題です。これは、まつもとさんが決定される事
> で、これまで、そういうものはあまり実装されてないので、やや不利な気はし
> ています。(いいけど)

Ruby ではユーザが勝手に既存クラスにメソッドを追加できるので、
組みこみライブラリにいれるハードルは高くてもいいと思います。
結局はそこのバランスに戻るんですが…


> (Array#extract があれば)。ていうか、"Array#[start,length]=" 等が削除さ
> れた値を返すようにすれば、それはもう splice なのではないでしょうか!?

細かいですがこれにも反対。
[]= は相当使うのでそのたびに配列が生成されるのはさすがに厳しいものが
あります。また前述の基準にてらしても []= (プロシージャ)が変な
返り値を返すのは適当でないと考えます。


> 別メールですが、あおきさんの
> 
> From: Minero Aoki <aamine / dp.u-netsurf.ne.jp>
> > それで提案なんですが、delete_at( i, len ) を self かなにかを返すように
> 
> ここで self を返すというのは、"array.delete_at( i, len )[i,len] = val"
> としたい、という cascading 願望の表れではないでしょうか?(多分、違う)。
> ほら、やっぱりみんな、欲しいんじゃん!(強引な結論)。

nil よりはいいかなと思ったのが理由です。

ところで、array.delete_at( i, len )[ i, len ] = val じゃ
望むものにならないと思うんですけど…
(ほら、無理にまとめるからやっぱり間違えるじゃん!(強引な結論。))


> > ようするに、pop( 3 ) の 3 というのがどういう意味の 3 なのか、
> > 何が返ってくるのか、想像がつきにくいんです。それはなぜかというと
> 
> はい、おっしゃる通りです。
> という事で、Array#pop/shift(n) は取り下げます。

それではこっちは終端ということで。


> #個人的に gets で $_ に代入する必要性を感じないが「互換性」の前に黙認

ぼくは「そんなものは Ruby にはないんだ!」と信じることで
心の平静を保っています。 ^^;;
実際 $_ なんて使ったこともないし。
-------------------------------------------------------------------
あおきみねろう