ともに最初の登場からは20年以上経ち、特にそれぞれ機械学習、Ruby on Railsなどの影響で利用されることの多くなったPythonとRuby。プログラミング学習と言えばCからと私などは思ってしまいますが、その敷居の低さから、この2つの内どちらかからプログラミングを始める、という場合も少なくないかもしれません。

そこで、私の場合はpythonからプログラミングを始めた訳ではありませんが、pythonに慣れていたところでrubyをコンスタントに書き始めた(厳密には4年前に授業で数か月触れていたが。)者として感じた、非常に基本的な部分の注意点・間違えやすいポイントを、予防接種のごとく、紹介したいと思います。

外部ファイル読み込み(require)の際にモジュール名などはクォーテーションで囲む。

見た目・影響ともに大したことではないのですが、これは初めの頃だけでなく、色々と慣れてからもirbで少し何か試すときなどについやってしまいがち。モジュール名がpythonと一致するものはそう多くはありませんが、csvモジュールはよく使う上に記法もimport csvとそう変わらないため、流れで””なしで書いてしまうことが多いです。特にrequireはファイルにスクリプトを書く場合は、全体に占める割合としてそうそう書くものではないため、たまにirbなどで書くときには忘れやすいポイントです。

キーワード引数はハッシュ形式で指定する。ただしデフォルト引数の設定には=が使える。

pythonではキーワード引数の値はx=5などと指定し、c++など他の言語でも概ねこの形式のため、当然rubyでも=を用いて指定するのかと思ってしまいます。さらに、デフォルト引数についてはrubyでも=で設定するため、例えば上図のforce_quotes=trueのように書いてしまうのですが、rubyでは:force_quotes => trueのようにハッシュ形式で指定する必要があります。

なまじirb等でこのようなことを経てから先のCSV.openのようなケースに当たると混乱するので要注意。(ここでは代入の戻り値9がfの第一引数となっているに過ぎません。)また、ここでは立ち入りませんが、関連した所でrubyのシンボルについて調べておくと、色々と勘違いが少なくなると思います。

Pythonはelif、Rubyはelsif

基本構文の中にも罠が仕掛けられています。これは最初に何の言語に触れたかという点も大きく影響すると思いますが、pythonならばelif、Cなどであればelse ifと普通の英語の文と同じようにelse ifが書けるという風に思う場合が多いでしょうか。しかしrubyではelsifです。

私はcやc++を学んでからpythonに移行した際に、else if ではなくelifという謎の略し方をすることに馴染みませんでしたが、今回はその経験もあってとりあえずelse ifと書いたら怒られたため、それでは、と思いelifと書いたらまた怒られてしまいました。

ちなみに、wikipediaのプログラミング言語リストから私が比較的メジャーだと思う言語のelse ifの記法を(細かいことは除いて)調べたところ、大半はelse if だがperlとrubyはelsif、Visual BasicがELSEIF、elifはpython特有のものという結果になりました。rubyはperlに影響を受けたということなので、このような記法になっているのだろうと思います。

enumerateとeach_with_index

if文の次はfor文をば。ということで、配列要素とともにインデックスを回す、pythonでいう所のenumerateのようなことをしたいと思い調べてみると、each_with_indexなるものがあるということに行きつきます。ということで意気揚々と使ってみると、、

何か違う。

pythonでは(インデックス, 要素)の順で指定するし、arr[index] = elementの順番的にインデックスが最初に来るものと思っていましたが、rubyでは逆なのです。所詮indexはwith indexの通り要素の添え物という理解のしかたもありますが、最近、arr.each.with_indexをeachメソッドとwith_indexメソッドとして用いるやり方を知ったため、(わざわざ使いませんが)これが根底にあることを意識すると、この順番も自然に感じるかもしれません。

for文っぽいものが色々ある

これは色々な方が言うことでもありますが、主に他人の書いたコードを読むときに厄介な点です。timesメソッドはpythonのfor i in range(x)に相当するもの、stepメソッドはpythonのfor i in range(0, 6)ないしrange(0, 6, 2)のようにステップ幅の指定ができるもので、一見pythonとrubyで相違ないように見えますが、pythonではlimit値の手前でループが終わるのに対し、rubyではlimit値を超える手前でループが終わるため、上図ではi = 5のループが実行されます。

この他にもuptoやdowntoやらもあり、人やコーディング規則の在り方にも依りますが、所々で色々な表現にぶつかることが多いのはpythonと異なる点です。

変数スコープの違い

これは私を含めCなどから触れたことのある方々にとっては自然なことですが、forループ内などで宣言、というか初代入を行った変数については、ループを抜けた後も参照できるpythonと違って参照できないため、事前にnilなどで初期化をしておく必要があります。

私の場合は初めてpythonに触れたときは変数スコープが曖昧なことに違和感がありましたが、今回の場合は逆に、rubyはcよりもpythonに近い印象であったため、ついpython感覚でfor文内で初期化した変数をループ外で参照してしまいました。(そして怒られました。)


今回は特に、つい当たり前のように書いてしまいがちな基本的な構文について、pythonとrubyの相違点を紹介しましたが、これ以外にも基本的な、あるいは細かい相違点は至る所に(隠れて)ありますので、アルゴリズム的に間違いがないはずなのに何か変数の値が違う、、、などといった場合には「当たり前」と思っている部分を疑うと原因に気付けるかもしれません。

最後に、本記事で少しでもRuby初学Pythonerのつまづきが1つでも減り、スムーズに学習が進めば幸いです。

Pocket