概要
前回の投稿で掲載していたRubyのコードがRubyらしい書き方になっていないことに気づいたので、そのリファクタリングの部分の勉強メモを記します。
下記記事を拝見したのがきっかけで、勉強のために実際に内容を参考にさせて頂きながら前回投稿分のコードを例にして修正してみました。
[初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか | Qiita
コード
修正前
Upcasing.rb
defUpcasing(result_lines)result_lines[0]=result_lines[0].capitalizebreak_flg=false## ④ Rubyでのハッシュの記法 (修正せず:できなかった理由は後述)break_sign={"."=>true,"!"=>true,"?"=>true,","=>false}result_lines.each_indexdo|i|## ① 条件分岐と真偽値ifbreak_flg==trueresult_lines[i]=result_lines[i].capitalizeend## ② 配列要素の指定方法、文字列中の指定番の文字の参照ifbreak_sign[result_lines[i].slice(-1)]==truebreak_flg=trueelsebreak_flg=falseendendjoined_line=result_lines.join(" ")## ③ Rubyでの戻り値の表記returnjoined_lineendprintUpcasing(["oh,","yeah!","hello!"])## 実行結果## Oh, yeah! Hello!
変更点
def Upcasing(result_lines)
result_lines[0] = result_lines[0].capitalize
break_flg = false
## ④ Rubyでのハッシュの記法 (修正せず、変更できなかった理由は後述)
break_sign = { "."=>true, "!"=>true, "?"=>true, ","=>false }
result_lines.each_index do |i|
## ① 条件分岐と真偽値
- if break_flg == true
+ if break_flg
result_lines[i] = result_lines[i].capitalize
end
## ② 配列要素の指定方法、文字列中の指定番の文字の参照
- if break_sign[result_lines[i].slice(-1)] == true
+ if break_sign[result_lines[i][-1]]
break_flg = true
else
break_flg = false
end
end
joined_line = result_lines.join(" ")
## ③ Rubyでの戻り値の表記
- return joined_line
end
print Upcasing(["oh,", "yeah!", "hello!"])
修正後
Upcasing.rb
defUpcasing(result_lines)result_lines[0]=result_lines[0].capitalizebreak_flg=falsebreak_sign={"."=>true,"!"=>true,"?"=>true,","=>false}result_lines.each_indexdo|i|ifbreak_flgresult_lines[i]=result_lines[i].capitalizeendifbreak_sign[result_lines[i][-1]]break_flg=trueelsebreak_flg=falseendendjoined_line=result_lines.join(" ")endprintUpcasing(["oh,","yeah!","hello!"])## 実行結果## Oh, yeah! Hello!
各修正箇所の詳細
検討箇所①〜④について、番号順に追っていきます。
① 条件分岐と真偽値
- if break_flg == true
+ if break_flg
制御構造 > if | Ruby 2.7.0 リファレンスマニュアル
恥ずかしいことですが、惰性で使いすぎていて、式として変数単体を記載するとその真偽を返すという根本的な仕様を理解していませんでした。Rubyに限った話ですらないですね・・・。
少なくとも、Rubyでは単純な真偽判定で(== true)を書かないようにします。
Ruby
hoge=truephogeifhoge;hoge=false;endphoge# true# false
JavaScript
varhoge=true;console.log(hoge);if(hoge)hoge=false;console.log(hoge);// true// false
C#
publicclassHello{publicstaticvoidMain(){boolhoge=true;System.Console.WriteLine(hoge);if(hoge){hoge=false;}System.Console.WriteLine(hoge);}}// True// False
② 配列要素の指定方法、文字列中の指定番の文字の参照
- if break_sign[result_lines[i].slice(-1)] == true
+ if break_sign[result_lines[i][-1]]
- Methods > [] (String) | API documentation for Ruby 2.7.1.
文字列の後ろに[]をつけて文字番号を指定できることを初めて知りました。
負のインデックスによって後ろから数えられるのは便利ですね。 - Methods > [] (Array) | API documentation for Ruby 2.7.1.
配列要素の番号についても同様らしく、負のインデックスが、配列の末尾からの計算を意味することが明記されています。
③ Rubyでの戻り値の表記
def Upcasing(result_lines)
##
## コード省略
##
joined_line = result_lines.join(" ")
- return joined_line
end
- クラス/メソッドの定義 > メソッドの評価 | Ruby 2.7.0 リファレンスマニュアル
returnが呼ばれなかった場合は、本体の最後の式の値が返されることになるので、わざわざ修正前のように1行分記載する必要がありません。
④ Rubyでのハッシュの記法
break_sign={"."=>true,"!"=>true,"?"=>true,","=>false}
初めは、下記のようにシンボルを用いた記法に修正しようとしました。
修正案
break_sign={".":true,"!":true,"?":true,",":false}
上記のように変更すると、上位のメソッドのデバッグ結果が変わってしまいました。
そこで、ハッシュの中身を確認すると、以下のように格納されるキー"!"が文字列では無くなってしまいました。
break_sign={"."=>true,"!"=>true,"?"=>true,","=>false}pbreak_sign#=> {"."=>true, "!"=>true, "?"=>true, ","=>false}break_sign={".":true,"!":true,"?":true,",":false}pbreak_sign#=>{:"."=>true, :!=>true, :"?"=>true, :","=>false}
- Hash | API documentation for Ruby 2.7.1.
記法のバリエーションや各種関連メソッドについての説明はドキュメントで説明されています。
どうにかシンボルを使って表現しようとも考えたのですが、そもそもハッシュのキーに特殊文字一文字を当てる場面がそんなにあるのだろうかと疑問に思い、今回はスルーすることにしました。
この件に関して、また気づきがあれば別途投稿します。