Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Ruby: 数値のゼロチェックには'== 0'よりも'zero?'メソッドを使おう(翻訳)

概要

元サイトの許諾を得て翻訳・公開いたします。

日本語タイトルは内容に即したものにしました。

Ruby: 数値のゼロチェックには'== 0'よりも'zero?'メソッドを使おう(翻訳)

Rubyの構文や標準ライブラリが提供するメソッドは、他の言語に比べて読みやすさ(と喜び)をしばしば優先しています。

その例の1つは、値をゼロと比較するときのシンタックスシュガーです。

それぞれのドキュメントのzero?メソッドの項を読んでみてください。

🔗 以下のように書くよりも

値が0に等しいかどうかのチェックを条件に書く。

if number == 0
  :yes
else
  :no
end

🔗 以下のように書こう

すべての数値型に組み込まれている#zero?メソッドを使う。

if number.zero?
  :yes
else
  :no
end

🔗 そうする理由

Rubyらしい書き方にすることで意味も明確になり、間違いが起こりにくくなります。

1番目のサンプルコードでは、うっかりnumber = 0と書いてしまう凡ミスが非常に起きやすくなります。こう書いてしまうと、変数との比較ではなく変数への代入が実行されてしまいます(この種のエラーから保護するためにテストを書いてもいいのですが)。

🔗 そうしない理由があるとすれば

== 0構文を採用している類似の言語はとても多く、広く知れ渡っています。Rubyプログラミング歴15年の私も、未だに上述のアドバイスの適用に苦労しています。

「パフォーマンス」を理由としてこの書き方に反発する人も一部にいるでしょう。

require "benchmark/ips"

Benchmark.ips do |x|
  x.report("1 == 0") { 1 == 0 }       #=> false
  x.report("0 == 0") { 0 == 0 }       #=> true
  x.report("1.zero?") { 1.zero? }     #=> false
  x.report("0.zero?") { 0.zero? }     #=> true

  x.report("1.0 == 0") { 1.0 == 0 }   #=> false
  x.report("0.0 == 0") { 0.0 == 0 }   #=> true
  x.report("1.0.zero?") { 1.0.zero? } #=> false
  x.report("0.0.zero?") { 0.0.zero? } #=> true
end

 Integerの場合:

1 == 0
29.049M (± 0.7%) i/s
0 == 0
28.972M (± 0.3%) i/s
1.zero?
23.009M (± 1.0%) i/s
0.zero?
22.860M (± 1.7%) i/s

Floatの場合:

1.0 == 0
18.768M (± 2.0%) i/s
0.0 == 0
19.066M (± 0.5%) i/s
1.0.zero?
22.784M (± 0.6%) i/s
0.0.zero?
22.841M (± 0.8%) i/s

このベンチマークでは、Integer==構文の方が高速ですが、Floatでは.zero?の方が勝っています2

しかし重要なのは、どちらも1秒間に数千万回実行される点では同じということです。自分のコードではパフォーマンスへの影響を気にするより読みやすさを重視しましょう。

関連記事

Railsでnil? blank? empty? present?を使いこなそう


  1. 訳注: 4つの中でBigDecimalのみコアクラスではなく標準ライブラリです。 
  2. 訳注: 元記事のベンチマークではRubyのバージョンや環境が示されていません。念のためご留意ください。 

CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。