PerlerのRuby日記

Rubyとか

参考書読んで覚えたこと雑記

  • rescue HogeError で、HogeErrorクラスを継承しているクラスの例外ならそれもキャッチされる。(よく考えたらrescue Exceptionが全部拾うなぁ)
  • コマンドラインオプション
    • c:文法チェック、w:警告モード、r:指定ファイル実行、d:デバッグモード、W:すべて警告モード、W0:標準出力警告モード、W1:標準入力警告モード、W2:標準エラー出力モード
  • 有効な環境変数
    • RUBYOPT:デフォルトで指定するコマンドラインオプション、RUBYLIB:デフォルトライブラリ検索パス
  • メソッドの中から外側のローカル変数は参照できない
  • 親クラス名の取得は、obj.class.superclass
  • %と%Qは同義(ダブルクオート扱い)。
  • 文字列の%演算子はsprintfと同じ意味になる。
  • eql? は==と大体同じだけど、違うときもある
    • 1 == 1.0 #=> true だけど、 1.eql?(1.0) #=> false だ!
  • a = Array.new(2, "a")でできるa[0]とa[1]は同一オブジェクト
    • 別物にするにはブロックを渡す。a = Array.new(2) { "a" }
  • 配列に*を使うとjoin扱いになる
    • [1,2,3]*"-" #=> "1-2-3"
  • for式ではブロックスコープが作成されない
  • ハッシュに存在しないキーを指定したときのデフォルト値は変更できる
    • h = Hash.new("a"); h[:nokey] #=> "a"
  • Hashでハッシュを作るときは=>ではなくすべてカンマ区切り
  • 正規表現マッチは=~だけでなく===でもt/fが返ってくる
    • /abc/ === "abcde" #=> true
    • "abcde" === /abc/ ではないことに注意!
  • ブロックを引数として渡すと、そのときの外部の変数を参照できる
    • x = 10; 1.upto(5) { |i| x += i }; x #=> 25
  • Procとブロックは引数が違ってもnilで埋めてくれるが、lambdaはArgumentErrorを発生させる
  • raiseを空実行させると、直前の例外を再発生させる
    • begin; 1/0; rescue; p "error"; raise; end
  • throwしたらcatchを抜ける
  • ancestorsメソッドでクラスの継承チェーンを参照できる(クラスメソッド)
    • 1.class.ancestors #=> [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
    • ↑1.8.7
    • 1.class.ancestors #=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject]
    • ↑1.9.3
  • 包含関係は大なり小なりで確認できる
    • Fixnum < Integer #=> true
  • includeするとそのモジュールの無名クラスが作られて、親クラスとの間に勝手に差し込まれる
    • しかしsuperclassやancestorsでは出てこないので注意
  • メソッド内で定義されているメソッドは、外側のメソッドが実行されるまで定義されない
  • extendとは、特異クラスに対してincludeすること
    • foo.extend(Bar)は、class << foo; include Bar; endと同義
  • privateメソッドはselfを省略した形でしか呼び出せない
  • 組み込み関数とはKernelモジュールのprivateメソッド
    • ただし独自の組み込み関数を定義するときはObjectクラスにすべき
  • インスタンス変数はメソッドのように探索されない
  • メソッド内で定数を定義すると、SyntaxErrorとなる
    • メソッドは複数回の実行が前提なので定数の初期化、値の更新を許していない
  • constantsメソッドでそのモジュール・クラスの定数を配列で返してくれる
  • 定数が同モジュール・クラス内に存在しない場合、外側に探索する
    • スーパクラスでも定数が見つからない場合、const_missingが呼び出される
  • Ruby1.8.7では、puts nilで「nil」が表示される
  • raise => e; e.backtrace でスタックトレース
  • オーバライドできない演算子
    • ?: ... .. ! not && and || or ::
  • 配列同士の引き算では、右辺にある要素に該当する左辺要素すべて削除される
    • [1,1,2,2,3]-[1,2] #=> [3]
  • Array#unshift は引数を指定しなければ何もしない
    • [1,2,3].unshift #=> [1,2,3]
  • String#index の第2引数は探索開始位置を指定できる
  • String#, String#slice で数値指定・範囲指定・文字列指定・正規表現で抽出できる。マッチした文字だけ返す。
    • "abcdefg"[0] #=> "a"
    • "abcdefg"[0..1] #=> "ab"
    • "abcdefg"[0...1] #=> "a"
    • "abcdefg"["a"] #=> "a"
    • "abcdefg"[/.*/] #=> "abcdefg"
  • String#delete の引数は、正規表現でいうところの「文字クラス」を文字列にしたもの
    • "abcdefg".delete('a-c') #=> "defg"
    • "abcdefg".delete('^a-c') #=> "abc"
  • String#scan はマッチした部分の文字列を「配列」で返す
    • "abcdefg".scan(/.../) #=> ["abc", "def"]
  • Hash#include?, Hash#member? はキーに一致するかを見てる
    • { :a => 1, :b => 2 }.include?(:a) #=> true
    • { :a => 1, :b => 2 }.member?(2) #=> false

  • includeするとモジュール名もancestorsメソッドで確認できる
    • module Hoge;end

class Fuga; include Hoge; end

Fuga.ancestors

#=> [Fuga, Hoge, Object, Kernel]

  • Float + Ratinal #=> Float
  • Float + Complex #=> Complex
  • ただのattr :hogeはattr_reader :hogeと同義。attr :huge, trueは、attr_accessor :hugeと同義。
  • クラス変数はサブクラスに共有される。
  • sortにブロックを渡して評価するなら、左が小さいなら「-1」にする
  • begin end内でのexitは、SystemExit例外を投げる
  • freezeはオブジェクトの内容の変更を禁止するのであって、参照変数自身は変更可能である。
    • a = [1,2,3].freeze
    • a += [4,5]
    • a #=> [1,2,3,4,5]
  • ancestorsメソッドはModuleクラスのインスタンスメソッド
  • Time - Time #=> Float