初心者向けです。
過去6年間ぐらい、仕事で主に Perl を書いていた筆者が、ここ約1ヶ月と少しの間で Ruby を勉強し直して、ハマったことや「あれっ?」となったことをまとめておきます。
それ以前の Ruby 経験というと、Ruby 1.8 〜 1.9 ぐらいの頃に Rails で Web アプリケーションを作っていたこともありました、というぐらいです。1
前提
(この辺りはハマったことというか、Ruby 初心者向け。)
- Ruby は基本データ型を持たない。すべてがオブジェクト(特定クラスのインスタンス)
- 数値や文字列などのリテラルは特別な書き方ができるが、実体は
Fixnum
やString
クラスのインスタンス
- 数値や文字列などのリテラルは特別な書き方ができるが、実体は
-
+
や==
,[]
など、他言語では演算子とされるものが Ruby ではメソッドとして実装されていたりする2
つまづいたこと
リテラル
- シンボルと文字列の違い
-
stash[‘foo’]
とstash[:foo]
は異なる - Rails の ActiveSupport では同一になるように拡張されているようだ
-
参考:
「ActiveSupportによる既存Rubyクラスの拡張は人間をダメにするんじゃないか」 - ActiveSupportのHash拡張であるslice, exceptがびっくりするぐらい便利 - Qiita
真偽値
- 偽判定されるのは
false
とnil
だけ- Perl では空文字列や
0
も偽
- Perl では空文字列や
演算子(のように見えるメソッド):
-
++
,--
はない
参考:
@key_amb Matzさんによる回答をご覧くださいhttps://t.co/9x3up3x3Ef
— YSR@ゆきちさんを応援し隊 (@YSRKEN) 2016年1月15日
配列と範囲
- 配列(Array)と範囲(Range)は違う
-
(1..3)
と[1..3]
は違う。後者には1..3
という Range オブジェクトの要素が1個しか入ってない。(1..3).to_a
すれば[1, 2, 3]
になる。
-
参考:
暗黙の型変換
- たまにやってくれることもあるけど、Perlと同じ挙動を期待してはいけない。
#!ruby
5 + "1" #=> TypeError
"foo" + 5 #=> TypeError
"foo" << 5 #=> "foo\u0005"
5 + "1".to_i #=> 6
"foo" + 5.to_s #=> "foo5"
#!perl
5 + "1" #=> 6
"foo" + 5 #=> 5 ※警告は出る
"foo" . 5 #=> "foo5"
変数の局所性
- perl は
sub { ... }
の中でも外側のスコープのレキシカル変数に対して読み書きできる - ruby の
def ... end
はローカル変数を局所化する
多値
-
a, b, c
みたいなの - Perl からの類推だと、ただの配列なのかなと思ってしまったが、別物っぽい。
- 使う構文が決まっている。今のところ、代入か、多値を
return
するか、関数で引数を受け渡しするケースかと思う。
- 使う構文が決まっている。今のところ、代入か、多値を
- 特に、多重代入については、『初めてのRuby』において「誰もが完全な仕様を把握してないのではないか」とさえ噂される Ruby の魔境の1つ」という記述があった。
クラス変数
継承先でも共有される。
サブクラスで変更されると、親クラスや他のサブクラスも影響を受ける。
参考:
- これはMUST!ActiveSupport の Class#class_attribute を使おう! - Qiita
'===' 演算子によるクラス判定
Ruby でオブジェクト同士が等価的かどうか判定するメソッドは ==
と ===
があり、case 構文内では後者が使われている。
大雑把な理解としては、 ===
の方がフレキシブルな使い方ができる。
例えばオブジェクトがどのクラスに属しているか、 case 構文で判定するサンプルコードは以下のような感じ(NG 例と OK 例を載せている):
# NG
case x.class
when String
p "x is String"
when Hash
p "x is Hash"
end
# OK
case x # ここが違う
when String
p "x is String"
when Hash
p "x is Hash"
end
ちなみに、 x === String
と String === x
の結果は異なる。
これは、 ===
がメソッドであり、左辺がレシーバであることを考えれば理解できる。
参考:
その他
- クラスインスタンス変数というものがある
- Ruby 1.9 で
{ foo: 1 }
みたいな書き方ができるようになった。昔は{ :foo => 1 }
だけだった。
参考:
結びに
今のところ、こんなところです。
もうだいぶ慣れてきたかな、と思っていますが、また何か驚くようなことがあれば書き足すかもしれません。
以上です。
脚注
-
ちなみに、2016/4/9 現在は『初めてのRuby』を読み終えて、『パーフェクトRuby』と『Rails3レシピブック 190の技』を読んでいる途中です。 ↩
-
コメントを参考に。また、正確にはリファレンスマニュアルを参照のこと。 ↩