D IT Y

タマキ工務店のIT日記

チェリー本輪読会 第6週目まとめ

f:id:shirotamaki:20210619091936p:plain

🍒 はじめに

チェリー本輪読会の第6週目のエントリーになります。

輪読会の概要については第1週目にまとめています。

🍒 輪読会 第6週目まとめ

第4章4.9.1〜第5章5.3.2まで

期間:2021年06月28日〜2021年07月02日

さまざまな繰り返し処理

Rubyには、同じことを繰り返す方法がいくつかあります。

timesメソッド

繰り返しの回数が決まっているときはtimesメソッドがおすすめです。

timesメソッドは、イテレータとも呼ばれます。イテレータ「繰り返す(iterate) + もの(-or)」という意味です。Ruby 用語としては、もっぱら繰り返し処理のためのブロック付きメソッドのことを指します。

Integer#times (Ruby 3.0.0 リファレンスマニュアル)

Ruby 用語としては、もっぱら繰り返し処理のためのブロック付きメソッドのことを指す。

uptoメソッド、downtoメソッド

Integer#upto (Ruby 3.0.0 リファレンスマニュアル)

Integer#downto (Ruby 3.0.0 リファレンスマニュアル)

stepメソッド

開始値.step(上限値, 1度に増減する大きさ)

Numericとは「数、数的な、数に関するの意」

Numeric#step (Ruby 3.0.0 リファレンスマニュアル)

while文

while文は指定した条件が「真」である間、処理を繰り返します。

while 条件式 (真であれば実行)
    繰り返したい処理
end

until文

while文の反対で、条件が「偽」である間、処理を繰り返します。

until 条件式 (偽であれば実行)
    繰り返したい処理
end

for文

eachメソッド、mapメソッドで代用できるためほとんど出番のない構文です。

普段、輪読会メンバーもfor文を使っている人はいませんでした。

for文はメソッドではありません。Rubyの書き方のひとつです。

for 変数 in  配列やハッシュ
    繰り返し処理
end

loopメソッド

無限ループを作りたいときは、loopメソッドが使えます。

loop do
    無限ループ用の処理
end

例えば、puts foo と記述すると、無限に'foo'がputsされ続け大変なことになります。

そんな時、繰り返し処理を途中で抜ける方法があります。

  • break  繰り返し処理を中断し、繰り返しの中から抜けることができる
  • next  繰り返し処理を中断し、次の回の繰り返し処理へ移動することできる
  • return  繰り返し処理を中断し、メソッドから抜け出すことができる

逆に、繰り返し処理をやり直したい場合は以下を使います。

  • redo  同じ条件で繰り返し処理をやり直す

繰り返し処理用の制御構造

繰り返し処理の途中で、処理を中断したり、次の回に飛ばしたり処理を制御したいときがあります。そのような処理を制御するための構造がRubyでは用意されています。以下のキーワードで処理を制御することが可能です。

break

  • breakを使ってloop処理を抜けます。
    • 下記は、 変数mfujiwaraと同一になった場合、breakさせます。(繰り返し処理を脱出します)
    • 下記の例では、loopメソッドを使っていますが、for文やeachメソッドなど他の繰り返し記法でも利用できます。
irb(main):073:1* def choose_members
irb(main):074:1* members = ['fujiwara', 'masukawa', 'naoi', 'masu']
irb(main):075:2*   loop do
irb(main):076:2*   m = members.sample
irb(main):077:2*   puts m
irb(main):078:2*   break if m == 'fujiwara'
irb(main):079:1*   end
irb(main):080:1*   puts 'I am a composer!!'
irb(main):081:0> end
=> :choose_members
irb(main):082:0> choose_members
masukawa
naoi
masukawa
fujiwara
I am a composer!!
=> nil

next

  • nextを使って次の処理へ移動してみます。
    • next if m == 'fujiwara' がtrueとなった場合、次の繰り返し処理へ移動します。
irb(main):031:1* def check_main_songwriter
irb(main):032:2*   ['fujiwara', 'masukawa', 'naoi', 'masu'].each do |m|
irb(main):033:2*     next if m == 'fujiwara'
irb(main):034:2*     puts "#{m}さんは、違います"
irb(main):035:1*   end
irb(main):036:2*   ['作詞', '作曲'].each do |n|
irb(main):037:2*     puts "fujiwaraさんは、#{n}します"
irb(main):038:1*   end
irb(main):039:0> end
=> :check_main_songwriter
irb(main):040:0> check_main_songwriter
masukawaさんは、違います
naoiさんは、違います
masuさんは、違います
fujiwaraさんは、作詞します
fujiwaraさんは、作曲します
=> ["作詞", "作曲"]

