5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

そのRubyプログラムをきっと速くできない小ネタ

5
Last updated at Posted at 2018-03-02

2017年9月なので少々前の話になるのですが、Rails のコミットログを見ていたらこんな変更を見つけました。

難しいことではなく、単に ||= を使っていたところを defined? でチェックし代入するように変更しています。

何が違うか

値が nil だった場合、変更前の書き方の場合は、「偽かチェックして、右辺を改めて算出する」のに対して、変更後はそれらが要りません。

「偽なら代入 ||= 」の場合

  • 定義しているか -> ?
  • 偽か -> チェックする
  • 代入する値 -> 計算する

「defined? が偽なら代入」の場合

  • 定義しているか -> チェックする
  • 偽か -> なし
  • 代入する値 -> なし

しかもこれが、このメソッドを通るたびに発生します。

自分は、真偽チェックと defined? と (Ruby の言語レベルの話として) どの程度コストが違うのか、というところまでは理解してないのですが、少なくとも defined? だけにすればやることが減るのは確かだと思います。

どんなケースに応用できるか

フレームワークレベルでこれを直せばなるほど意味があるように思いますが、それ以外でもどこかに役立てたいものです。

同様の修正が有効なのは、(追記しました)

  • 右辺で複雑な計算をしている
  • 結果として nil もしくは false が返って来うる
  • 何度も実行されるが、右辺の返り値は変わらない

上記の場合でしょうか。

自分の書いているプログラムには思い当たらないです。残念。

追記: 特に早くしたい目的ではないのですが、代入するものの導出が複数行に渡り、 begin - end で書いているようなケースでは、見た目の複雑さが大きくは変わらないので積極的に使っていこうと思いました。

before
def client
  @client ||= begin
                # ... 何かすごい処理
                Client.new
              end
end
after
def client
  unless defined?(@client)
    # ... 何かすごい処理
    @client = Client.new
  end
  @client
end
5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?