🕌

RubySilver学習まとめ

に公開

現在、RubySilverの学習をしているので、ややこしい箇所をまとめていきます!

ヒアドキュメント

書き方 展開できるか? 本文中のスペースやタブを削除する 終了タグの前にインテンド入れられるか?
<<EOT × ×
<<'EOT' ×(''はエラーになる) × ×
<<"EOT" × ×
<<~EOT 自動で除去 ×
<<~'EOT' ×(''はエラーになる) 自動で除去 ×
<<-EOT × (これだけエラーにならない)
<<-'EOT' ×(''はエラーになる) × (これだけエラーにならない)

展開

#{} による式展開や、バックスラッシュ記法(\n など)を使って変数・式を展開できるかどうか。

# 展開 ○
name = "Ruby"
str = <<EOT
Hello, #{name}!
EOT
# => "Hello, Ruby!"

# 展開 ×
name = "Ruby"
str = <<'EOT'
Hello, #{name}!
EOT
# => "Hello, #{name}!"  # 置き換わらない

本文中のスペースやタブの自動削除

str = <<~EOT
    line1
    line2
EOT
# => "line1\nline2\n"  # 行頭のスペースが除去される

終了ラベル(例: EOT)を、行頭からインデントして書けるかどうか

str = <<-EOT
line1
line2
  EOT
# 終了ラベルの文頭にインテンド入っていてもOK

# これは動かない
def sample
  <<TXT
    Ruby
    Java
  TXT
end
p sample

終了ラベルの書き方

s = <<'EOF'
Hello,
Ruby
'EOF'
EOF

p s
# => "Hello,\nRuby\n'EOF'\n"

終了は EOFクォートなし!)のため、'EOF'クォート付き)は文字列内の一部になる。

短絡評価・演算子

演算子 意味 特徴(短絡評価)
|| または(OR) 左が true なら右は評価しない a || b => a
&& かつ(AND) 左が false なら右は評価しない a && b => b
- 差集合(配列演算) 配列 a から b の要素を除外 [1,2,3,4] - [4,5,6]
& 積集合(配列演算) 配列 ab の共通要素を抽出 [1,2,3,4] & [4,5,6]

上記表内の||部分について、半角で||と書くと表示されなくなってしまうため、わざと全角||で書いてます。

a = [1,2,3]
b = [4,5,6]
p a || b # => [1, 2, 3]
p a && b # => [4, 5, 6]
a = [1,2,3,4]
b = [4,5,6]

p a-b #=> [1, 2, 3]
p a & b #=> [4]

問題29

silver_j.mdより引用。

ary = []
ary << 1 && false
true || ary << 2
false && ary << 3
false || ary << 4
p ary

実行結果

[1, 4]
考え方

1. ary = []

空の配列を用意。

2. ary << 1 && false

評価順:

  • ary << 1 は配列に 1 を追加し、その戻り値は ary(truthy)
  • truthy && false → 結果は false
ary = [1]

3. true || ary << 2

評価順:

  • true || ... の時点で、|| の左が真なので右は評価されない(短絡評価)
  • ary << 2 は実行されない!
ary = [1](そのまま)

4. false && ary << 3

評価順:

  • false && ... → 左が偽なので右は評価されない(短絡評価)
  • ary << 3 実行されない!
ary = [1](変わらず)

5. false || ary << 4

評価順:

  • 左が false → 右を評価
  • ary << 4 実行 → 4 が配列に追加
ary = [1, 4]

6. p ary

[1, 4]

==, eql?, equal? の違い

メソッド 比較内容 ゆるさ
== 値が同じか(型が違ってもOK) ◎ ゆるい 1 == 1.0true
eql? 値が同じ&型も同じ ◯ やや厳しい 1.eql?(1.0)false
equal? 完全に同じオブジェクトか(同じID) ✕ 厳しい 1.equal?(1)true1.equal?(1.0)false
  1. ==(等価) ← 一番ゆるい
  2. eql?(厳密な等価)
  3. equal?(同一性) ← 一番きびしい
a = "hello"
b = 'hello'

p a == b        # => true・値が同じならOK
p a.eql?(b)     # => true・値と型の両方が一致する
p a.equal?(b)   # => false・同一オブジェクトか?
a = 1       # Integer
b = 1.0     # Float

p a == b       # => true・値が同じならOK
p a.eql?(b)    # => false・値と型の両方が一致する
p a.equal?(b)   # => false・同一オブジェクトか?
a1 == a2  # => true
a1.eql? a2 # => true
  • ==
    • 「中身(値)」が同じならtrueを返す
    • 文字列の場合、"abc" == "abc" → true
  • eql?
    • これも「値が同じかどうかを調べる。文字列同士で中身が同じならtrue
    • 数値などでは型も比較するけど、今回はどちらもStringなので同じ
    • ""(ダブルクォート)で囲んだ文字列も''(シングルクォート)で囲んだ文字列もどちらもStringクラスのインスタンス

Rubyでのハッシュ生成方法

書き方 使用可能なキー
h = { :key => "value" } 任意(シンボル、文字列など) { :name => "Alice" }
h = { key: "value" } シンボルのみ(Ruby 1.9以降) { name: "Alice" }
h = Hash.new 空のハッシュを作る h[:foo] = "bar"
h = Hash[:a, 1, :b, 2] ペアの列で初期化 { :a => 1, :b => 2 }
h = Hash[ [[:a, 1], [:b, 2]] ] ペアの配列から作る { :a => 1, :b => 2 }

エイリアスメソッド

map / collect

すべての要素に対して処理を行い、変換結果を新しい配列として返す。

p [1,1,2,3,5,8].map { |x| x*2 }
# => [2,2,4,6,10,16]
[1, 2, 3].map { |n| n * 2 }
# => [2, 4, 6]

select / find_all

条件に一致する要素だけを集めて返す配列フィルタ。

[1, 2, 3, 4].select { |n| n.even? }
# => [2, 4]

reject

select の逆で、条件に一致しない要素を返す。

[1, 2, 3, 4].reject { |n| n.even? }
# => [1, 3]

find / detect

ブロックの条件を満たす最初の1つの要素を返す。

[1, 2, 3, 4].find { |n| n.even? }
# => 2

参考文献

Discussion