breakとreturnの違い

breakは、上記の例で取り上げたように「繰り返し処理からの脱出」を行うために利用する記法です。

returnは、「メソッドからの脱出」を行うために利用されます。メソッドの実行を終了するとも言い換えられます。

  • returnを使ってメソッドから脱出させます。
    • 下記は、 変数mfujiwaraと同一になった場合、returnさせます。(メソッドを脱出します)
    • 下記の例では、loopメソッドを使っていますが、for文やeachメソッドなど他の繰り返し記法でも利用できます。
    • return if m == 'fujiwara' がtrueになった場合、メソッドから脱出します。メソッド内で記述しているputs 'I am a composer!!' は、実行されません。
irb(main):083:1* def choose_members
irb(main):084:1* members = ['fujiwara', 'masukawa', 'naoi', 'masu']
irb(main):085:2*   loop do
irb(main):086:2*   m = members.sample
irb(main):087:2*   puts m
irb(main):088:2*   return if m == 'fujiwara'
irb(main):089:1*   end
irb(main):090:1*   puts 'I am a composer!!'
irb(main):091:0> end
=> :choose_members
irb(main):092:0> choose_members
masukawa
masukawa
naoi
masu
fujiwara
=> nil

throw と catch を使った大域脱出

breakでは、繰り返し処理を中断し、一番内側の処理しか脱出できませんが、throwcatchを使えば、一気に外側のループまで脱出できます。(returnのようにメソッドの脱出ではありません。あくまでもループ全体の脱出になります)

:bumpがタグ文字といってcatchとthrowの後に記述します。同じタグ文字にする必要があります。

irb(main):095:0> records = [ 'LAMP', 'ダイヤモンド', '天体観測' ]
=> ["LAMP", "ダイヤモンド", "天体観測"]
irb(main):096:0> release = [1, 2, 3]
=> [1, 2, 3]
irb(main):097:1* catch :bump do
irb(main):098:2* records.shuffle.each do |record|
irb(main):099:3* release.shuffle.each do |n|
irb(main):100:3* puts "#{record}は、#{n}枚目のシングルです}"
irb(main):101:4* if record == '天体観測' && n == 3
irb(main):102:4* throw :bump
irb(main):103:3* end
irb(main):104:2* end
irb(main):105:1* end
irb(main):106:0> end
ダイヤモンドは、1枚目のシングルです}
ダイヤモンドは、2枚目のシングルです}
ダイヤモンドは、3枚目のシングルです}
LAMPは、3枚目のシングルです}
LAMPは、2枚目のシングルです}
LAMPは、1枚目のシングルです}
天体観測は、2枚目のシングルです}
天体観測は、1枚目のシングルです}
天体観測は、3枚目のシングルです}
*=> nil*

ハッシュ

ハッシュは、「キー」と「値」のセットでデータを管理するオブジェクトのことです。

他の言語では「連想配列」「辞書」「マップ」と呼ばれたりします。

英語のHashは、コマ切れ肉と野菜を炒めた料理の事を指し、ハッシュドビーフの語源でもあります。

ハッシュの3つの書き方

ハッシュロケットを使った書き方。キーは文字列です。

{ 'first_single' => 'LAMP', 'second_sigle' => 'ダイヤモンド', 'third_single' => '天体観測' }

ハッシュロケットを使った書き方。キーはシンボルです。

{ :first_single => 'LAMP', :second_sigle => 'ダイヤモンド', :third_single => '天体観測' }

ハッシュロケットを省略した書き方。キーはシンボルですが、:コロンの位置が右側に変わります。

{ first_single: 'LAMP', second_sigle: 'ダイヤモンド', third_single: '天体観測' }

ちなみに、改行して書くこともできます。

{ 
'first_single' => 'LAMP',
'second_sigle' => 'ダイヤモンド',
'third_single' => '天体観測' 
}

シンボル

シンボルは任意の文字列と一対一に対応するオブジェクトです。Rubyがメソッドなどの名前を識別するためのラベルをオブジェクトにしたものです。先頭に: をつけて表現します。

文字列との違いは、主に4つあります。

  • クラスが違います。文字列はStringクラスです。シンボルはSymbolクラスです。
