Ruby は行指向型言語です。つまり、改行が一文の区切りとなります。
文末記号としてセミコロン ';' も使えるのですが、一行に複数の文を書きたいのでも ない限り必要ありませんし、推奨されてもいません。
class NoVipError < StandardError ; end
↑セミコロンで文を区切る頻出例。中身のない例外クラスの定義。
なお、C言語 と同様に、バックスラッシュを打つことで行を継続させることが できますし、メソッド呼び出しの引数も複数行にわたって書くことができます。
どこでなにが複数行にわたっての記述が可能か、ということはおおむねユーザの直感に そぐうように決められているので、問題はないでしょう(C や Perl プログラマなら、 この直感はより鋭くなるでしょう)。
#行末までコメントだぜ
シェルスクリプトや Perl や Python と同じです。
=begin RDを書くところ。 =end
このように、「'=begin'」のみの行から「'=end'」のみの行までの間もコメントとして 処理系には無視される。 クラスやメソッドの説明をRD(Ruby Document)形式で書くために使われたりする。
Ruby の変数には型がありません。 「すべてがオブジェクト」である Ruby では、変数はそのオブジェクトへの参照です。
Rubyの変数には数種類あり、識別子の先頭で書き分けます。
普通に英数字・アンダーバーで名前を付けます。 宣言は代入と同時、宣言されていないローカル変数の参照は NameError 例外を 起こします。
Ruby のローカル変数の宣言と評価順序はびみょーにかみ合ってません。 パースしていく感じで考えて下さい。
危険なアイツ。 '$' を先頭につけます。一度も代入せずに参照すると nil を返します。そういう意味 でも危険です。'$var' と間違って '$val' とタイプしてもエラーになりません。
自分で作った変数だと「'$' が先頭 -> グローバル変数」なのですが、組み込み変数の中には例外(スレッドローカルだったり)があるので注意が必要です。
大文字で始めると定数にされます。 const や final のようなキーワードはありません。 宣言は代入と同時です。宣言されていない定数を参照すると NameError 例外が発生 します。この挙動を返るフックは存在しますが後述します。
Ruby の定数の縛りはちょっとゆるく、定数に再代入(初回の代入(=宣言)以降の代入) しても現在はエラーではなく警告が出るだけです。
また、Ruby の変数は前述のとおりオブジェクトへの参照なので、定数とするのも 参照です。
CONST_ARRAY = [] CONST_ARRAY.push 'hoge'
なので、オブジェクトの操作はし放題です。オブジェクトの変更禁止は別の方法が あります。
Ruby で「オブジェクトの状態」を表現するもの。 '@' を先頭に付けます。一度も代入せずに参照すると nil を返します。
メンバー変数とでも言える機能ですが、オブジェクトの外からのアクセスは (リフレクション抜きでは)できません。 通常 setter・getter メソッドを定義します。
名前どおりクラスが持つ変数です。 そのクラスと、そのクラスのオブジェクト両方からアクセスできます。さらに、 サブクラスに継承されたりします。若干スコープがややこしいです。
'@@' を先頭に付けます。一度も代入せずに参照すると NameError 例外が発生 します。
Rubyのリテラル表現は豊富です。以下に代表的なものを挙げます。
123 | 整数 |
4567.89 | 実数 |
?a | aの文字コード |
"double_quote" | 式展開などが解釈されます |
'single_quote' | 書いたままになります |
`back_quote` | コマンドとして実行し、出力を値とします |
`back_quote` 構文の挙動は、実は Kernel#` というすごい名前のメソッドが 実現しています。
式展開とは: val = 123 puts "put #{val} value" このコードを実行すると、出力は put 123 value となります。式展開が有効なリテラル中で、#{...} で Ruby の式ならなんでも 置いてみると、それを評価した値の文字列表現が展開されます。 「式展開が有効なリテラル」と言いましたが、この機能が有効なのはダブルクォート 文字列に限らず、ヒアドキュメントや正規表現リテラルでも使えたりします。
[12, "abc", 123.45, some_method()]
カンマで式を区切って並べて要素を指定します。もちろん一つも要素を指定しないで、 空の配列を作ることも可能です。
{ "key" => "value", :KEY => 123 }
「キー => 値」という式のペアを、カンマで区切って指定します。もちろん一つも 要素を指定しないで、空のハッシュテーブルを作ることも可能です。
Ruby 1.9.x feature: { key1: "value", key2: 123 } キーが Symbol リテラルの場合、こういった書き方もできます。
Symbol オブジェクトは、Ruby の識別子の実体でもあるオブジェクトです。 処理系に作られるものもあれば String#intern メソッドによって作られるものも あります。
「:ident」のようにリテラルが書けます。「:"*hoge*"」のように、識別子っぽくない Symbol をリテラルで書くにはクォートします。
メソッドに引数としてオブジェクトを渡すのみならず、処理のカタマリ=ブロックを 渡すことができます。
method_name(arg, ...) do |x| ... end
method_name(arg, ...){|x| ... }
のように記述すると、method_name 内でこのブロックを呼び出すことが 出来ます。|...| で囲われた部分は、そのブロックのためのローカル変数です。 メソッドの引数のようなものですが、メソッドと違ってブロックからは外側の ローカル変数を見ることが出来ます。
ざっくりと言ってしまうと、高階関数に渡すための無名関数のリテラル、と言えます。
例えば Lisp だと (mapcar #'(lambda (x) (* x 10)) '(1 2 3)) ; => (10 20 30) のようなことが、Ruby では [1, 2, 3].map{|x| x * 10 } # => [10, 20, 30] と書けます。
Ruby 1.9.x feature: ブロックローカル変数の扱いが変わっています。 - 多重代入のような挙動から、メソッド引数のような扱いに変更されています。 - 外側の環境に同名のローカル変数があるのに、ブロックローカル変数にもその名前を 使った場合、外側の環境の変数として扱われていたのに対し、新たに ブロックローカル変数が確保されるようになります。
ブロックを受け取った側では、yield を使ってブロックを関数呼び出しのように 呼び出せます。
def method_name(arg, ...) ... block_returning_value = yield(val) ... end
この機能によって、制御構文のようなメソッドが Ruby にはいろいろあります。
以下に述べる条件分岐などで、Ruby の値(=オブシェクト)がどのように真偽評価される かを説明します。
結論から言うと、Ruby における偽とは false と nil であり、それ以外のあらゆる オブジェクトは真です。
明示的に真を表す代表的な値に true があります。
これら(true, false, nil)はそれぞれ TrueClass, FalseClass, NilClass の唯一の インスタンスです。
if EXPR then ... end if EXPR [then] ... end ... if EXPR
EXPR を評価して真ならば、... を実行する。 複数行に分けて書くならば(改行で区切りが明確なので) then は省略可能です。
if EXPR1 ... # (A) elsif EXPR2 ... # (B) else ... # (C) end
EXPR1 を評価して真ならば (A) を実行して終わりますが、そうでない場合、 EXPR2 を評価して真ならば (B) を実行します。 こうした elsif 部の条件式も全部偽だった場合、(C) の else 部を実行します。
0 個以上の elsif 部の後に 0 ~ 1 個の else 部が書けます。
if に似た文法をとりますが、unless は条件式の評価基準が逆です。
... unless EXPR
は、EXPR の評価が偽のときだけ ... を実行しますし、
unless EXPR ... (A) else ... (B) end
は、EXPR の評価が真ならば (A) を実行し、そうでなければ (B) を実行します。 ただ、if における elsif に相当するパートはありません。
Ruby における繰り返し(ループ)のための文とは、
です。以下これら総称してただ単にループと呼びます。
while COND [do] ... end
COND の評価が真である限り、中の文を実行します。do は省略可能です。
until COND [do] ... end
while - until は if - unless の関係に対応し、COND の評価が偽である限り、 中の文を実行します。
: for 文
for IDENT in LIST_EXPR ... end
Ruby の for 文は C などのものと違い、シェルスクリプトや Perl の foreach に 近いです。 これは、配列のように複数の要素の集合である LIST_EXPR(の評価結果)に対して、 その各要素を IDENT という変数に取り出して順次処理していくときに使われます。
in の後にとるオブジェクトには、each というメソッドがイテレータ(後述)として 実装されている必要があります。 for 文は内部でこのメソッドを呼んでいます。
array = [1, 2, 3, 4, 5] array.each do |x| p x #=> 1, 2, 3, 4, 5 end
ブロック付きメソッド呼び出しで、「要素に対しての繰り返し」を隠蔽して 実装しています。
loop do ... end
のように、一見制御構造のようなイテレータから、
1.upto(10) do |x| p x #=>1, 2, 3, ..., 9, 10 end
のように、用途が特化した便利なイテレータもあります。
元々 Ruby のブロック付きメソッド呼び出し機能は、このようなイテレータメソッド を実装する狙いで、CLU という言語を参考にしたものです。 そうした歴史的経緯から、ちょっと前の文書だと 「ブロック付きメソッド呼び出しのブロック」ぐらいの意味で「イテレータ」という 言葉が使われていたりします。
ループ内でのフロー制御文です。
begin ... # (A) rescue ExClass => ex ... # (B) else ... # (C) ensure ... # (D) end
(A) 内で起きた例外を rescue で捕捉します。
捕捉する例外クラス ExClass を指定して、変数 ex で実際に捕捉した 例外オブジェクトを参照します。 「rescue => ex」、「rescue ExClass」のように両者とも省略可能です。ExClass が 省略された場合は StandardError が指定されたものとして処理されます。 rescue 節は、発生した例外のクラスが ExClass、またはそのサブクラスの場合にその 例外を捕捉します。
並べた rescue 節がひとつも実行されなかった場合、(C) の else 部が実行されます。
そして最後に、例外が起きようが起きまいが、どの rescue 節あるいは else 節が実行 されようがされまいが、必ず締めに実行されるのが (D) の ensure 節です。
1 個以上の rescue 節のあとに 0 ~ 1 個の else 節が書けます。 そのあとに 0 ~ 1 個の ensure 節が書けます。
せっかくのオブジェクト指向言語ですから、クラスの作り方をば。
class ClassName < SuperClass ... end
「< SuperClass」は名の通り継承するクラスを指定します。省略すると自動的に Object クラスを継承します。評価すればスーパークラスを返す式ならば置けます。
ClassNameは大文字で始める必要があります。定数と同じです(というか、まんま定数 なのですが)。
定義したクラスのインスタンスは obj = ClassName.new() のカタチで作れます。 カタチを見て判るとおり、new は予約語ではなくメソッド名で、普通に変数名とかにも 使えます。
生成したクラスを初期化したい場合、C++ や Java でいうコンストラクタのような ものを定義します。class ... end 内で定義される initialize() というメソッドが それです。new は自分の引数を initialize に丸投げします。
クラスと似たようなものにモジュールがあります。
module ModuleName ... end
モジュールはクラスと違って継承できず、インスタンスも持てません。
しかし、include によってそのモジュールで定義した機能を クラス定義中に取り込むことができます(Mix-In)。
class ClassName public ... # (A) private ... # (B) protected ... # (C) end
C++ や Java と語彙が一緒なので誤用されていることがたまにあります。
(A) で定義されたメソッドは public で、どこからでも呼べます。
(B) で定義されたメソッドは private で、そのオブジェクト自身のコンテキストで しか呼べません。
(C) で定義されたメソッドは protected で、private のような制御が成されますが、 自分のクラスがそのオブシェクトのクラスと同じ、あるいはサブクラスであるような オブシェクトのコンテキストでは public な制御がされます。
Ruby のメソッド呼び出し制御の着眼点は、「レシーバ.メソッド」という形で 呼び出すかどうか、に集約されます。
class Hoge def initialize priv # これはOK self.priv # NoMethodError end private def priv ... end end
同じコンテキストですらこうです。
それから、いくら private にしようがリフレクションでどうにでもなるゆるゆるな制御 なので、あてにし過ぎるのは止してください。
「変数」の節で
メンバー変数とでも言える機能ですが、オブジェクトの外からのアクセスは (リフレクション抜きでは)できません。 通常 setter・getter メソッドを定義します。
と述べました。
さて、その setter と getter ですが、set_member(val), get_member() のような ネーミングは Ruby では一般的ではありません。
obj.member = 123 obj.member
あたかも属性のように、こう書きたいものです。そして Ruby では実際にこのような書き方が出来ます。Ruby パーサは、前者を member=() という名前のメソッド呼び出しと 解釈してくれるからです。
class C def member @member end def member=(val) @member = val end end
これで、インスタンス変数をメソッドで属性のように扱えます。 定義する際においては他のメソッドとなんら変わりなく、代入値のチェックなども 自分で勝手に書けます。
ただ、そういった独自処理もしないのにいちいち上記のような setter・getter を手で 書くのは煩雑です。なのでこれに等しい処理は
class C attr_accessor :member end
で可能です。
特別な構文のように見えますが、実はリフレクションを駆使して定型処理を便利に まとめた 1 メソッドに過ぎません。 def my_attr_reader(name) define_method(name){ instance_variable_get("@#{name}") } end def my_attr_writer(name) define_method("#{name}="){|val| instance_variable_set("@#{name}", val) } end 最低限、こんな感じで自分でも実装できます。