独習ruby
読んだまとめ
デバッグメソッド
puts
p
pメソ ッドはputsに似ているが値をより型情報のわかる形で出力する。
たとえば、文字列であれば "Hoge"
のようにクウォート付きで出力する。配列ならブラケット付きで出力。
rubyコマンド
ruby -w
オプションを渡すとコードに問題があるい場合に警告を表示してくれる
データ型
動的型付け。 ただしデータ型をまったく意識しなくても良いわけではない。 値を演算/比較する場面ではデータ型によって挙動が変化する。
ヒアドキュメント
シンボル型(Symbol)
シンボルは文字列に比べてメモリ消費が少なく、比較(検索)のためのパフォーマンスも高い型
シンボル(Symbol)はシンボル(モノの名前)を表すための型。
head = :title
puts head # 結果 title
:名前
の形式で表す。文字列に似ているが以下の点で異なる
- 値を変更で機内
- 同じであるかを判定する場合、文字列よりも高速
- 同じ値であれば同じメモリで管理されるのでメモリの利用効率が高い
- 文字列よりも少しだけスッキリ表現できる。
nil型(ニル)
nil型はある変数が値を持たないこと表す。 より正確にはNilClassという型があり、nilはその値を格納した擬似変数
irb(main):003:0> puts 10
10
=> nil
=> 以降はputsが返す値を表す。 putsメソッドは指定された値を出力するだけで(voidみたいなものか)何らかの値を返すわけではない(=nilを返す)わけ
擬似変数
true/false、nilの他にも擬似変数が用意されている 擬似変数は変数とはいうが再代入ができない
self 現在のレシーバー
FILE
実行中の .rb
ファイル
LINE 実行中の行(番号)
ENCODING 現在のコードの文字エンコーディング
配列
配列の値は互いに異なっていても構わない。 が、一般的には1つの配列内では型を統一するのが普通
配列ショートカット
p %w!山田 佐藤! # ["山田", "佐藤"]
p %i!isbn title price! # [:isbn, :title, :price]
式展開を有効 w → W i → I
連想配列(キーは文字列型)
ハッシュは名前をキーにアクセスできる配列。 言語によっては連想配列、マップなどとよばれる。 ※キーが重複した場合、後半に宣言したキーで上書きされる。
構文
data = {
'name' => '鈴木',
'address' => '営業',
}
puts data['name']
ハッシュ(連想配列)
ハッシュキーはシンボルにするのが必須
構文
data = {
:name => '鈴木',
:address => '営業',
}
puts data[:name]
シンプルな構文
キーがシンボルの場合、さらにシンプルに キー:値
で表すことも可能
data = {
name => '鈴木',
address => '営業',
}
puts data[:name]
さらにシンプルな構文
data = {
name: '鈴木'
address: '営業',
}
参照/値渡し
Integer/Floatの一部の値/true/false/nil/シンボル
これらの型は処理効率上の理由から(参照値ではなく)実際の値そのものが変数に格納される(このような実装を即値と呼ぶ) ただし、これらの型ではこれまた処理効率上の理由から同じ値は同じオブジェクトとして管理される(同じ値であれば同じ参照値が返される)
定数
定数は変更できない変数と捉えるのは違う。 再代入できない変数(つまり変数であっても値を変更できてしまう場合がある) →そもそもRubyでは再代入しても警告しか発生しない
- イミュータブル(プリミティブ)
VALUE = 10
VALUE = 15 # エラー(警告)
- ミュータブル
VALUE = [10, 20, 30]
VALUE = [1, 2, 3] # エラー(警告)
VALUE[0] = 100 # 動作してしまう
多重代入
- 同時代入 複数の変数/定数に対してまとめて値を代入するための仕組 み
a, b = 12, 2
puts a # 12
puts b # 2
- 配列分解 配列を分解もできる(左辺の変数と右辺の 要素数は一致していなくても良い) →余った変数はnil(空)となる。
data = [1, 2, 3]
a, b, c = data
- 配列分解(であまった値をすべて代入) ※(アスタリスク)は末尾でなくても構わない。また値が入らなかった場合はからの配列が生成される。
data = [1, 2, 3, 4, 5]
a, *b, c = data
制御構文
Rubyの制御構文はすべて式(つまり値を返す。返す値がなければnil)
条件式が真の場合に命令を実行する
if(文)
- 後置if命令 else節がないのであれば、後置ifを使う
note 後置ifで変わるニュアンス 前置構文では「条件が正しければしなさい」条件が主体 後置構文では「しなさい。条件が正しければ」処理そのものが主体
if(式)
式としても利用可能(つまり値を返し変数に代入できる) if式では最後に評価された値を返す。
条件式が偽の場合に実行するunless
unless
否定は人間の頭にとって把握しにくいもの。 ※unlessのelseは否定の否定はかえって理解しづらいのでやめる。
unless 条件式
# 条件式が偽の時に実行する処理
else
# 条件式が真の時に実行する処理
end
- 後置unless
case ... when
switchのこと
例外処理
例外処理とは、あらかじめ発生するかもしれないエラーを想定しておき実行を継続できるよう処理する。または安全に終了させるための処理のこと
begin
# 例外が発生するかもしれないコード
rescue 例外の種類 => 例外変数
# 例外発生時の処理
end
第5章 最初らへん重要なことが書いてある
インスタンス構文
クラスによってはnewメソッドの代わりにインスタンス生成のための専用メソッドが用意しているものもある。
t = Time.now # 現在時刻を表すTimeインスタンスが生成される
構文
a = クラス名.new()
組み込みは読み込み不要だが、標準添付ライブラリ(Rubyと一緒にインストールされる)はRuby本体とは別のためあらかじめ読み込む必要がある。
&.(ぼっち演算子) Safe Navigation Operator
実際のコーディングでオブジェクトがnilではない時だけ、そのメンバーにアクセスしたいまたnilの場合はそのままnilを返す という状況はよくある。
このような処理をRubyでは &.
で 簡単にd系r。
str = nil
p str&.upcase # 結果 nil strがnilでもエラーにならない。
キーワード引数
引数はカンマ区切りで値を列挙するのが基本だが、メソッドによっては 名前: 値
の形式で渡せる場合もある。
日付/時刻
組み込みのTimeクラスを利用すれば十分。 DateTimeは非推奨になっている。
ブロックは複数の処理を束ねたもの
6章
セット(集合)
セットは、配列と同じく複数の値を束ねるための型。 配列とは以下の違い
- 順番はない(よって何番目の要素を取り出すといったことはできない)
- 重複した値は許されない(これが一番重要)Rubyの場合は無視される(エラーはなし)
- 順番を持たないため、実行結果の並び順はその都度変わる。
- ブラケット
[]
構文によるアクセスはできない。
require 'set'
# もっとも基本
sets = Set['山田', '佐藤']
# 配列などEnumerableな型からセットを作成したいのであれば、Set::newメソッドを利用する
sets = Set.new(['山田', '佐藤']) # 2
# 末尾にブロックを渡して、元の配列を加工してからSetが作成できる。
sets = Set.new([15, 32, 33]) {}
2が結構重要 配列などをSetにかまして重複を取り除くっていうのはいわゆるテクニック。
ハッシュ(再)
ハッシュは一意のキーと値のペアで管理されるデータ構造 ハッシュは内部的にハッシュ表(ハッシュテーブル)と呼ばれる配列を持つ。 応訴を保存する際に、キーからハッシュ値を求めることでハッシュ表のどこに値(オブジェクト)を保存するかを決定する。
8章
ブロックとは
メソッド呼び出しの際に引数と一緒に渡すことのできる処理のかたまり 引数の他に、do~endまたはで囲まれたブロック構文。
代表的なブロックの使い方
代表的な使い方が以下の3つです。
- 繰り返し
- 処理の隠蔽
- 処理の一部の差し替え
ブロック付きメソッド
メソッドによってはブロックを受け取れるものもある。 ユーザ定義メソッドでもブロック付きは実装可能(def..end配下でyield命令を呼び出すだけ)
考え方
children
と似ている。
枠組みとなる機能をだけを実装しておき、詳細な機能はメソッドの利用者が決める汎用性の高いメソッドを設計できる。
# ブロック付きメソッドの定義
def my
start_t = Time.now.to_f
# ブロック呼び出し
yield
end_t = Time.now.to_f
end
my do
sleep(4)
end
ブロックを渡さなかった場合
yield呼び出しを伴うメソッドでブロックが渡されなかった場合 no block given(yield)(LocalJumpError)
のようなエラーが発生する。
ブロックを省略可能にする
ブロックの引数
yield
命令に渡した値がそのままブロックの引数(パラメーター)になる。
def walk(list)
for item in list
yield item
end
end
data = [1, 3, 5]
walk(data) do |item|
puts item
end
10章
例外処理
すべての例外クラスはExceptionを基底クラスとしている。 ※アプリ固有のビジネスロジックに起因する問題に対しては、適切な例外クラスを用意しておくのが望ましい(もちろん標準例外で事足りるのであればそちらを優先すべき)
-
rescue節が呼び出される方式 発生した例外がrescue節に記述されたものと一致した場合、または発生した例外の基底クラスである場合
-
rescue節実行順序 複数のrescue節がある場合には、記述が先にあるものが優先される。 最初は下位の例外クラスで捉え、より範囲を広げていくイメージで作成していく。
バックトレース情報に関して 例外が発生するまでに経てきたメソッドの一覧(スタックトレースともいう) エントリーポイント(トップレベル)から呼び出し順に記録される(エラー文は下からentrypointとなる) ※一般的にはバックトレースの末尾を確認することで例外の直接原因を特定できる。
-
ensure節 finalと同一。
-
raise 例外を発生させる
raise [exp], [message]