LoginSignup
7
7

More than 5 years have passed since last update.

Object#self があればちょっとうれしい(→2.2.0からは Kernel#itself ができるそうです)

Last updated at Posted at 2014-08-06

きっかけ

さきほど

hoge = [1, 2, 2, 3, 3, 4, 5, 6, 5, 4]
hoge.group_by{|i| i}.reject{|k,v| v.size == 1}.keys
#=> [2, 3, 4, 5]

[Ruby]重複している値の扱い方 - Qiita

というのを読みました。
DRY を大原則としていたい私としては

group_by{|i| i}

をなんとかできないのかと考えたのですが、ムリでした。

補足:DRY とは →OAOO とは

情報システムの構成や構築手法についての原則の一つで、同じ意味や機能を持つ情報やデータを複数の場所に重複して置くことをなるべく避けるべきとする考え方。
複数の場所に同じ情報が置かれていると変更時に整合性が取れなくなる危険性が高まるため、一箇所で管理して必ずそこから参照するようにすべきとする原則である。
転じて、プログラムコード中で同じ(ような)動作をするコードを何度も書かずに、一度書いたものを再利用するようにすべきとする意味で用いられることもあるが、 こちらは本来は“Once and Only Once”(OAOO)原則と呼ばれるもの である。
DRY原則とは 【 Don't Repeat Yourself 】 - 意味/解説/説明/定義 : IT用語辞典

…うわ、今の今まで勘違いしてたorz OAOOだそうです_φ(・_・

モンキーパッチ

オブジェクトに対して何もせずに自分自身を返すメソッドがあればいいのに…と思ったので、作りました。作ったというのもおこがましいほどのスクリプト。

class Object
  def self
    self
  end
end

これで望み通りの表記にできます!

hoge = [1, 2, 2, 3, 3, 4, 5, 6, 5, 4]
hoge.group_by(&:self).reject{ |k,v| v.size == 1 }.keys
#=> [2, 3, 4, 5]

やった\o/

その他の例

"string".each_char.sort_by{ |char| char }
#=> ["g", "i", "n", "r", "s", "t"]
"string".each_char.sort_by(&:self)
#=> ["g", "i", "n", "r", "s", "t"]
"string".each_char.map{ |char| char }
#=> ["s", "t", "r", "i", "n", "g"]
"string".each_char.map(&:self)
#=> ["s", "t", "r", "i", "n", "g"]

self って予約語じゃね?やばくね?

予約語はクラス名、変数名などに用いることはできません。(中略)また、def のあとやメソッド呼び出しのピリオドのあとなど メソッド名であるとはっきり分かる場所ではメソッド名として用いることができます
るりま:字句構造

ということでレシーバがハッキリしていれば self メソッドを作っても/使っても大丈夫っぽいです。

先人の教え

同じことを考えている方が(当たり前でしょうが)居られました。
やはり Object#tap を思いつきますよね。

selfを返すメソッドといえば、思い付くのが「tap」なんですけど「tap」はブロックがないと localJumpError: no block given (中略)なんでブロック必須なんだろ?? ブロックがない時はselfを返してくれればいいのに!

class Object
  def tap
    block_given? ? super : self
  end
end

Rubyでselfを返すメソッドってあったっけ? - Qiita

追記:Kernel#itself ができるそうです

コメント欄引用

@niku
つい先日コミットがあり 2.2 からは Kernel#itself というメソッドを利用できそうです.

いい話です^^
Feature #6373: public #self - ruby-trunk - Ruby Issue Tracking System
を見てみると一昨年4月に Object#self が提案されていますね。

9/30追記:2.2.0 preview1 に載ってきました

いわゆる恒等関数と呼ばれる、自身 (self) をそのまま返すメソッド Kernel#itself が追加されました。
他の言語でも恒等関数が組み込みで存在する場合があり、ididentity などの名前で定義されていることが多いです。「 名前重要! 」の Ruby では恒等関数の導入案は以前からありましたが、名前がなかなか決まらなかったという経緯があります。今回は itself という名前に落ち着いたようで、ようやく導入されました。
» Ruby 2.2.0 preview1: ついに来ました!恒等関数 Kernel#itself などなど TECHSCORE BLOG

MRI 2.2 未満(正確には 2.1.2 以下)の為に itself gem を作ってみた

riocampos/itself
(2.1.3が出たから更新しなきゃ…)

$ gem install itself

Kernel#itself が使えるようになります。

[1, 2, 3, 4, 5, 1, 2, 2, 3].group_by(&:itself)
#=> {1=>[1, 1], 2=>[2, 2, 2], 3=>[3, 3], 4=>[4], 5=>[5]}

"string".each_char.sort_by(&:itself)
#=> ["g", "i", "n", "r", "s", "t"]
7
7
2

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
7
7