初めての Ruby を読んだ
初めての Ruby を読みました。 良書でした。 この本は他の言語を使ったことがある人が Ruby の言語仕様をざっとキャッチアップするのに最適な本な気がします。
自分は本を読んだ後に書かないと知識が残留しない方なので、 自分忘備録として個人的に便利だったことを箇条書きでメモしておきます。
2章 配列とハッシュ
添字代入について
配列 a に対して添字代入は下記のような挙動となります。
irb(main):001:0> a = [1, 2] => [1, 2] irb(main):002:0> a[0] = 3 => 3 irb(main):003:0> a => [3, 2] irb(main):004:0> a[4]= "4" => "4" irb(main):005:0> a => [3, 2, nil, nil, "4"] irb(main):006:0> a[0, 3] = 'a', 'b', 'c' => ["a", "b", "c"] irb(main):007:0> a => ["a", "b", "c", nil, "4"] irb(main):008:0> a[0..2] = "A" => "A" irb(main):009:0> a => ["A", nil, "4"]
a[0, 3] = 'a', 'b', 'c'
^^ index: 0 から 3 要素以外はデータが消えてしまいます。
添字代入の裏側
添字参照式が返す値は、配列が保持しているオブジェクトの参照 実は添字代入式と添字参照式はまったく別物。
- 添字代入式 ... Array#=メソッドの呼び出し
- 添字参照式 ... Array#メソッドの呼び出し
よって下記のような現象が発生する。
irb(main):010:0> a = %w[a b] => ["a", "b"] irb(main):011:0> a => ["a", "b"] irb(main):012:0> a[-3] => nil irb(main):013:0> a[-3] = 1 IndexError: index -3 too small for array; minimum: -2 from (irb):13:in `[]=' from (irb):13 from /usr/bin/irb:12:in `<main>'
3章 数値
ビット演算
ビットシフトは下記のように行うことができます。
右にシフト
irb(main):021:0> 1 << 0 => 1 irb(main):022:0> 1 << 1 => 2 irb(main):023:0> 1 << 2 => 4 irb(main):024:0> 1 << 3 => 8 irb(main):025:0> 1 << 4 => 16
左にシフト
irb(main):026:0> a = 1 << 4 => 16 irb(main):028:0> a => 16 irb(main):029:0> a >> 1 => 8
4章 文字列
ヒアドキュメント
EOS が区切り文字で % のあとに送りたい変数をがかけます。
count = database_connector.get_int(<<"EOS" % author.id) SELECT COUNT(*) FROM book WHERE book.author_id = %d EOS
シンボル
シンボルは唯一性と軽量性が利点。
文字列の場合
irb(main):039:0* str1 = "ruby" => "ruby" irb(main):040:0> str2 = "ruby" => "ruby" irb(main):041:0> str1 == str2 => true irb(main):042:0> str1.equal? str2 => false
シンボルの場合
シンボルは内容が同値であれば必ず同一のオブジェクトとなる。 特定の内容を表すシンボルオブジェクトはプロセス内で唯一となる。
irb(main):043:0> symbol1 = :ruby => :ruby irb(main):044:0> symbol2 = :ruby => :ruby irb(main):045:0> symbol1 == symbol2 => true irb(main):046:0> symbol1.equal? symbol2 => true
オブジェクトとして同一かどうかだけを調べれば良いので、 シンボル同士は文字列同士に比べて高速に同値性を判定できる。
また、内容に対する唯一性を維持しなければならないため、 シンボルオブジェクトは文字列をは異なり変更不能(immutable)。
5章 入出力
特にまとめることはなかったかもです。
6章 変数と式
参照
入力のオブジェクトを破壊せずにオブジェクトを加工したいときには dup
を使って複製してから行う。
def describe(name) name[2] = ?p end
^^ これだと破壊的に処理してしまうため、
def describe(name) name = name.dup name[2] = ?p end
という感じでオブジェクトを複製します。
多重代入
複数の式を平行して代入することができる。
a, b, c = 1, 2, 3
内部的には
a = 1; b = 2; c = 3
をしているとおもいきやそうではないらしい。
上記とは評価順序が異なり、 代入されようとしている値は、代入が実際に行われるよりも先に完全に計算される。 よって、
a, b = b, a
なども、元々も a 及び b の値がそれぞれ b 及び a に代入され、値の交換が実現できる。
irb(main):062:0> a, b, c = 1, 2, 3 => [1, 2, 3] irb(main):065:0> a, b = b, a => [2, 1] irb(main):066:0> a => 2 irb(main):067:0> b => 1
多値と配列展開
多重代入は多値をいっぺんに代入する記法です。
*
とい修飾を使うことで多値を受け取ることができる。
irb(main):068:0> a, *b = 1, 2, 3, 4, 5 => [1, 2, 3, 4, 5] irb(main):069:0> b => [2, 3, 4, 5] irb(main):070:0> a => 1
また、*
が代入の右辺に出現すると、逆に配列を多値に展開してくれる。
irb(main):071:0> array = [1, 2, 3] => [1, 2, 3] irb(main):072:0> a, b, c = *array => [1, 2, 3] irb(main):078:0> a, b, *c, d = *array, 3, 4, 5 => [1, 2, 3, 3, 4, 5] irb(main):079:0> a => 1 irb(main):080:0> b => 2 irb(main):081:0> c => [3, 3, 4] irb(main):082:0> d => 5
7章 メソッド
レシーバの省略
擬似変数selfは常に「現在のレシーバ」を指している。 private メソッドは常にレシーバ省略形式で呼び出さなければならない。
Rubyプログラムにおいては、メソッド内外にかぎらずいかなる箇所においてもselfとなるべきオブジェクトが存在する。
irb(main):083:0> self => main
ブロック付きメソッドの定義
yield 式は、メソッド内から呼び出し側のブロックをコールバックする構文。
irb(main):092:0> def foo_bar_baz irb(main):093:1> yield "foo" irb(main):094:1> yield "bar" irb(main):095:1> yield "baz" irb(main):096:1> end => nil irb(main):097:0> foo_bar_baz do |item| irb(main):098:1* puts item irb(main):099:1> end foo bar baz => nil
8章 オブジェクトとクラス
特異メソッドと特異クラス
Rubyには特定のオブジェクトのためだけのメソッドやクラス、という概念があり、 これらのことを特異メソッド、特異クラスと呼ぶ。
特異クラス
ある特定のインスタンスのためだけにあるクラス。
CENTRAL_REPOSITORY = Object.new class << CENTRAL_REPOSITORY def register(target) ... end def unregister(target) ... end end
特異メソッド
概念上はクラスではなく、インスタンスに直接所属しているメソッド。 実装上は、特異メソッドもクラスに属していて、特異クラスのインスタンスメソッドという位置づけ。
irb(main):100:0> message = "Hello" => "Hello" irb(main):101:0> def message.build_greeting(target) irb(main):102:1> "#{self}, #{target}" irb(main):103:1> end => nil irb(main):104:0> message.build_greeting("world") => "Hello, world" irb(main):105:0> message2 = "Hello" => "Hello" irb(main):106:0> message2.build_greeting("world") NoMethodError: undefined method `build_greeting' for "Hello":String from (irb):106 from /usr/bin/irb:12:in `<main>'