坂野 正明です。

# 拙論では入門者(特にプログラミング言語全般の)にとって、
# 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 で「/」の仕様を変更するのは、マイナスの影響を
    補ってあまりある意義ある仕様変更だと、思う次第です。


=====

以上、長文お読み下さり、ありがとうございました。
まつもとさんはじめ皆様、今一度御一考下されば、幸いです。

坂野 正明