2008-06-23
2008-05-24
■[memo][ruby][lisp]配列の先頭要素が「0番目」であることは気持ち悪いか…「N番目」という言葉を考察してみる
JavascriptやPHPの配列や関数などで 配列の最初の要素がary[0]に.. - 人力検索はてな
C言語、Ruby、Lispなど多くの言語では配列は0起点である。つまり、先頭の要素のインデックスは0である。
なぜそうなっているか‥それは実装上の都合であったり歴史的理由だったりする。
C言語の配列は「連続したメモリ空間の、先頭アドレス」で表現している。そして、オフセットを進めることでそれぞれの要素にアクセスしている。だから配列の最初の要素を「0番目」とすることでアドレス計算が楽になるわけだ。
多くの言語はC言語の文法を拝借しているし、C言語は十分普及しているから、「C言語にあわせて配列は0起点でいいや」となっていると推測している。コンピュータの世界じゃ歴史的理由ってのがけっこう多い。
そういうわけでプログラマが配列の要素を数えるとき、勝手に「0番目」→「1番目」→「2番目」と数えている。新しい言語でも0起点とするのは、プログラマにとって自然だ。
しかし、日本語の観点では「0番目」というのはいささか気持ち悪い。「日本語」では、順番に並んでいるものの先頭は「1番目」として数えるからだ。
気持ち悪いのは確かなんだが、こうは考えられないか?「N番目」という言葉は、プログラミングの文脈では「インデックスがN番目」という意味にオーバーライドされていると考えるのだ!言葉なんて文脈によって意味が異なるじゃん。「鯖」という言葉をとってみても、一般的な意味では魚のサバだが、インターネットの文脈ではserverを意味する*1。
それでもいささか気持ち悪いのは、(0起点の)「N番目」という言葉は、通常の日本語の意味の(1起点の)「N番目」という言葉で表現できてしまうからだろう。Rubyなどのオブジェクト指向プログラミング言語でいえば「super」だ。
この「N番目」という言葉はかなりの曲者で、プログラミングの解説の文脈でも0起点だったり、1起点だったりするのだ!
たとえば解説でインデックスが「+1」されていれば普通の日本語の「N番目」という意味だ。
ary = [:foo, :bar, :baz]
ary.each_index do |i|
puts "#{i+1}番目の要素は#{ary[i].inspect}です。"
end
# >> 1番目の要素は:fooです。
# >> 2番目の要素は:barです。
# >> 3番目の要素は:bazです。
一方、Array#[]の解説では「N番目の要素を得る」と書いてある。これは0起点の「N番目」が使われている。Array#[]の解説で「N+1番目の要素を得る」と書かれているのはほとんど見かけない。これは…理解のしやすさ、文章のすっきり度なんだろうね。
こんな感じでプログラミング解説で「N番目」という言葉が出てきたら、プログラマは脳内で無意識に「0起点かな、1起点かな」と考えさせられる。脳味噌のCPUタイムの無駄である(笑)それでも、経験的にプログラミング解説では0起点の「N番目」が使われていることが多いようだ。
どうしても気持ち悪いのが抜けないならば、いっそのこと新しい表現を使えばいいじゃないか。(0から数えて)「N番目の要素」という表現を「インデックスがNの要素」と言い換えてみる。それなら間違いなく0起点なんだからね。
[2008/05/25]追記
class Array
alias aref_org []
def [](x)
aref_org(x - 1)
end
end
当然、これでは不十分です。 a[1, 2]やa[1..2]の場合に対応できていません。
他にも配列のインデックスを扱うArray#values_atとか、Array#indexとかもありますし。
Array#begin、Array#begin=で起点を指定できればいいのですが…
[2008/05/25]追記
404 Blog Not Found:perl - 配列を1番目からはじめてみる
$[ キターーーーーー(゜∀゜)ーーーーーー!!
Perlな人は「1からやり直しです」を「$[からやり直しです」って言うんだっけか。大昔0か1の代わりに $[ と書いてるのを見てコーヒー吹いたことがある。
[2008/05/25]追記
これ、現実世界との接点がある説明で結構困る。「HTML上で1番目の<form>を配 列から抽出」と か。0番目の<form>ってあるの? みたいな。結局「HTMLで1番 目の<form>を配列の0要素目から 選択」とか妙な表現に
まったく…そうなんですよorz
やっぱりRubyの配列は起点を指定できると嬉しい…もちろん組み込みで。
[2008/05/25]追記
先頭要素が「1番目」であるFortran - @author pyridoxin
FORTRANやCOBOLやBASIC(可変)の配列は1起点ですね。他にはどんな言語があるのでしょう。
推測ですが、C言語とFORTRANの問題領域が異なるからでしょう。C言語は機械寄りだからアドレス計算が楽な0起点になっています。
FORTRANは数値計算がメインだから1起点が無難なのでしょう。行列にしたって、左上の要素は1行目1列目の要素(A_1_1)であって0行目0列目の要素とは言わないでしょう。
2008-03-05
■[lisp]Lisp系言語のカッコは慣れの問題
Schemeではじめての計算 - Mattari Diary
LispやSchemeは日常使っている中置記法ではないから慣れるまでが大変かも…でも慣れたら普通に読めるので。LispやSchemeは四則演算等他言語だと演算子で提供されるものも関数やマクロであることがポイント。「+」、「-」、「*」、「/」は演算子ではなくて関数名。で、「(関数名 引数 ...)」という文法になっているので、そういう形式に目を慣らそう。
Emacsを使うならばquack.elとscheme-complete.elを入れると快適になると思う。カッコの対応を目視で取ると挫折するので、カッコの対応を自動で取ってくれるエディタの習得は必須。
2008-02-26
■[lisp]Schemeやるならまともなエディタを使おう
Schemeは俺もけっこう好きな言語だ。set!とかはあるけど、雰囲気が正統派の関数型言語という感じで美しい。最近の言語は関数型パラダイムを取り入れているのが多いから、Schemeで学んだことは他のプログラミングにも生かせるはず。
SchemeにせよCommon Lispにせよカッコだらけだから、Emacs等カッコの対応を取るエディタは必須だ。絶対使え。そしてS式ベースの移動を覚えよう。でないと間違いなく挫折する。
俺も大昔Emacsにあこがれていた。懐しい…あのころは矢印キーでポイント動かせなかったな。C-p、C-n、C-b、C-fを覚えさせられた。