# 文字列
irb#1(main):014:0> 'BumpOfChicken'.class
=> String

# シンボル
irb#1(main):015:0> :BumpObChicken.class
=> Symbol
  • 同じシンボルは同じオブジェクトIDです。文字列は毎度オブジェクトIDが変わります。
# 文字列(毎回、違う)
irb#1(main):016:0> 'BumpOfChicken'.object_id
=> 260
irb#1(main):017:0> 'BumpOfChicken'.object_id
=> 280
irb#1(main):018:0> 'BumpOfChicken'.object_id
=> 300

# シンボル(毎回、同一になる)
irb#1(main):019:0> :BumpOfChicken.object_id
=> 2296228
irb#1(main):020:0> :BumpOfChicken.object_id
=> 2296228
irb#1(main):021:0> :BumpOfChicken.object_id
=> 2296228
  • シンボルは整数として扱われるため、文字列より高速に処理できます。
    • 同じシンボルであれば同じオブジェクトである理由で、シンボルの方がメモリ効率がよいです。
    • シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。整数として扱えることが高速に処理できる理由です。class Symbol (Ruby 3.0.0 リファレンスマニュアル)
  • シンボルはイミュータブル(非破壊的)なオブジェクトです。
    • 文字列はミュータブル(破壊的)なオブジェクトのため変更は可能ですが、シンボルはイミュータブルなため変更できません。勝手に変更されては困る名前などの用途に向いています。
# 文字列は変更が可能です。
irb(main):002:0> name = 'bump'
=> "bump"
irb(main):003:0> name.upcase!
=> "BUMP"

# シンボルは変更できません。
irb(main):004:0> name = :bump
=> :bump
irb(main):005:0> name.upcase!
(irb):5:in `<main>': undefined method `upcase!' for :bump:Symbol (NoMethodError)

irbの情報を確認

irb_info コマンドで、irbの情報を確認することができます。

shiro@shiro:~$ irb
irb(main):001:0> irb_info
=>
Ruby version: 3.0.0
IRB version: irb 1.3.6 (2021-06-19)
InputMethod: ReidlineInputMethod with Reline 0.2.6
RUBY_PLATFORM: x86_64-darwin19

irbで、行を挿入する方法

option + Enter で、実行中のirbに行を挿入することができます。

とても便利で頻繁に使っています。

GitHub内をアドバンスドサーチ

advanced search とは、高度検索と訳せます。複数の検索パラメータを組み合わせることによって、指定された範囲でより正確な結果を得ることのできる機能です。

Googleなどが有名ですが、GitHubにも存在することを教えてもらいました。

Google 検索オプション

メソッドの使い方、記法など、希望する条件を入力し検索することができます。

GitHub · Where software is built

コントリビュートチャンス

チェリー本を読み進めていたとき、ふと英単語の誤植が目に入ってきました。

139頁の真ん中あたりのサンプルコード内で、

本来numbersの綴りが正しいはずですが、nunmbersとなっていました。

nunmbersのループは脱出するが、fruitsのループは継続する

コントリビュートというと大げさではありますが、人生初めての誤植発見というのもあり、嬉しくてテンション上がりました。笑

その後、すぐにフィヨルドブートキャンプ内のバグ・誤字脱字の窓口へ報告を行いました。

なんと直接、著者の伊藤さんにご対応いただき、無事に技術評論社の正誤表へ反映いただきました。

gihyo.jp

スタンプ

そんなこともあり、輪読会メンバーの(id:yana_g)さんが「コントリビュートチャンス」スタンプを作ってくれました笑。こういった遊び心とても素敵ですね。

絵文字ジェネレーター - Slack 向け絵文字を無料で簡単生成

f:id:shirotamaki:20210722140250p:plain

参考書籍

🍒 まとめ

今週で6週目を終えました。

始めた当初は苦手意識のあった「irb」と「るりま」ですが、日々使用することで親しみが増し、今ではだいぶ仲良くなれたと思います。わからないことに出くわしたときは、すぐに「るりま」を参照する習慣が身につきました。また「irb」を使用し手元で動きを確認することも、今では自然と手がスッと動くようになり、身についてきたと思います。

輪読会を通して、この大きな2つの武器を手に入れられたことは大きな収穫です。

引き続き、この武器を活用し技術を磨いていきたいと思います。

では、また来週!(次回、第7週目)