坂野 正明です。 # 拙論では入門者(特にプログラミング言語全般の)にとって、 # int/int => rational が優しい(←易しいではない)、となって # います。実際に入門者の方々の意見が伺えたら言うことないのですが…。 At Fri, 2 Apr 2004 07:43:01 +0900, matz / ruby-lang.org wrote: > ただ単に「自然」というのではなく、こうだから嬉しい、という論 > 法になりませんでしょうか。 > > 今まで聞いたのだと(comp.lang.pythonで聞いたのですが)、「/」 > を整除にしないと(Pythonの場合はfloatですが)、整数と実数が完 > 全に可換になってPolymorphicにできる、というものが比較的説得 > 力を感じました。まだ弱いけど。 Googleで調べてみると、↓の辺りの話みたいですね。 http://www.aful.org/wws/arc/python/2001-07/msg00100.html さて、まつもとさんの suggestion (ありがとうございます!)に従った 筋で、思うところをまとめます (長文御容赦!)。 int/int => rational となることで… ◎ありがたくないこと。 互換性が失われます。 「/」は基本的演算子なので、その影響は小さくなさそうです。 ただし、 ・Array の添字は整数である必要はない (参考 [ruby-list:39470]) ・ループカウンタも問題になることはそう多くなさそう 例) i=0; while(i<=5/2){ (i+=1 など; i は整数) ...} は、5/3 が整除でも「÷」でも挙動は同じです。 なので、影響は実は限定されるように想像します。 # もちろん、プログラミングスタイル次第では、影響は大きいことは # あり得ましょう。 拡張ライブラリ作者にとっては、拡張ライブラリ用言語と「/」の挙動が 一致しなくなる(可能性が高い)。 # もっとも、今でも、C言語で拡張ライブラリを書くなら、「/」の挙動 # は一致しないんですけど…。 ◎ありがたいこと。 ○整除の表記に紛れがなくなる 「/」には、(言語ごとに)色々なスタイルがあり、かつ、Ruby の中でも 変更可能です。だから、たとえば誰かのプログラムで 「3/2」 とあって、それが 1 を意味するかどうかは、これだけでは、それほど 自明ではないでしょう。一方、上が default で rational を返せば、 結果に整数を欲しければ、 「(3/2).floor」 または目的に応じて 「(3/2).truncate」 と書くことになります (.div を使うもよし)。これは、見た目に 一目瞭然で紛れがありません。 # 整除の方式(Ruby/Python or C/Fortran)も一目瞭然です。 後ろに計算を続けても、誤解の余地はありません。 例: 「(3/2).floor * 2 => 2」 ○その逆は不可能。。 言うまでもなく、逆は不可能です。つまり、現在の Ruby の標準仕様では、 「3/2」 と一旦書くと、rational や float の 2分の3(=1.5)を生成できません。 後ろに計算を続けると、誤解の余地が拡大します。 例: 「3/2 * 2 => 2 (3??)」 (@現Ruby) これを避けるには、3.quo(2) などとするしかありません。 ○C言語的整除の表記に紛れがなくなる もうひとつ、嬉しいことに、「/」でrationalが返れば、例えば、C言語 の仕様での「整除」を実行することが簡単かつ、見た目に紛れがありません。 例: 「(-3/2).truncate * 2 => -2」 一方、現在の仕様では、これは(一般的に実行するのは)面倒でしょう。 例: (一般的に)無理に一行で書くなら、こんな感じ? ((-3/2)+Rational((-3/2)/(-3/2).abs,2)*(-1)+Rational(1,2)).to_i または (-3/2)+(((-3/2) >= 0) ? 0 : 1) もしくは、「/」を一切使わない。 ((-3).quo(2)).truncate ○負号としての「-」と演算子としての「-」とが、「/」において同意になる またもうひとつ、嬉しいことに、「/」でrationalが返れば、負合としての 「-」と演算子としての「-」との意味が、「/」演算において結果的に同じ になって、優先順位などの紛れが無くなります。 例: 「( -3/2 ) == ( - 3/2 ) => Rational(-3,2)」 # 今の Ruby は、「-3/2」も「- 3/2」も「(-3)/2」と解釈されています。 # ですから、上の "==" は、今の Ruby でも成り立っています。 # が、これは万人にとって自明の仕様とは言い難く、「- 3/2」が # 「-(3/2)」と解釈されると思い込む間違いがしばしば起こりそう。 # 特に、(literalの)「3」でなく、「a」のようなオブジェクトだと…。 # 今の Ruby の「/」ならば、この二つの解釈によって、返ってくる値が # 異なることになるのがちょっと気持ち悪いところです。 ○「==」比較の問題 現在、 1.0 == 1 => true ですが、 1.0/2 == 1/2 => false です。 # 1.0 が気持ち悪ければ、Rational(1) に置き換えてもいいでしょう。 同じものに対して、同じ(記号の)演算を行なった結果が、異なるわけです。 「/」でrationalが返れば、こういう気持ち悪さ(?)が無くなります。 ○mathn のことを考えなくてもよくなる 現状では、mathn を require することで、「/」の挙動を変更できます。 少なからぬ人が、これを常用しているのではないかと推測できます。 Ruby本にも紹介されている方法ですし。 この変更は、Global に影響を与えます。つまり、汎用ライブラリを 書く場合、(mathn を require する人々のことも考慮すると)ライブラリ 内で「/」が整除でないとどうしても困る、というように使用するのは 躊躇われます。 # Ruby2 では、「Selector Namespace」が考えられているようなので、 # http://www.rubyist.net/~matz/slides/rc2003/mgp00029.html # この辺りはうまく解決され得るかも知れませんが。 もし、int/int => rational がdefaultになった場合、逆はしごく簡単です。 つまり、整除にしたければ、結果に .to_i を常につけるなどすればいい、と。 もちろん、.div を使うもよし、と。 ○「落とし穴」で無くなる Reference Manual の「Rubyの落とし穴」には、整数への「/」について の注意があります。 http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=trap%3A%3ANumeric 「/」が整除である以上、C/Fortran的仕様かPython的仕様か、という 無視できない問題がありますし、(初心者向けの)「落とし穴」への 記述は避けられません。でも、int/int => rational ならば、(rational をユーザーが意識する必然がほとんどない以上)「落とし穴」に敢えて 記述するほどのことではなくなるんではないかと (=潜在的な「落とし穴」 がひとつ減る?!)。 # 無論、仕様変更時は、「!変更点!」として最大限強調するにせよ。 ○プログラミング初心者への福音!? プログラミング初心者(特に、Ruby が初めて触るプログラミング言語 という(恵まれた!)人)にとって優しい。 基礎算数(〜数学)教育のどこにおいても、3÷2 は 1 になりません。 1.5 か、1あまり1か、1と2分の1か、2分の3か、その感覚は人それぞれにせよ、 「1"と少し"」というのが、多分身に染み着いた感覚でしょう (プログラ ミング言語に触れるまでは!)。 プログラミング言語に慣れ親しんだ人にとっては、そういう普通の算数的な 感覚とは、(慣れ親しんだ言語によってそれぞれ)違う感覚を育ててきたかも 知れません。しかし、自分が慣れ親しんだ感覚そのままで他の言語でcoding すれば…はまる可能性大。例えば、C言語とRubyとPerlとSmalltalkとで 「/」の挙動はすべて違いますから。でも、それはある一言語で面倒見切れる 話ではない。 では、どこに標準を持ってくるのが、「最小驚き」になるか、というのが 議論のポイントだと考えます。「/」は割算(もしくは分数; 同じことですが) というのが一般的な捉え方だと仮定すれば、算数に一致する定義にすれば、 少なくともプログラミング初心者には「最小驚き」ではないか? 逆に エキスパートなら、「『/』は要注意」というのは知っているはずだから、 十分対応できるのではないか(後述)、と思います。 言葉を替えれば、少なくとも「計算機プログラミング初心者」にとって、 > |当然です。で、今の Ruby の「/」の挙動は、「整数(Integer)」という > |オブジェクトをユーザーが常に気にしなくてはいけない仕様だと感じます。 > |一方、ユーザーが最も自然に気にするのは、ただ「数(Numeric)」 > |なんじゃなかろうか、と私は感じるわけです。 は、成り立ちませんか? # もし周りにプログラミング初心者、または非経験者がいれば、 # 3÷2 は? と尋ねてみれば、1 という答が返ってくる可能性はごく低いでしょう。 だから、、、3/2 => 3/2(Rational) になれば、 ・「プログラミング初心者」にとって優しい ・「プログラミング・エキスパート」にとっては、(反応はさまざまにせよ) 悪くても許容範囲内 (であるのが大勢)? ◎あともうひとこと 「3/2 が 1」は、プログラミング黎明期(=この半世紀)には大いに意味が あったし(人間が計算機の都合に合わせなければならなかった)、今でも、 そういう用途(たとえば速度重視)には意味があるところだと思います。 だから、優秀なプログラマーとなるためには、本来の算数的な感覚から 離れて、その言語特有の感覚へと移行するように自分の感覚を磨いて 変えていく必然もあったことと理解します。 # そして、そういうエキスパートにとって、しばしば「3/2 が 1」の方が # 自然になる、というのも大いに理解できます。 機械語やアセンブリは本当にパズルだったところが(ハンドアセンブルが 懐かしい…)、C言語のお蔭でかなり楽になりました。人間が、計算機特有の 枠組を以前ほど意識しなくて済むようになった。Ruby のおかげで、それが さらにずっと楽になりました。今後、パズルを解くようなプロフェッショ ナルなプログラミングから、論理の筋を自然に追えば書ける、という プログラミングの大衆化に向かって進むなら、表記は「ノン」プログラマー の感覚と一致していればいるほど、彼らにとって理解が早い、と感じます。 # 例えば、"1 sin" (Smalltalk) よりも sin(1) (Ruby) の方が # 「ノン」プログラマーには自然でしょう、と。 Ruby の仕様にどっぷり浸かっているエキスパートの方々には、 仮に「/」の挙動の default を変更すると、しばらくは気を遣う必要が ある人も出てくるでしょう。また、既存のライブラリで変更が必要になって くるものも出てくるでしょう。それはマイナスの影響ですね。 一方、今後、Ruby ユーザーは増えていくでしょうし、ノンプログラマー から Rubyエキスパートになる人々もどんどん増えていくでしょう。 ノンプログラマーにとって、「/」が"普通の"割算である方が自然だとすれば、 長い目で見て、Ruby2 で「/」の仕様を変更するのは、マイナスの影響を 補ってあまりある意義ある仕様変更だと、思う次第です。 ===== 以上、長文お読み下さり、ありがとうございました。 まつもとさんはじめ皆様、今一度御一考下されば、幸いです。 坂野 正明