【読書メモ】Ruby レシピブック 第2版 268の技 ①

# はじめに
復習も兼ねてのメモ書きです。
誤り等あればご指摘いただけると嬉しいです:bow:

## 第1賞 Rubyの文法

- 記法
    - `\`はwindowsでは`¥`に表記される
    - `\n`は改行、`\t`はタブを表す
    
- ヒアドキュメント
    - `<<`の式の次の行から`<<`の後ろに来る文字列が先頭に現れる行までを1つの文字列とする)
    - 例
    
```
<<“HEREDOC”
うひのおくやまけふこえて
HEREDOC
```

- 正規表現
    - `/ /`で囲む表記方法
        - パターン中に`/`を直接書けない。`\`でエスケープする必要がある。
            - 例：`http://www.ruby-lang.org/ja/`、`http://www.ruby-lang.org/en/`
            - 正規表現化：`http:\\www\.ruby-lang\.org/ja/`、`http:\\www\.ruby-lang\.org/en/`
            
- 配列リテラル
    - `[ ]`で囲む表記方法(`,`で区切られた値1つ1つが配列の要素)
        - 例：[1, 2, 3]
    - `%w`を使う表記方法（空白で区切られた値を文字列としたものが配列の要素）
        - 例：%w(a b c)
            - 式展開した場合

```
%W(a b #{1 + 1}) => [“a”, “b”, “c”}
```

- ハッシュリテラル（`{ }`を使う）
    - キーと値が1:1の関係になるようにする
    
- 単項演算子（変数や式の前に置かれる演算子）
    - 例：`!`var
        - 否定形：`!`、`not`、`~`（ビット反転）
        - プラス、マイナス符号 など
        
- 2項演算子（`1 + 2`のように2つのオブジェクトを左右に取る）

``` 
- `::`（クラス、モジュールなどをネストする）# 優先順位が高い
- or（論理和）                           # 優先順位が低い
```

- 条件演算子
    - `条件 ? 式1 : 式2`（下記のif文と同義）

```
if 条件 then
　式1
else
　式2
end
```

- 配列参照演算子（`var[0]`の配列などのオブジェクトにインデックスでアクセスする時に使われる）

- メソッドで定義できない演算子
    - `::`、`..,`、`…,`、`?`、`:`（条件演算子）、`not`、`and`、`or`、`!`、`&&`、`||`、`=`
    
- ローカル変数
    - メソッドやブロック、クラス定義文からのみ代入、参照できる。
    - 名前はアルファベット小文字または`_`で始まり、英数字と`_`で構成される
        - 例：1var
        
- インスタンス変数
    - 特定のオブジェクトだけに属し、そのオブジェクトのメソッド内からのみ代入、参照できる
    - 名前は`@`で始まり、英数字と`_`で構成される
        - 例：@!var
        
- クラス変数
    - 特定のクラスに所属し、クラスとサブクラス、およびそのインスタンスから代入、参照できる
    - 名前は`@@`で始まり、英数字と`_`で構成される
        - 例：@@cvar
        
- グローバル変数
    - プログラムのどこからでも代入、参照できる
    - 名前は`$`で始まり、英数字と`_`で構成される
        - 例：$gvar
        
- 擬似変数
    - 代入不可能。名前に使われる文字の種類がローカル変数と同じであるため、変数と呼ばれる
        - 例：`self`、`true`、`false`、`nil`、`__FILE__`、`__LINE__`
        
- 定数
    - 一度定義したら変更しない値を設定する
    - 名前はアルファベットの大文字から始まり、英数字と`_`で構成される
        - 例：Const
        
※ `;`で明示的に文を区切ることができる

```
hello(); world()
```

※ 文末に2項演算子がある場合や、メソッドの引数の途中で改行が入る場合、改行が文の区切りとして扱われなくなる

```
func1(“a”, “b”,
      “c”)         
=func1(“a”, “b”, “c”)
```

- 条件分岐（`if文`、`unless文`、`case文`）
    - `if`文、`unless`文
        - `false`と`nil`：偽
        - それ以外の値：真
            - if修飾子：`実行したい処理 if 条件`、`実行したい処理 unless 条件`
    - `case`文（比較する時に`===`演算子を使う）
	- case文とは　参考：https://www.javadrive.jp/ruby/if/index9.html

```
case #比較したい式 省略可能）
　when 値1 then
　　処理1
  when 値2 then
    処理2
  end
end
```

