Collectとは

collect とは、フィルタで値のリストを得ることに特化した機能です。

Plugin.filtering でイベントのフィルタだけを呼び出すことができます。イベントがキューに積まれて後で実行されるのに対して、 Plugin.filtering はフィルタをその場で呼び出して、メソッドの戻り値として引数をフィルタした結果を返します。

以下は、従来のフィルタのおさらいです。

単純なフィルタの定義
filter_mute do |world, yielder|
  if world == 'hoge'
    yielder << 'toshi_a'
  end
  [yielder]
end

このようなフィルタは、第二引数に << メソッドで値を挿入することで、複数のプラグインが :mute イベントの結果に値を加えることができるのでした。

フィルタの拡張の例
filter_mute do |world, yielder|
  yielder << 'jack'
  [yielder]
end
従来のフィルタ戻り値の受け取り方
world, users = Plugin.filtering(:mute, 'hoge', [])
world # => "hoge"
users # => ["toshi_a", "jack"]

world, users = Plugin.filtering(:mute, 'fuga', [])
world # => "fuga"
users # => ["jack"]

このように、ある引数に << メソッドで追加されていくことを期待しているフィルタをコレクションフィルタ、そのような引数のことをコレクション引数 と呼びます。

Collectが解決すること

collect単純なフィルタの定義はそのままで、従来のフィルタ戻り値の受け取り方のコードを簡潔にすることを目的とします。以下が、従来のフィルタ戻り値の受け取り方collectを使って書き換えたものです。

collectを使った例
collect(:mute, 'hoge') # => ["toshi_a", "jack"]
collect(:mute, 'fuga') # => ["jack"]

関心のある値だけを取得できる

Plugin.filtering は、引数全てを配列にして戻り値とします。あるフィルタの引数として5つの引数が必要なら、 Plugin.filtering の戻り値は5要素の配列です。したがって単純なフィルタの定義のように多重代入で必要な要素だけピックアップするか、 Plugin.filtering(…​)[1] のように書いていました。

一方、collectコレクション引数のみを返します。コレクションフィルタの戻り値では、コレクション引数にしか興味がないことがほとんどなので、些細なことですがこの挙動は非常に有用です。

Collectionとのシナジー

collect従来のフィルタ戻り値の受け取り方のようなコードを簡潔にすることを目的としていると説明しましたが、単純なフィルタの定義を改善するのはCollectionです。

collectは従来のフィルタと互換性がある一方で、Collectionといっしょに使うことでパフォーマンスが有利になります。

collect

Table 1. collect(event_slug, *args) → Enumerable
引数名 意味

event_slug

Symbol

subscribeするイベントの識別子

*rest

-

コレクション引数以外の引数

戻り値

Enumerable

コレクション引数に列挙されたオブジェクトのリスト

コレクションフィルタの定義

defevent :mute, prototype: [String, Pluggaloid::COLLECT]

defevent でイベントを定義するとき、 prototype: キーワード引数に渡す配列の中に、 Pluggaloid::COLLECT という定数を含めると、コレクションフィルタになります。