C・C++とRubyとで、あなたのコードがどう変わるのかを示すのは容易ではありません。 ものすごく大きな違いがあるからです。 一つには、Rubyの実行環境が本当にたくさんのことを行うという違いがあります。 RubyはC言語の「機構側は何も隠蔽しない」という原則からはかけ離れた言語のように見えます。 Rubyの本質は、人間の仕事を簡単にするために、できるだけ多くの作業を実行環境が肩代わりすることにあります。 最適化するためにコードをプロファイリングするようになるまでは、Rubyを使う際にコンパイラ側の都合を気にする必要はありません。
とはいうものの、C・C++で書かれたコードの実行時間と比べて、Rubyコードの実行時間はずっと遅いと言われています。 そのため、どうしたら最小のコードでやりたいことを実現できるかを考えると同時に、 それを高速化する方法についても、あなたは頭をフル回転させることになるかもしれません。 RubyはC++よりもずっとずっとシンプルな言語です。Rubyはきっとあなたのことを甘やかすことでしょう。
Rubyは動的型付けです。静的型付けではありません。 Rubyの実行環境は、なるべく多くのことをプログラム実行時に行おうとします。 たとえば、どのモジュールをRubyプログラムにリンクする(ロードして使えるようにする)かや、どのメソッドを呼び出すかを、 あなたはあらかじめ知る必要はありません。
幸いなことに、RubyとCは堅実に共生関係を持つことができます。 Rubyはいわゆる「拡張ライブラリ」という仕組みをサポートしています。 拡張ライブラリは、Rubyプログラムから使用することができるものですが、Cで書かれます (外側から見ると、それはRubyで書かれたライブラリと同様に振る舞います)。 この仕組みを使うと、Rubyプログラムの中でパフォーマンスが重要となる部分を、純粋なCで書き直すことができます。
そしてもちろん、Ruby自体もCで書かれています。
Cとの類似
Cと同様に、Rubyは…
- 書きたいと思えば、手続き的にプログラムを書くことができます(けれど、その裏側はオブジェクト指向のままです)。
- 使用できる演算子は、複合代入子やビット演算子も含めて、だいたい同じです。ですが、Rubyには
++
と--
はありません。 __FILE__
と__LINE__
を使えます。- 定数もあります。けれど、
const
のような特別なキーワードはありません。 定数化は名前付けによって行われます。変数名の最初が大文字のものは定数として扱われます。 - 文字列は二重引用符(
"
)で括ります。 - 文字列は可変です。
- manページのように、ターミナルからほとんどのマニュアルを読むことができます。ただ、その際に使うコマンドは
ri
です。 - これまでと同じコマンドラインデバッガを使うことができます。
C++との類似
C++と同様に、Rubyは…
- 使用できる演算子はだいたい同じです(
::
もあります)。<<
はリストに要素を追加するためによく使われます。 Rubyではメンバ関数の呼び出しに->
は使いません。常に.
を使うので、この点には気をつけてください。 public
やprivate
、protected
などを使います。- 継承を一文字で表現できます。ですが、使うのは
:
ではなく<
になります。 - コードをモジュール化することになりますが、これはC++で
namespace
を使うことと変わりません。 - 例外を扱うための作法は一緒です。ですが、そのために使われるキーワード名などには違いがあります。
Cとの違い
Cと違って、Rubyは…
- コードをコンパイルする必要はありません。単に実行するだけです。
- オブジェクトは強く型付けされています(そして、変数名自身はまったく型を持ちません)。
- マクロやプリプロセッサはありません。キャストもポインタ(とポインタ演算)もありません。 typedef や sizeof、列挙型もありません。
- ヘッダファイルはありません。ただ関数(「メソッド」と呼ばれます)とクラスをソース内に記述するだけです。
#define
はありません。そのかわりに定数を使います。- すべての変数はヒープ上に配置されます。あなたがそれを解放する必要はありません。代わりにGCがその世話をしてくれます。
- メソッド(関数)の引数は値渡しされます。参照渡しはされません。
#include <foo>
や#include "foo"
の代わりに、require 'foo'
と書きます。- アセンブリコードに変換はできません。
- 行の終わりにセミコロンは不要です。
if
やwhile
などの条件式は、括弧を付けなくても動きます。- メソッド(関数)呼び出しの括弧は基本的にオプションです。
- 波括弧はあまり使いません。複数行に渡る処理片の終わりには、一般的に
end
キーワードが使われます。 do
キーワードは「ブロック」と呼ばれる機能のためにあります。Cにおける「do命令」ではありません。- 「ブロック」はC言語にあるブロックとは別ものです。 Rubyのブロックは、メソッド呼び出しに関連付けるコード片を意味します。 ブロックは、メソッドの本体から実行時に呼び出されます。
- 変数宣言はありません。変数が必要になったら、新しい変数名に紐付けるだけです。
- 真偽値をテストする際、
false
とnil
だけが偽と評価されます。他(0
、0.0
、"0"
なども)はすべて真となります。 char
はありません。単なる一文字だけの文字列になります。- 文字列の終端はヌル文字ではありません。
- 配列リテラルは角括弧です。波括弧ではありません。
- 要素を追加すると、配列の大きさは自動的に拡張されます。
- 二つの配列を足し合わせると、新しい大きい配列が返されます(もちろん、ヒープ上に割り当てられます)。ポインタ演算は行われません。
- だいたいの場合は、すべてが式です(
while
命令が実際に右辺値を評価しているなど)
C++との違い
C++と違って、Rubyは…
- 明示的に参照を扱うことはありません。 Rubyでは、すべての変数はあるオブジェクトへの間接参照として扱われます。
- オブジェクトは強い型付けがされますが、それは動的に行われます。 環境は実行時、メソッド呼び出しが実際に行われたタイミングで型を決定します。
- コンストラクタは、クラス名ではなく、
initialize
メソッドとなります。 - メソッドはすべて仮想関数です。
- クラス変数(静的メンバ変数)名は、常に
@@
からはじまります(例えば@@total_widgets
というように)。 - 外部からメンバ変数に直接アクセスすることはありません。 publicなメンバ変数(Rubyでは属性と呼ばれます)へのアクセスはメソッド経由で行います。
this
の代わりにself
を使います。- 最後が?や!で終わるメソッドがあります。これらは実際にメソッド名の一部です。
- 多重継承はありません。Rubyでは代わりにMix-inを使います。 Mix-inを用いることで、モジュールが持つすべてのインスタンスメソッドを「継承」できます。
- 大文字表記、小文字表記が強制されるケースがあります。たとえば、 クラス名は大文字から開始し、変数名は小文字から開始する必要があります。
- メソッド呼び出しの括弧は基本的にオプションです。
- いつでもクラスをオープンしてメソッドを追加できます。
- どんな種類のオブジェクトでも変数に設定でき、型は実行時に評価されるので、 C++テンプレートは必要ありません。キャストもありません。
- イテレーションはわずかな違いがあります。
Rubyでは、
vector<T>::const_iterator iter
のような独立したイテレータオブジェクトは使いません。 代わりに、コンテナオブジェクトが持つeach
などのイテレータメソッドを使います。 イテレータメソッドはコード片を受け取り、それを各要素へと順に渡していきます。 - コンテナクラスは
Array
とHash
の2種類だけです。 - 型変換はありません。Rubyを使い始めれば、必要ない理由がわかるはずです。
- マルチスレッド機能は組み込まれています。 ただし、Ruby1.8 以前のマルチスレッド機構は、ネイティブスレッドに対してグリーンスレッドと呼ばれ、 処理系だけで実装されたスレッド機能になっています。
- ユニットテストのライブラリはRubyに標準添付されています。