- `and`、`&&`：左辺に書いた部分が真であれば右辺を実行する
- `or`、`||`：左辺に書いた部分が偽である場合にのみ右辺を実行する

- 繰り返し
    - `while`（条件式が真の間くり返す）
    - `until`（条件式が偽の間繰り返す）

```
until 条件 do
　繰り返したい処理
end
```

- for（あらかじめ指定したオブジェクトから順に値を取り出しながら繰り返しを行う）

```
for 変数（num） in オブジェクト（1..3） do
　繰り返したい処理
end
```
※for文で指定できるオブジェクトは`each`メソッドを持ったオブジェクトでなければならない（配列やハッシュ、範囲オブジェクト など)
※繰り返したい処理が1行しかない場合：`繰り返したい処理 while（until）条件`

※ 1回目の条件分岐よりも前に繰り返しの中の処理を実行する場合

```
begin
　繰り返したい処理　　　   #繰り返し処理を1度実行
end while（until） 条件　 #条件によって再度実行判断
```

- `break`：繰り返しを強制的に終了
- `next`：次の繰り返しに進む
- `retry`：もう一度頭から繰り返す
- `redo`：同じ条件で繰り返しをやり直す

- メソッド呼び出し
    - 書き方：オブジェクト.メソッド名(メソッド引数)
    
- 引数では、配列を`*`で展開して渡せる

```
a = [1, 2, 3[
　obj.some(*a) 

#obj.some(1, 2, 3)
```

- メソッド呼び出しの対象になるオブジェクト：レシーバ
    - 例：`STDOUT（レシーバ）.puts`
    
- 関数的メソッド（レシーバ省略形式で呼ばれるメソッドのこと）
    - メソッド名(メソッド引数)
        - `self`がレシーバの役割を担う
        - 例：`puts(“ruby”) #RUBY`
        
- ブロックパラメータ（メソッド定義とブロック定義本体との間で情報をやり取りするために使われる）

```
オブジェクト.メソッド名 do |ブロックパラメータ|
　ブロック定義本体
end
```

```
オブジェクト.メソッド名 {|ブロックパラメータ|
　ブロック定義本体
}
```

```
オブジェクト.メソッド名(メソッド引数) do |ブロックパラメータ|
　ブロック定義本体
end
```

- メソッド定義

```
def メソッド名(引数リスト)
　メソッド定義
end
```

- 引数リスト（次の順番でのみ定義できる）
    - 詳細：Rubyの引数色々　https://qiita.com/rtoya/items/33617078501776fdcad7
        - `param`：通常の引数（0個以上）
        - `param = val`：デフォルト値付き引数（0個以上）
            - 引数にデフォルト値をもたせられる。
            - 実行時に引数を渡さなかった場合、デフォルト引数を用いて処理が行われる。
        - `*param`：可変長引数（0〜1個）
            - `*`をつければ引数を複数個設定できる。引数は配列として受け取られる。
        - `&param`：ブロックを`proc`化して受け取る引数（0〜１個）
            - ブロックとして記述された手続きを持ち運ぶためのクラス。ブロックをオブジェクト化したものがProc。
                - 参考
                - TECH::EXPERT【Ruby】Procクラス【67日目】https://note.mu/syojikishindoi/n/n4e4c25bc9e9a
                - to_proc http://ref.xaio.jp/ruby/classes/symbol/to_proc
                - [Ruby]Procオブジェクトについてhttps://qiita.com/nagata03/items/919b0457409cc755ff0f
                
- ブロック付きメソッドの定義
    - メソッドに渡されたブロックを実行するには`yield`を使う
        - `yield`は、与えられた引数をブロックパラメータとしてブロックに渡す
          
```
def map_with_index(list)
　result = [ ]
　　list.each_with_index{|item, idx|
　　　value = yield [item, idx]
　　result << value
   }
　return result
end

map_with_index([1, 2, 3]){|item,idx| item*idx } #=>[0, 2, 6]
```

- メソッドの呼び出し制限
    - `public`（メソッドを他のクラス定義やトップレベル`classやmoduleの中で定義していないメソッド`から呼び出せるようにする）
    - `private`（メソッドをレシーバの省略した形でしか呼び出せないようにする）
        - 例：`initialize`メソッド
    - `protected`（メソッドを同一クラスとサブクラスからしか呼び出せないようにする）
        - 参考：qs Developers 
        http://qs.nndo.jp/difference-between-private-and-protected-in-ruby

