Scala'da birden çok örtük argüman içeren bir işlevi tanımlama


95

Birden çok örtük argüman içeren bir işlevi nasıl tanımlayabilirim?

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

3
Soru metninde bir fonksiyon hakkında soru soruyorsunuz. Kod pasajınızda bir yönteminiz var. Bir işlev mi yoksa yöntem mi soruyorsunuz?
Jörg W Mittag

Yanıtlar:


190

Hepsi tek bir parametre listesine girmeli ve bu liste sonuncu olmalıdır.

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

1
Bu bir sınıf olsaydı, sözdizimi class MyClass () olurdu (örtük p1: String, örtük p2: Int) {}
skjagini

2

Aslında OP'nin gerektirdiğini tam olarak yapmanın bir yolu var. Biraz kıvrık, ama işe yarıyor.

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'te ("Dotty" olarak da bilinir, ancak bu derleyicinin adıdır) yardımcı bir MyFunPart2 nesnesi döndürmek yerine, dolaylı olarak örtük argümanlarla bir işlev değeri döndürmek mümkündür. Bunun nedeni, Scala 3'ün "Örtük İşlevleri" desteklemesidir (yani "parametre örtüklüğü" artık işlev türlerinin bir parçasıdır). Birden çok örtük parametre listesinin uygulanması o kadar kolay hale geldi ki, emin değilim, ancak dilin bunları doğrudan desteklemesi mümkün.


1

Benzer bir etki elde etmenin başka (IMO daha basit ve daha esnek) bir yolu vardır:

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

Bir Tuple'ı parametrelerin temel temsili olarak kullanmak iyi bir fikir değildir çünkü örtük dönüştürmeler diğer kullanımları etkileyebilir. Aslında, herhangi bir standart türe (kitaplık dahil) örtük dönüştürmeler genellikle önemsiz olmayan uygulamalarda sorun yaratır. Çözüm, bir Tuple yerine parametreleri tutmak için özel bir durum sınıfı oluşturmaktır. Önemli bir avantaj, onlara _1 ve _2'den çok daha anlamlı isimler verilebilmesidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.