[Ruby] 勉強メモ

## 背景
最近Ruby勉強し始めて、[AOJの Introduction to Programming I](http://judge.u-aizu.ac.jp/onlinejudge/topic.jsp?cid=2)を解きつつ覚えています。ただ解くだけではなく、使えるやり方をストックしておかないと中々向上しないなと思ったので、Qiitaをお借りしてメモ代わりにコードを置いておきます。
自分用メモなので分かりにくかったらすみません。誰かの役に立てばいいなくらいで公開しておきます。

#### コメントがあったので追記
筆者はPHPをかじったことあるため、無意識にPHPと比較して書いてる部分があると思います。

# Rubyメモ
* [公式ドキュメント](https://www.ruby-lang.org/ja/documentation/)
* [PHPとの違い](https://www.ruby-lang.org/ja/documentation/ruby-from-other-languages/to-ruby-from-php/)
* [逆引きリファレンス(めちゃ使える)](http://www.namaraii.com/rubytips/)

### 制御構造
[公式リファレンス](http://miyamae.github.io/rubydoc-ja/2.4.0/#!/doc/spec=2fcontrol.html)

#### if
```ruby
# 例
# thenは無くてもいい 
if age >= 12 then
  print "adult fee\n"
else
  print "child fee\n"
end
gender = if foo.gender == "male" then "male" else "female" end

# 文法
if 式 [then]
  式 ...
# else if ではダメ！
[elsif 式 [then]
  式 ... ]
...
[else
  式 ... ]
end

# 例
print "debug\n" if $DEBUG

# 文法
式 if 式
# 右辺の条件が成立する時に、左辺の式を評価してその結果を返します。 
# 条件が成立しなければ nil を返します。
```
#### while
```ruby
# 例
ary = [0,2,4,8,16,32,64,128,256,512,1024]
i = 0
while i < ary.length
  print ary[i]
  i += 1
end

# 文法
while 式 [do]
   ...
end
```
#### times（固定回数の繰り返し）
```ruby
# doは必要
5.times do
  puts "timesメソッドの確認です"
end
```
実行結果

``` bash
timesメソッドの確認です
timesメソッドの確認です
timesメソッドの確認です
timesメソッドの確認です
timesメソッドの確認です
```

#### for
```ruby
# 例
for i in 1..3 
  puts i
end

for i in [1, 2, 3]
  print i*2, "\n"
end

# 文法
for lhs ...  in 式 [do]
  式..
end

# 複数のイテレータ
for i,j in [[1,2], [3,4], [5,6]]
  p [i,j]
end
=> [1, 2]
   [3, 4]
   [5, 6]
```

#### foreach（.each）
```ruby
オブジェクト.each{|変数|
  実行する処理1
  実行する処理2
}

# 又は次のように記述することも出来ます。
オブジェクト.each do |変数|
  実行する処理1
  実行する処理2
end
```

#### case
* `break`がない
* `switch case` ではなく`case when`
* `default`ではなくelse

```ruby
case age
when 0 .. 2
  "baby"
when 3 .. 6
  "little child"
when 7 .. 12
  "child"
when 13 .. 18
  "youth"
else
  "adult"
end

# 条件式ではなく条件を書くので注意
# when 条件1, 条件2
#   式
# と書くことも可能

# when 節の最後の式に `*' を前置すればその式は配列展開されます。
ary = [1,2,3]
case v
when *ary
 ..
end
# は、以下と等価
case v
when 1, 2, 3
 ..
end
```

#### until

```ruby
# 例
until f.eof?
  print f.gets
end

# 文法
until 式 [do]
   ...
end
# 式を評価した値が真になるまで、本体を繰り返して実行します。
```

### 関数定義、クラス
※コメントを見て追記

厳密にはRubyに関数は存在しないです。PHPで言う関数と同じ使い方ができると思っていただければ幸いです。

``` ruby
# 関数定義
def name(a, b)
  print a + b
end

# クラス定義
class Greeter
  # コンストラクタ
  # @をつけるとプライベート変数になる
  # 厳密にはプライベート変数ではなくインスタンス変数と呼ぶ
  def initialize(name = "World")
    @name = name
  end
  def say_hi
    puts "Hi #{@name}"
  end
  def say_bye
    puts "Bye #{@name}, come back soon."
  end
end
greeter = Greeter.new("Pat")
greeter.say_hi

# 定数の参照は::を使う
pi = Math::PI
```

クラスの内容を追加したい場合、追加項目を定義しなおせばいい

``` ruby
class Greeter
  #アクセサの追加，セミコロンに注意！
  attr_accessor :name
end
```

---

### map
```ruby
# mapメソッドは、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。collectメソッドの別名です。
numbers = ["68", "65", "6C", "6C", "6F"]
p numbers.map {|item| item.to_i(16) }
# [104, 101, 108, 108, 111]

# map!メソッドはmapの破壊的メソッド
numbers = [104, 101, 108, 108, 111]
numbers.map! {|item| item.to_s(16) }
p numbers
# ["68", "65", "6c", "6c", "6f"]
```
ただし、`!`がついているからと言って破壊的であるとは限らない
[参考](https://qiita.com/tadsan/items/7baab2605a4d8ac1858e)

### #!usr/bin/env ruby って何
[Shebang(「シバン」や「シェバン」)というらしい](https://qiita.com/mohira/items/566ca75d704072bcb26f)

### 標準入力の受付
```ruby
# 文末に改行を含める
s = gets
# 文末に改行を含めない
s = gets.strip
# 型の変換
num = s.to_i
# 空白区切りで入ってくる
my_string = 'perl, python, java';
puts my_string.split(', ');
# => ["perl", "python", "java"]
```

### 文字の出力
```ruby
print "Hello World"
puts "Hello World" 
p "Hello World"
```

```bash
Hello WorldHello World
"Hello World"
```
* printは改行なし(ただしフォーマット指定可能)
* putsは改行あり
* pはデータ型を考慮して改行出力

```ruby
area = 1
round = 2
# #{変数}で展開できる
puts "#{area} #{round}"
# 1 2
```
### メソッドが使用できるのか確認(.respond_to?())
```ruby
# Say bye to everybody
def say_bye
  if @names.nil?
    puts "..."
  # joinメソッドを使用できるかどうか
  elsif @names.respond_to?("join")
    # Join the list elements with commas
    puts "Goodbye #{@names.join(", ")}.  Come back soon!"
  else
    puts "Goodbye #{@names}.  Come back soon!"
  end
end
```

### if `__FILE__` == $0
`__FILE__` は現在のファイル名を返す特別な変数です。 $0はプログラムを実行するときに使われるファイル名です。
このチェックは、「もしこれがメインファイルとして実行されているならば……」 という意味になります。
これは、ライブラリとして使われる場合には実行されないけれど、 実行ファイルとして使われる場合には実行されるコードを書くために使われます。

### rubyのインクリメント演算子
[Ruby にインクリメント演算子のようなものが無い理由](http://blog.tokoyax.com/entry/ruby/increment)

```ruby
# rubyではi++, i--は動作しない
# 代わりにi+=1, i-=1を使う
i+=1

```

### 文字列→配列
```ruby
#引数を変えると区切り文字を変更可能
# ""を指定すると1文字区切りにできる
s = "hello"
p s.split("")
#["h", "e", "l", "l", "o"]
```

１文字ずつ処理する場合は以下のようにも書ける

```ruby
s = "hello"
# s.each_char でも可
s.chars {|ch| print ch + "_" }
# h_e_l_l_o_
```