Scalaで複数の暗黙の引数を持つ関数を定義する


94

複数の暗黙の引数を持つ関数を定義するにはどうすればよいですか。

def myfun(arg:String)(implicit p1: String)(implicit p2:Int)={} // doesn't work

2
質問文では、関数について尋ねています。コードスニペットにはメソッドがあります。関数やメソッドについて尋ねていますか?
イェルクWミッターク

回答:


190

それらはすべて1つのパラメーターリストに含める必要があり、このリストは最後のリストでなければなりません。

def myfun(arg:String)(implicit p1: String, p2:Int)={} 

1
それがクラスの場合、構文はクラスMyClass()(暗黙のp1:文字列、暗黙のp2:Int){}
skjagini

2

実際には、OPが必要とするものを正確に実行する方法があります。少し複雑ですが、機能します。

class MyFunPart2(arg: String, /*Not implicit!*/ p1: String) {
  def apply(implicit p2: Int) = {
    println(arg+p1+p2)
    /* otherwise your actual code */
  }
}

def myFun(arg: String)(implicit p1: String): MyFunPart2= {
  new MyFunPart2(arg, p1)
}

implicit val iString= " world! "
implicit val iInt= 2019

myFun("Hello").apply
myFun("Hello")(" my friend! ").apply
myFun("Hello")(" my friend! ")(2020)

//  Output is:
//      Hello world! 2019
//      Hello my friend! 2019
//      Hello my friend! 2020

Scala 3(別名「Dotty」、これはコンパイラーの名前です)では、補助のMyFunPart2オブジェクトを返す代わりに、暗黙の引数を持つ関数値を直接返すことが可能です。これは、Scala 3が「暗黙的な関数」をサポートしているためです(つまり、「パラメーターの暗黙性」は関数型の一部になりました)。複数の暗黙的なパラメーターリストを実装するのが非常に簡単になるので、言語がそれらを直接サポートする可能性がありますが、よくわかりません。


1

同様の効果を実現する別の方法(IMOがよりシンプルでより柔軟)があります。

// Note the implicit is now a Tuple2
def myFun(arg: String)(implicit p: (String, Int) ): Unit = {
  println(arg + p._1 + p._2)
  /*otherwise your actual code*/
}

// These implicit conversion are able to produce the basic implicit (String,Int) Tuples
implicit def idis(implicit is: String, ii: Int): (String,Int)= (is,ii)
implicit def idi(s: String)(implicit ii: Int): (String,Int)= (s,ii)

// The basic implicit values for both underlying parameters
implicit val iString = " world! "
implicit val iInt = 2019

myFun("Hello")
myFun("Hello")(" my friend! ")
myFun("Hello")(" my friend! ",2020)

// Output is:
//     Hello world! 2019
//     Hello my friend! 2019
//     Hello my friend! 2020

// If we add the following implicit, 
implicit def ids(i: Int)(implicit is: String)= (is,i)

// we can even do
myFun("Hello")(2020)

// , and output is:
//     Hello world! 2020

暗黙的な変換は他の用途に干渉する可能性があるため、パラメーターの基本表現としてタプルを使用することはお勧めできません。実際、標準タイプ(ライブラリを含む)への暗黙的な変換は、通常、重要なアプリケーションで問題を引き起こします。解決策は、タプルの代わりにパラメーターを保持する専用のケースクラスを作成することです。重要な利点は、_1と_2よりもはるかに意味のある名前を付けることができることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.