ログ

学習の記録

チェリー本4章 学んだこと

・スコープ ・メソッド内での変数はメソッド内でしか使えない、呼び出せない

num = 1

def hoge
  str = 'a'
end

puts num => 1
puts str => #エラー

・ブロック内もブロック外(ローカル変数)も同じ変数名が使える(使うのは好ましくない)
もし同じ名前の変数があればブロック内ではローカル変数よりもブロック内の変数が優先される

num = 1

def hoge
  num = 2
  puts num
end

puts num #=>1
hoge #=>2

・ブロックは、1行でかけるコードでは{}、複数行はdo...end

nums = [1,2,3,4,5]

# 中身は1行
nums.each {|n| n * 2}

# 複数行 
nums.each do |n|
  str = '数字は'
  after_num << n * 2
end

・concatは破壊的(危険)、"+"で配列合体は非破壊的

nums = [1,2,3,4,5]
str = ['a','b','c']

nums.concat(str)
#=> [1, 2, 3, 4, 5, "a", "b", "c"]
nums # 破壊的
#=> [1, 2, 3, 4, 5, "a", "b", "c"]
nums = [1,2,3,4,5]
str = ['a','b','c']

nums + str
=> [1, 2, 3, 4, 5, "a", "b", "c"]
nums # 非破壊的
=> [1, 2, 3, 4, 5]
str # 非破壊的
=> ["a", "b", "c"]

・可変長引数は該当部分は配列化、が結構便利そう
(splat演算子)を配列の入った変数の前に置くと展開する(配列を解除して中身だけ出すみたいな)(配列の配列状態を回避できる)
nums = [[1,2],[3,4]] *nums # [1,2,3,4]を期待したが、シンタックスエラー
Array#flattenで良いのでは?と思い調べました。
*(splat演算子)は配列同士の連結のリファクタリングの際に使えそう 可変長引数と配列解除と覚える

  nums = [3,4]
  [1,2]+ nums +[5,6] #=> [1, 2, 3, 4, 5, 6]
  nums = [3,4]
  [1,2,*nums,5,6] #=> [1, 2, 3, 4, 5, 6]

(&:to_i)などの(&:)の条件が知れた
・ブロックパラメータが1個
・ブロックの中で呼び出すメソッドに引数がない
・ブロックの中で、ブロックパラメータに対してメソッドを1回呼び出す以外の処理がない

・Rangeに対して.to_aで配列化、一つ一つの要素にできる (1..10).to_a #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] #()がないとエラー

・Array.newにブロックを渡すと引数の要素にindexの値が入る

Array.new(10){|n| puts n}
0
1
2
3
4
5
6
7
8
9
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]

配列にデフォルト値を渡す場合、破壊的変更をすると全ての要素に影響が出る。(参照の関係)これを回避するためにはデフォルト値をブロックで渡す

・繰り返し処理(eachとか)のメソッドの大半はブロックなしで呼び出すとEnumeratorオブジェクトを返す、よってEnumeratorクラスのメソッドが使える(だからwith_indexメソッドが呼び出せる)

nums = [1,2,3,4,5,6,7,8,9,10]
nums.delete_if.with_index do |n, i| 
  n.modulo(2) == 0 && i.odd?
end

・2次元、3次元配列は()でいい感じにできる

(hoge,huga),hoge_hoge = [[1,2],3]

()や( , )を使うことで要素を抽出して変数に入れたりできる(ややこいのは変わりない)

・{}.hgoehogeのようにブロックの後にメソッドチェーンが使える

・配列は加工できるものと思う

・breakはeach、while,until,for文で使える

・breakは繰り返し処理からの脱却、returnはメソッドからの脱却
returnはメソッドで使う(使わない方が好ましい)

組み込みメソッド

delete_if

each_with_index

with_index(mapと組み合わせたりしていろんな条件に対応)

Enumerator#with_index(mapなどで加工しつつ、添え字も取得できる、引数を渡せば添え字の開始を0じゃなく任意の数字にできる)

テストの書き方、考え方

  1. テストファイルを作る、実行ファイルを作る
  2. テストメソッド作る、絶対通りそうなテストを書くor期待するテストを書く、テストを走らせる、テストが通らないことを確認する
  3. 実行ファイルにメソッド作る、メソッドに絶対テストが通りそうな仮実装のコードを書く(テストに書いた期待する結果やtrue)、テストを実行する、テストが通ることを確認する
  4. テストが通ったことを確認したら、テストファイルに意味あるテストコードを書いてなかったら書く(要件に合うテスト)、テストが通ることを確認する
  5. 別のテストパターンを書く
  6. テスト実行、失敗を確認する
  7. テストが通るように実行ファイルにコードを書く(とりあえず動くもの)
  8. テストが通ることを確認する
  9. ここまでテストが書けて、要件を満たすコードが書けたらリファクタリングできるか考える(より綺麗なコード)
  10. テストが通ったらさらにリファクタリングできるか考える(組み込みメソッドでさらに簡潔にできるか、多重代入は使えないか )

感想

本を読み進める前に、自分でどうやったら実装できるか考えてコードを書いてみました。
相変わらず一つの方法しか考えないこと、これでいけるっしょと深く考えないところは改善しないとと感じますが、概ね参考書に近いコードが書けました。
自作メソッドの作り方やテスト駆動をチュートリアル形式で取り組めました。
上級編のリファクタリングは自分にはまだまだできないなーと思いつつコードがすごく簡潔になりびっくりしました。
簡単と感じてもまずは動かしてみる、使い方に慣れていこうと思います。
あとブログの書き方下手だから上手くなりたい・・
一つのテーマで深掘りできそうなことがあればそれで1記事書いてみたいと思います。

https://qiita.com/wasu/items/7aeb6d32fcf51cf04a57

参考、引用: 著者 伊藤淳一 さん「プロを目指す人のためのRuby入門<改訂2版>」 出版社 技術評論社 (2021/11/29) 4章P102~P166