どうやらエクストラクタオブジェクトのunapply/unapplySeqは、暗黙のパラメータをサポートしていません。ここで、興味深いパラメータaと、cを抽出するときに隠れておくとよい不穏に遍在するパラメータbを想定します。
[編集]:これを引き起こした私のintellij/scala-pluginインストールで何かが壊れているようです。私は説明できません。私は最近、私のIntellijで多くの奇妙な問題を抱えていました。再インストールした後、問題を再現できなくなりました。unapply / unapplySeqが暗黙のパラメーターを許可することを確認しました!ご協力いただきありがとうございます。
これは機能しません(**編集:はい、機能します):**
trait A; trait C; trait B { def getC(a: A): C }
def unapply(a:A)(implicit b:B):Option[C] = Option(b.getC(a))
理想的なエクストラクタがどのようなものであるかを理解していると、Javaの人々にも直感的に意図が明確になりますが、この制限により、追加のパラメータに依存するエクストラクタオブジェクトが基本的に禁止されます。
通常、この制限をどのように処理しますか?
これまでのところ、私はそれらの4つの可能な解決策を持っています:
1)私が改善したい最も簡単な解決策:bを非表示にしないで、タプルの形式でunapplyの通常のパラメーターとして、パラメーターbをaと一緒に提供します。
object A1{
def unapply(a:(A,B)):Option[C] = Option(a._2.getC(a._1)) }
クライアントコード:
val c1 = (a,b) match { case A1(c) => c1 }
ここではaからcへの脱構築が重要であるということを逸脱するノイズが多いので、私はそれが好きではありません。また、このscalaコードを実際に使用することを確信しなければならないJavaの人々は、1つの追加の合成ノベルティ(タプルブレース)に直面しています。彼らは反スカラ攻撃性を得るかもしれません「これは何ですか?...では、そもそも通常の方法を使用して、確認してみませんか?」
2)特定のBへの依存関係をカプセル化するクラス内にエクストラクタを定義し、そのインスタンスのエクストラクタをインポートします。インポートサイトではJavaの人々にとっては少し珍しいですが、パターンマッチではサイトbがうまく隠されており、何が起こっているのかが直感的にわかります。お気に入り。私が逃したいくつかの不利な点は?
class BDependent(b:B){
object A2{
def unapply(a:A):Option[C] = Option(b.getC(a))
} }
クライアントコードでの使用法:
val bDeps = new BDependent(someB)
import bDeps.A2
val a:A = ...
val c2 = a match { case A2(c) => c }
}
3)クライアントコードのスコープでエクストラクタオブジェクトを宣言します。bは、ローカルスコープで「b」を使用できるため非表示になっています。コードの再利用を妨げ、クライアントコードをひどく汚染します(さらに、コードを使用する前にコードを記述する必要があります)。
4)関数B => Cのオプションを適用せずに返します。これにより、bをエクストラクターに直接提供するのではなく、使用した場合の結果に、野心的なパラメーターに依存するエクストラクターのインポートと使用が可能になります。Javaの人々は、関数値の使用法に混乱している可能性があります。bは非表示ではありません。
object A4{
def unapply[A,C](a:A):Option[B => C] = Option((_:B).getC(a))
}
次に、クライアントコードで:
val b:B = ...
val soonAC: B => C = a match { case A4(x) => x }
val d = soonAC(b).getD ...
さらなる備考:
- この回答で示唆されているように、「ビュー境界」は、エクストラクタを暗黙の変換で機能させるのに役立つ場合がありますが、これは暗黙のパラメータでは役立ちません。何らかの理由で、暗黙の変換を回避したくない。
- 「文脈の限界」を調べましたが、同じ制限があるようですよね?