implicitly
스칼라 예제에서 사용되는 이름의 함수를 보았습니다 . 그것은 무엇이며 어떻게 사용됩니까?
여기 예 :
scala> sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:8: error: could not find implicit value for evidence parameter of type
Foo[Double]
foo(List(1.0))
^
implicitly[Foo[A]].apply(x)
컴파일러 는 매개 변수를 implicitly[Foo[A]](x)
호출 한다는 것을 의미 하므로 작성해야합니다 implicitly
.
객체 / 유형 등을 조사하는 방법 도 참조하십시오 . 스칼라 REPL에서? 와 스칼라는 implicits 어디에서 보는가?
답변
유쾌하게 간단한 방법을 사용해야하는 몇 가지 이유가 있습니다 implicitly
.
암시 적 뷰 이해 / 문제 해결
선택의 접두사를 고려할 때 암시 적 뷰가 트리거 될 수 있습니다 (예 : 고려할 수 the.prefix.selection(args)
있는 멤버 selection
가 포함되지 않은 경우 args
( args
암시 적 뷰로 변환 한 후에도 ))이 경우 컴파일러는 로컬로 정의 된 암시 적 멤버를 찾습니다. 현재 또는 둘러싸는 범위에서 상속되거나 가져온 범위에서 해당 유형의 함수에서 정의 된 the.prefix
유형 selection
또는 동등한 암시 적 메소드 가있는 유형의 함수입니다 .
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
다음과 같이 표현식이 예상 유형을 준수하지 않는 경우 암시 적 뷰가 트리거 될 수도 있습니다.
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
컴파일러는이 함수를 찾습니다.
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
컨텍스트 바운드에 의해 도입 된 암시 적 매개 변수 액세스
암시 적 매개 변수는 암시 적 뷰보다 스칼라의 더 중요한 기능 일 것입니다. 형식 클래스 패턴을 지원합니다. 표준 라이브러리는 이것을 몇 곳 scala.Ordering
에서 사용 SeqLike#sorted
합니다. 사용 방법을 참조하십시오 . 암시 적 매개 변수는 또한 배열 매니페스트 및 CanBuildFrom
인스턴스 를 전달하는 데 사용됩니다 .
스칼라 2.8에서는 컨텍스트 바인드라고하는 암시 적 매개 변수에 대한 간단한 구문을 사용할 수 있습니다. 간단히 말해서, type 매개 변수 A
를 갖는 메소드는 다음 유형 의 암시 적 매개 변수 를 필요로합니다 M[A]
.
def foo[A](implicit ma: M[A])
다음과 같이 다시 작성할 수 있습니다.
def foo[A: M]
그러나 암시 적 매개 변수를 전달하지만 이름을 지정하지 않는 요점은 무엇입니까? 메소드를 구현할 때 어떻게 유용 foo
합니까?
암시 적 매개 변수를 직접 참조 할 필요가없는 경우가 종종 있으며, 호출 된 다른 메소드에 대한 암시 적 인수로 터널링됩니다. 필요한 경우 컨텍스트 바인딩을 사용하여 간결한 메소드 서명을 유지 implicitly
하고 값을 구체화하기 위해 호출 할 수 있습니다.
def foo[A: M] = {
val ma = implicitly[M[A]]
}
암시 적 매개 변수의 서브 세트를 명시 적으로 전달
타입 클래스 기반 접근 방식을 사용하여 사람을 예쁘게 인쇄하는 메소드를 호출한다고 가정하십시오.
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
이름이 출력되는 방식을 바꾸려면 어떻게해야합니까? 명시 적으로 호출 PersonShow
하고 대안을 명시 적으로 전달할 수 Show[String]
있지만 컴파일러가을 전달하기를 바랍니다 Show[Int]
.
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
답변
Implicitly
Scala 2.8에서 사용 가능하며 Predef 에서 다음 과 같이 정의 됩니다.
def implicitly[T](implicit e: T): T = e
일반적으로 암시 적 유형의 값 을T
사용할 수 있는지 확인 하고 그러한 경우 반환합니다 .
retronym의 프레젠테이션 에서 간단한 예 :
scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
val c = implicitly[Int]
^