- class定義

```
class クラス名
　クラスの定義
end
```

※別のクラスを継承したクラス

```
class サブクラス名 < スーパークラス
　　クラスの定義
end
```		
※クラス名に`::`を使って深いネストクラスを直接指定可能（但し、ネストされる側のクラスは予め定義されている必要がある）

```
class C1
　　・
　　・
　　・
end

class C1::C2
　def foo
　　p “foo”
　end
end

C1::C2.new.foo #=> ”foo”
```

- `self`（クラス定義の中でクラスのオブジェクト自身を表す、モジュール定義の中でモジュールのオブジェクト自身を表す）
    - モジュールが他のクラスにインクルードされた場合、モジュールのメソッド定義の中にある`self`はそのクラスのオブジェクト自身を指す
    - クラスのインスタンスメソッド定義の中では、インスタンス自身を表す

```
class C1
　p [self, self.class] #=> [C1, Class] #オブジェクト
　def foo
  　p [self, self.class]
  end
end

C1.new.foo #=> C1 #インスタンス
```

- `module`定義
    - `module`文

```
module モジュール文
　モジュールの定義
end
```

- モジュールとクラスの違い
    - インクルード：クラス（できない）、モジュール（できる）
    - 継承：クラス（できる）、モジュール（できない）
    - インスタンス生成：クラス（できる）、モジュール（できない）

- モジュールのインクルード
    - include文

```
module M1
end

class C
　include M1 #クラスCにモジュールM1をインクルードする
end
```
※モジュールはクラスと同様、ネストできる。（クラスとモジュールを交ぜてのネストも可能）

```
module M1
　module M2
　　class C1
　　end
　end
end

c = M1::M2::C1.new
```

- 特異メソッド（個々のオブジェクトだけのメソッドを定義できる）

```
def オブジェクト.特異メソッド名(引数リスト)
　特異メソッド定義本体
end
```

- 複数の特異メソッドを一度に定義したい時

```
class << オブジェクト
　def 特異メソッド名(引数リスト)
　　特異メソッド本体
  end
end
```

-  `class << オブジェクト 〜 end 形式（特異クラス定義）`：特異クラス
    - 特異クラス定義の中で`self`を参照すると特異クラス自身にアクセスできる

- 例外処理（ファイルの読み書きに失敗した時などに例外が発生する）

```
begin
　主処理1
rescue 例外クラス1 => 変数1 then   #発生した例外が指定した例外クラス1かサブクラスの場合、例外処理1が実行される
　例外処理1                        #例外が発生するかもしれない処理　
rescue 例外クラス2 => 変数2 then   #（発生した例外が指定した例外クラス1またはサブクラスではない場合）例外クラス2と比較する
　例外処理2                                      
　　　・
　　　・
　　　・
rescue 例外クラスn => 変数n then   #上記の処理が繰り返される
　例外処理3
else
　主処理2                         #上記の例外が発生しなかった場合、主処理2が実行される
ensure
　主処理3                         #例外が発生してもしなくても、最後に必ず実行される
end
```	
    
- 例外クラスが省略された場合、`StandardError`が使われる（型指定なしで`rescue`すると、`StandardError`のサブクラスのみcatch する）
    - 参考
        - Rubyで独自例外を定義するときはStandardErrorを継承する　https://blog.toshimaru.net/ruby-standard-error/	
        - rubyの例外についてまとめてみた　https://qiita.com/kasei-san/items/75ad2bb384fdb7e05941
    
- rescue修飾子：`主処理 rescue 例外処理　# 主処理で例外が発生した時、例外処理を実行する。rescueする例外クラスは指定できない。`
   
- aliasとundef
- 別名をつける（Rubyのメソッドに別名がつけられる。aliasを使う。）

```        
alias 別名 元の名前
    - alias method_new method_old
    - alias :method_new :method_old #シンボルの指定も可能
```
    
- メソッドを使えないようにする（既に定義されているメソッドを使えないようにする。undefを使う。）

```
undef メソッド名
    - undef some_method
    - undef :some_method
```

- 予約語（変数名やメソッド名として使えない名前。変数の名前などに使おうとするとエラーになる）

```
BEGIN、END、alias、and、begin、defind?、def、class、case、break、do、else、elsif、end、ensure、module、in、if、for、false、next、nil、not、or、redo、rescue、retry、retuen、self、super、then、true、undef、unless、when、while、yield、__FILE__、__LINE__
```