- 🍒 はじめに
- 🍒 輪読会 第2週目まとめ
- 第2章2.9.1〜第3章3.4まで
- ビット演算
- 数値クラス(Numeric)
- Rubyの式の評価基準
- 演算子の優先順位
- if文と反対の意味で使えるunless文
- 複数の条件を指定する時に便利なcase文
- 三項演算子
- 角谷さんにレビューしてもらった話
- odd と even の覚え方
- メソッド定義はメソッド名の symbol が返り値になる
- エイリアスメソッド alias method
- require、require_relative、loadの使い分け
- putsメソッド、printメソッド、pメソッド
- Minitestを使うためにはrequireが必要
- Minitestで使用する主要な3つのメソッド
- refureメソッドとassert_notメソッドの違い
- irb
- 参考書籍
- 🍒 まとめ
🍒 はじめに
チェリー本輪読会の第2週目のエントリーになります。
第1週目のエントリーはこちら
輪読会の概要については第1週目にまとめています。
🍒 輪読会 第2週目まとめ
第2章2.9.1〜第3章3.4まで
期間:2021年05月31日〜2021年06月04日
ビット演算
- ビット
- ビットは、コンピュータの世界における「0か1が入る箱」(1bit)のことを指しています。コンピュータが処理する最小単位です。ちなみに、この箱の数が8個集まるとbyteバイト(8bit = 1byte)となります。ビット - Wikipedia
- ビット演算
- ビット(0か1)に着目して、その
ON/ OFF
を操作すること。これをビット演算と言います。
- ビット(0か1)に着目して、その
- ビット演算子
以下、ビット演算を使い2進数の数字を演算してみます。
0b
は、数値の頭につけると2進数の表記になります。返り値は10進数です。
(8進数は、0
、16進数は0x
です)
以下は、10進数の4649
を、頭に0b
と付けることで2進数で表現しています。
irb(main):031:0> 0b1001000101001 => 4649
.to_s(2)
とすることで、結果を2進数で確認できるようにしています。
irb(main):018:0> (0b1111).to_s(2) => "1111"
&
ビット積
2つを比較して、どちらも1なら1、どちらか片方が0の場合は0を返します。
irb(main):019:0> (0b1111 & 0b1010).to_s(2) => "1010"
|
ビット和
2つを比較して、どちらかが1なら1、どちらも0の場合は0を返します。
irb(main):001:0> (0b1111 | 0b1010).to_s(2) => "1111" irb(main):002:0> (0b1110 | 0b1010).to_s(2) => "1110"
^
排他的論理和
2つを比較して、どちか片方だけ1なら1、どちらも0またはどちらも1の場合は0を返します。
irb(main):025:0> (0b1010 ^ 0b00110).to_s(2) => "1100"
>>
右ビットシフト
スイッチのON/OFFの状態を、右に1個ずらします。
irb(main):039:0> (0b1100 >> 0b1).to_s(2) => "110" irb(main):040:0> (0b1100 >> 0b10).to_s(2) => "11"
<<
左ビットシフト
スイッチのON/OFFの状態を、左に1個ずらします。
irb(main):028:0> (0b1000 << 0b1).to_s(2) => "10000" irb(main):029:0> (0b1000 << 0b10).to_s(2) => "100000"
数値クラス(Numeric)
複素数がよくwakaran状態だったので深堀りしてみました。
実数
real number(実際に存在する数)虚数
imaginary number(想像上の数)複素数
(complex number 複合、混合)実数
+虚数
の組み合わせを複素数
といいます。
有理数
は整数および分数のことを指します。無理数
は分数で表せない √2、π(円周率)などを指します。
これ以上深追いすると沼から抜け出せそうにないのでこのへんで切り上げたいと思います。 データサイエンス難しい…!
ちなみに最近読んでいる本をご紹介。数学的な考え方が勉強になりました
Rubyの式の評価基準
大原則、Rubyでは「左辺から順番に式を評価」していきます。
&&
の戻り値と評価を終了するタイミング
左から評価された式は、式全体の真
または偽
が確定すると終了になります。
全部、真
の場合は最後に評価された値が返ります。以下のGeoge
が返ってきてる例です。
今回の例は文字列を&&
で比較していますが、文字列の内容は関係ありません。文字列であれば真の評価となります。
irb(main):056:0> "Paul" && "Paul" && "Paul" => "Paul" irb(main):057:0> "Paul" && "Ringo" && "Jhon" && "George" => "George"
false
と、nil
が存在する場合は、そこで式の評価が終了となり、false、nilが返ってきます。
irb(main):058:0> "Paul" && nil && "Paul" => nil irb(main):059:0> "Paul" && false && "Paul" => false
||
の戻り値と評価を終了するタイミング
||
を使う場合も同じルールに沿って評価されますが、||
は「またはor」と訳せるので演算子の違いによる戻り値の変化に注意が必要です。以下は、Paul
またはRing
となりますが、'Paul' の時点で真
と評価されるのでPaul
が返ります。
irb(main):074:0> "Paul" || "Ringo" => "Paul"
以下は、false
、nil
が左辺にありますが、Ringo
を評価した時点で真
なら全体も真
になるので、最初のRingo
が返ってきています。
irb(main):078:0> nil || "Ringo" || "Jhon" => "Ringo" irb(main):079:0> false || "Ringo" || "Jhon" => "Ringo"
演算子の優先順位
普段、優先順位を気にすることが少ない演算子。
and
やor
は条件分岐ではあまり使われないようです。用途としては制御フロー(コンピュータプログラムで、命令が実行される流れを定めたもの)に 向いています。
高い ! && || not and or 低い
if文と反対の意味で使えるunless文
条件が偽になった場合に処理を実行する条件分岐です。
まずは、普通のif文で表現してみます。!=
は、値が違えばOKと判断されます。
irb(main):085:0> shot_count = 9 => 9 irb(main):086:1* if shot_count != 10 irb(main):087:1* puts "ざんねん!" irb(main):088:1* else irb(main):089:1* puts "ストライク!" irb(main):090:0> end ざんねん! => nil
次は、unless文を使って書き換えてみます。
irb(main):117:0> shot_count = 7 => 7 irb(main):118:1* unless shot_count == 10 irb(main):119:1* puts "ざんねん!" irb(main):120:1* else irb(main):121:1* puts "ストライク!" irb(main):122:0> end ざんねん! => nil
複数の条件を指定する時に便利なcase文
elsif
でも表現できますが、「比較したいオブジェクトや式」があり、そこを基準に「場合分け」したい場合に使うとシンプルに書けます。
case 比較したいオブジェクトや式 when 値1 値1に一致する場合の処理 when 値2 値2に一致する場合の処理 else どれにも一致しない場合の処理 end
まずは、elsifを使ったパターン。
irb(main):012:0> name = 'Paul' => "Paul" irb(main):013:1* if name === 'Ringo' irb(main):014:1* "I play the drums!" irb(main):015:1* elsif name == 'Paul' irb(main):016:1* "I play the bass guitar!" irb(main):017:1* else irb(main):018:1* "I play the guitar!" irb(main):019:0> end => "I play the bass guitar!"
case文を使い書き換えてみます。
case name が基準となり、nameがtrueを返したら実行されます。elsifを使ったパターンと比べても可読性がよくシンプルに書くことができます。
irb(main):020:0> name = 'Paul' => "Paul" irb(main):021:1* case name irb(main):022:1* when 'Ringo' irb(main):023:1* "I play the drums!" irb(main):024:1* when 'Paul' irb(main):025:1* "I play the bass guitar!" irb(main):026:1* else irb(main):027:1* "I play the guitar!" irb(main):028:0> end => "I play the bass guitar!"
三項演算子
コードレビューを何度か受けて使えるようになり、今は普段から意識して使っている三項演算子。
コードを短く書くことができるので、何となくイケてる感じがだせるので好きです笑。輪読会でも一行でバシッと書けてカッコいい!という意見が多かった人気の書き方です。
とはいえ、何でもかんでも使えばいいものではないようで、可読性には注意する必要があります。
- 公式
式 ? 真だった場合の処理 : 偽だった場合の処理
当時、コードレビューで指摘を受けたコードを取り上げたいと思います。
まずは、自分で考えて書いたベーシックなif文のプログラムです。
if options["y"] year = options["y"].to_i else year = Date.today.year end
上記のif文を三項演算子で書き換えてみます。スッキリ!
year = options["y"] ? options["y"].to_i : Date.today.year
角谷さんにレビューしてもらった話
少し前の出来事ですが、三項演算子 ternary operatorについてもうひとつ。
TwitterでBadコードと、Goodコードをツイートしたところ、 なんと、角谷さんにレビューしていだきました!
Badコードの例
#bad code
— tamaki (@tamaki460) 2021年2月21日
shots = []
scores.each do |s|
shots << if s == 'X'
10
else
https://t.co/HpqT2cLbxk_i
end
end
自分なにり考えてみたGoodコードの例
# good code(ternary operator)
— tamaki (@tamaki460) 2021年2月21日
# equation ? What to do when it's true : What to do when it's false
scores.each { |s| shots << ( s == 'X' ? 10 : https://t.co/HpqT2ctA8K_i ) }
角谷さんにレビューいただいたGreatコードの例
you can remove the empty array assignment : `shots = https://t.co/IBEr89QD2S{|s| s == 'X' ? 10 : https://t.co/ajWlLA1QN9_i }`
— Kakutani Shintaro (@kakutani) 2021年2月21日
odd と even の覚え方
odd(奇数)even(偶数)をいつも取り違えてしまう問題...
覚え方について輪読会で質問してみました(輪読会はこういった小さな疑問も気軽に聞けるのがいいですね) みんなの覚え方を聞いて面白く参考になりました。
- oddは3文字なので奇数。evenは4文字なので偶数。
- デヴィット・ボウイ(odd eyes、Space Oddity)
これまた完全な余談ですが、デヴィット・ボウイの名前を聞くとなぜか曲より先に思い出してしまう戦場のメリークリスマス。「メリークリスマス、ミスターローレンス!」声に出して言いたくなる名台詞です。
メソッド定義はメソッド名の symbol が返り値になる
メソッドを定義すると返ってくる、:foo
気になって調べたところ、メソッド名のシンボルでした。
irb(main):017:1* def foo irb(main):018:1* end => :foo
エイリアスメソッド alias method
メソッドの別名のことです
るりまにも書いてありましたが、最初はまったくわかっていませんでした(気づきませんでした)。
自分でエイリアスメソッドを定義することも可能です。
String#length (Ruby 3.0.0 リファレンスマニュアル)
aliasという英単語、プログラミング学習を始めてから初めて知った言葉のひとつだけど、「偽名」という意味で使うことを今日犯罪ドキュメンタリーを見ていて知った。
トミーさん(id:eatplaynap329)が取り上げていたエイリアスの補足情報!なるほど〜おもしろい!
require、require_relative、loadの使い分け
requireは、「re(再び)quire(求める)〜を必要とする、要求する」の意味があります。
標準ライブラリやgem(外部ライブラリ)は、事前にライブラリを読み込まないと使えません。
ライブラリを読み込む際には、ファイルへrequire 'ライブラリ名'
と書きます。
まずは、require
、require_relative
の使い分けについてです。
結論としては、ライブラリやgemをrequireするときはrequire
を使い、自前で書いたコードを読み込むときはrequire_relative
が望ましいようです。
require
は、自分が今実行しているディレクトリ(カレントディレクトリ)が基点になります。
require_relative
は、自分のファイルパスが起点として、読み込むファイルを指定できます。
Kernel#require (Ruby 3.0.0 リファレンスマニュアル)
- ディレクトリの構造
$ tree /rindokukai └── /ruby-book ├── /lib │ └── rgb.rb └── /test └── rgb_test.rb
require
自分が今いるディレクトリが基点になります。
下記の例では相対パスを記述しています。実行しているパスが基点になりますので、下記で記述しているパスの意味は、ruby-bookの一段上のディレクトリを基点(つまり/rindokukai
ディレクトリに今いるという事)としてrequire
する。と表しています。例えば、/libディレクトリに移動してテストを実行しすると、エラーが表示されます。
require 'minitest/autorun' require './ruby-book/lib/rgb'
または、相対パスではなく、絶対パスを記述することでrequire
することもできます。
絶対パスを記述すれば、自分が今いるディレクトリは関係ないので予測しづらいエラーを回避できます。
require 'minitest/autorun' require '/Users/shiro/rindokukai/ruby-book/lib/rgb'
require_relative
現在のrgb_test.rbファイルを基点として指定します。下記はrgb_test.rbファイルにに記述してあります。自分のファイルパスが起点となりますので、自作のプログラムではrequire_relative
が推奨されています。
require 'minitest/autorun' require_relative '../lib/rgb'
load
無条件に毎回読み込みが行なわれます。逆にrequire
は一度しか読み込まれません。一般的に、load
は設定などのファイルを読みこませることが主な用途のようです。load
は絶対パスの指定が必要になります。
putsメソッド、printメソッド、pメソッド
こちも似たようなメソッドの代表格になります。
ひとつずつ見ていきたいと思います。
- putsメソッド
- 出力後に改行される
- 要素ごとに改行される
- 配列をputsすると各要素が改行されて出力される
- 呼び出すメソッドは
to_s
(Stringを返す) - 戻り値はnil
irb(main):044:0* a = 1 => 1 irb(main):045:0> puts a 1 => nil irb(main):046:0> a.class => Integer irb(main):029:0> puts [1,2,3] 1 2 3 => nil
- printメソッド
- 出力後に改行されない
- 呼び出すメソッドは
to_s
(Stringを返す) - 戻り値はnil
irb(main):042:0> print [1,2,3] [1, 2, 3]=> nil irb(main):043:0> print 123 123=> nil
- pメソッド
- 出力後に改行される
- 呼び出すメソッドは
inspect
メソッドObject#inspect (Ruby 3.0.0 リファレンスマニュアル) - 戻り値は引数のオブジェクト
- \nや\tなどのエスケープ文字もそのまま出力する
- 主にデバッグで使用される。開発者用。
irb(main):047:0> p [1,2,3] [1, 2, 3] => [1, 2, 3] irb(main):067:0> p "123\nabc\t" "123\nabc\t" => "123\nabc\t"
Minitestを使うためにはrequireが必要
Minitestとは、テストを自動化するためのテスティングフレームワークです。
library minitest/unit (Ruby 1.9.3)
Rubyには最初からインストールされています。
しかし使用するためには、`require 'minitest/autorun' と書き、ライブラリを事前に読み込む必要があります。
また、classに継承するためにはMinitest::Test
と書く必要があります。(クラスの継承)
require 'minitest/autorun' class MusicTest < Minitest::Test def test_music asser_equal 'BEATLES', 'beatles'.upcase end end
Minitestで使用する主要な3つのメソッド
以下の検証メソッドを使います。他にもたくさんメソッドが容易されているようですが、チェリー本では以下3つだけが使用されています。まずはこの3つを使いこなせるようにしたいと思います。
assert_equal b, a
aがbと等しい場合はパスする。assert a
aが真であればパスする。refute a
aが偽であればパスする。
assert は「結びつける、〜ということを断言する」の意。
refute は、「〜の誤りを証明する」の意
assertion (アサーション)とは、オブジェクトや式を評価して、期待された結果が得られるかどうかをチェックするコードのことです。
refureメソッドとassert_notメソッドの違い
上記のrefute
メソッドと似たassert_not
メソッドなるものが存在します。
輪読会で上記の疑問が持ち上がり、卒業生の(id:masuyama13)さんのブログを参考にさせていだきました。
Ruby refute と assert_not の違いを調査 - No Solution for Life
irb
irb は Interactive Ruby の略です。interactive(双方向、対話式) irb を使うと、Ruby の式を標準入力から簡単に入力・実行することができます。
library irb (Ruby 3.0.0 リファレンスマニュアル)
普段からirbを使い実際の動きを確認するようにしていますが、今までちゃんと活用できていないことを痛感しました。その中でもirbを起動する場所(カレントディレクトリ)が影響することについては、まったく知りませんでした。どこで起動しても同じものだと思っていました。
こういった普段何気なく使っているツール等についても、輪読会を通してinteractiveに学習することで、気付きがあり学ぶことができています。
参考書籍
- 伊藤淳一 著/『プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで』/技術評論社/2017年https://gihyo.jp/book/2017/978-4-7741-9397-7
- 五十嵐邦明,松岡浩平 著/『ゼロからわかる Ruby 超入門』/技術評論社/2018年https://gihyo.jp/book/2018/978-4-297-10123-7
- 高橋征義、後藤裕蔵 著/『たのしいRuby第6版』/SBクリエイティブ/2019年https://tanoshiiruby.github.io/6/index.html
- プログラミング言語 Ruby リファレンスマニュアル https://docs.ruby-lang.org/ja/
🍒 まとめ
自信のなかったMinitestの項目を無事終えることができました。
第3章は、プラクティスを進める上でテストコードが必須ではなかったため当時は軽く読み流していました。そのためwakaran状態だったのですが、今回輪読会を通してwakaru に変わり、今週も輪読会効果は絶大でした!
特に、モブプロのドライバーとして自分で手を動かしながらコードを確認することができたのが大きかったです。エラーコードを出したり、パスさせたり、「何がどうなっているのか?」実際に動かしてみることが理解の助けになりました。
では、また来週!(次回、第3週目)