filterでプレイスホルダー複数使いたい
(1 to 10).filter(_ % 3 == 0 || _ % 5 == 0).mkString(",")
// => 3,5,6,9,10
みたいな。
でもこれはコンパイルを通らない。
error: missing parameter type for expanded function
((x$1, x$2) => x$1.$percent(3).$eq$eq(0).$bar$bar(x$2.$percent(5).$eq$eq(0)))
と怒られる。
↓これならコンパイル通る。
(1 to 10).filter((it: Int) => it % 3 == 0 || it % 5 == 0).mkString(",")
でも、違うんだよ。
空気読んでくれよ。
引数の型とか、いちいち書きたくないよ。
コンパイラのエラーメッセージを読むと「引数の型がない」と言ってるが
よく見ると【引数を2つ取る関数】だと判断しているように見受けられる。
(x$1, x$2) => x$1.$percent ...
じゃ、これでどうよ。
implicit def dblArgs[A, B](f: (A, A) => B): (A) => B = (a: A) => f(a, a)
(1 to 10).filter(dblArgs(_ % 3 == 0 || _ % 5 == 0)).mkString(",")
// => 3,5,6,9,10
(1 to 10).filter(_ % 3 == 0 || _ % 5 == 0).mkString(",")
// => error: missing parameter type for expanded function ...
自分で書けばOKだが、暗黙には変換してくれない。。。
これならどうだ。
implicit class SeqW[A](seq: Seq[A]) {
def filter(f: (A, A) => Boolean): Seq[A] = seq.filter(it => f(it, it))
}
(1 to 10).filter(_ % 3 == 0 || _ % 5 == 0).mkString(",")
// => error: missing parameter type for expanded function ...
ダメでした。。。
では、これなら?
implicit class SeqW[A](seq: Seq[A]) {
// 名前をfilterNにしてみた
def filterN(f: (A, A) => Boolean): Seq[A] = seq.filter(it => f(it, it))
}
(1 to 10).filterN(_ % 3 == 0 || _ % 5 == 0).mkString(",")
// => 3,5,6,9,10
OK!
どうやら同名の関数がある場合は暗黙変換は適用されないようだ。
implicit classでオーバーロードはできないってことか?
、、、と思いそうになったが調べてみると違った。
オーバーロードできます。
でも今回のケースではうまくいかない。
この件は後日メモを残す(つもり)
当初の目的は達成したものの、プレイスホルダーが増えれば増えた分だけfilterX
を定義しなければならない。
最大で22個も。。。
しかもmap
でも同じことやりたい、find
でも、となると全部書くことに。。。
費用対効果が。。。
今回の件で、複数のプレイスホルダーを使うにはいろいろ面倒だ、ということがわかった。
ひとつ利口になった(といいなぁ)。