LoginSignup
6
6

More than 5 years have passed since last update.

Perl Monger が Ruby に入門してつまづいたことのまとめ

Last updated at Posted at 2016-04-09

初心者向けです。
過去6年間ぐらい、仕事で主に Perl を書いていた筆者が、ここ約1ヶ月と少しの間で Ruby を勉強し直して、ハマったことや「あれっ?」となったことをまとめておきます。

それ以前の Ruby 経験というと、Ruby 1.8 〜 1.9 ぐらいの頃に Rails で Web アプリケーションを作っていたこともありました、というぐらいです。1

前提

(この辺りはハマったことというか、Ruby 初心者向け。)

  • Ruby は基本データ型を持たない。すべてがオブジェクト(特定クラスのインスタンス)
    • 数値や文字列などのリテラルは特別な書き方ができるが、実体は FixnumString クラスのインスタンス
  • +==, [] など、他言語では演算子とされるものが Ruby ではメソッドとして実装されていたりする2

つまづいたこと

リテラル

  • シンボルと文字列の違い
    • stash[‘foo’]stash[:foo] は異なる
    • Rails の ActiveSupport では同一になるように拡張されているようだ

参考:

「ActiveSupportによる既存Rubyクラスの拡張は人間をダメにするんじゃないか」 - ActiveSupportのHash拡張であるslice, exceptがびっくりするぐらい便利 - Qiita

真偽値

  • 偽判定されるのは falsenil だけ
    • Perl では空文字列や 0 も偽

演算子(のように見えるメソッド):

  • ++, -- はない

参考:

配列と範囲

  • 配列(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 === StringString === x の結果は異なる。
これは、 === がメソッドであり、左辺がレシーバであることを考えれば理解できる。

参考:

その他

  • クラスインスタンス変数というものがある
  • Ruby 1.9 で { foo: 1 } みたいな書き方ができるようになった。昔は { :foo => 1 } だけだった。

参考:

結びに

今のところ、こんなところです。
もうだいぶ慣れてきたかな、と思っていますが、また何か驚くようなことがあれば書き足すかもしれません。

以上です。

脚注


  1. ちなみに、2016/4/9 現在は『初めてのRuby』を読み終えて、『パーフェクトRuby』『Rails3レシピブック 190の技』を読んでいる途中です。 

  2. コメントを参考に。また、正確にはリファレンスマニュアルを参照のこと。 

6
6
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6