true/falseとnilの違いの有用なケース
最近久しぶりにrubyをよく書いている。
で、ちょっと特殊だけどnilとfalseの組み合わせで有用なケースがあったので記載しておく^^
で、先に書いておくと
if/unless等では、falseとnilは等価であるが、他の方法(case whenやnil?等)ではfalseとnilは区別できることです
想定:ログ解析スクリプト
で有用なケースというのは、ログ解析にrubyで簡単なフィルタを作成したのですが
最初は入力値のパターンが「2パターン(なのでtrue/falseを使用)」のみで十分と判断してたのですが、
なんやかんやで「3パターン」必要じゃない?ってなりました。
で、仕方ないので結構書きなおすかと思ったのですが、nilを追加することで入力「3パターン」を最小の変更で対応できました
[入力 true/false] -> [出力 "pass"/"fail"]
で、簡単に書くと最初は以下みたいなコード書いてました。
最初入力パラメータを、true/falseを想定してたので、途中でif/unlessの条件分岐がいくつか入れてしましました><
flags = [false, true] #入力 result = [] #出力 flags.each{|flg| # if/unlessで条件チェックした処理があり puts 17 unless flg puts 42 if flg # で結果を出力 if flg result << "pass" else result << "fail" end } #=> 17 42 p result #=> ["fail", "pass"]
[入力 true/false/nil] -> [出力 "pass"/"fail"/"todo"]
で、入力「3パターン」にnilを追加して、以下のような対応しました。
で新しく増えたパターンは意味的にfalseに近いのでnilを使用*1、途中のif/unlessをそのまま流用。
で途中はfalse/nilは一緒の意味で使いたいけど、出力は分別したいので、caseで分岐。
ってか、caseで分岐できることを確認できたので、nilを入力パターンの追加ケースの値に選びましたとさ><
flags = [false, true, nil] #入力 result = [] #出力 flags.each{|flg| # if/unlessで条件チェックした処理があり puts 17 unless flg puts 42 if flg # で結果を出力 case flg when true result << "pass" when false result << "fail" when nil result << "todo" end } #=> 17 42 17 p result #=> ["fail", "pass", "todo"]
と、途中のif/unlessの条件チェック部分を書き換えることなく入力/出力2パターンから、3パターンに修正が出来ましたとさ^^
結論
設計は確りと><、*2
P.S. 23:15
今回if/unlessにおいてfalseと等価なものが必要であり、nilがそうであったので使用しました。
が、trueと等価なものが必要であったケースを想定して、よく考えると、一杯あります。ってかfalseとnil以外ですね><
なのでtrueとif/unlessにおいて等価なパターンはいくらでも増やせますね
(はいそんなケースは最初の設計が狂っていたということです><
[入力 true/false/nil/42/"ruby"] -> [出力 "pass"/"fail"/"todo"/"num"/"pyhton"]
flags = [false, true, nil, 42, "ruby"] #入力 result = [] #出力 flags.each{|flg| # if/unlessで条件チェックした処理があり puts 17 unless flg puts 42 if flg # で結果を出力 case flg when true result << "pass" when false result << "fail" when nil result << "todo" when 42 result << "num" when "ruby" result << "python" end } #=> 17 42 17 42 42 p result #=> ["fail", "pass", "todo", "num", "python"]