복붙노트

[SCALA] 스칼라에서 암시 적 이해

SCALA

스칼라에서 암시 적 이해

나는 스칼라 플레이 프레임 워크 튜토리얼을 통해 내 길을 만들고 있었고, 난 나를 의아해했다이 코드 조각을 가로 질러 온 :

def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
        errors => BadRequest(views.html.index(Task.all(), errors)),
        label => {
          Task.create(label)
          Redirect(routes.Application.tasks())
        } 
  )
}

그래서 조사하기로 결정하고이 게시물을 가로 질러왔다.

나는 아직도 그것을 얻을하지 않습니다.

이 차이점은 무엇입니까 :

implicit def double2Int(d : Double) : Int = d.toInt

def double2IntNonImplicit(d : Double) : Int = d.toInt

서로 다른 방법 이름이 명백한 사실이 아닌.

언제 암시 사용하고 왜해야합니까?

해결법

  1. ==============================

    1.나는 아래 implicits의 주요 사용 사례를 설명하지만, 자세한 내용에 대한 스칼라 프로그래밍 관련 장을 볼 수 있습니다.

    나는 아래 implicits의 주요 사용 사례를 설명하지만, 자세한 내용에 대한 스칼라 프로그래밍 관련 장을 볼 수 있습니다.

    암시 적 매개 변수

    방법의 최종 매개 변수 목록 값들이 호출되는 상황에서 수행 될 즉, 암시 적으로 표시 될 수있다. 범위의 오른쪽 종류의 내재 가치가없는 경우는 컴파일되지 않습니다. 암시 적 값이 하나의 값으로 확인되어야하고 충돌을 방지하기 때문에, 예를 들면, 그 목적에 특정 유형을 확인하는 것이 좋습니다 암시 적 지능을 찾기 위해 방법을 필요로하지 않습니다!

    예:

      // probably in a library
    class Prefixer(val prefix: String)
    def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
    
      // then probably in your application
    implicit val myImplicitPrefixer = new Prefixer("***")
    addPrefix("abc")  // returns "***abc"
    

    암시 적 변환

    컴파일러가 컨텍스트에 대한 잘못된 유형의 표현을 발견하면, 그것은 유형 체킹 할 수 종류의 암시 적 기능의 가치를 찾을 것입니다. 는 A가 필요하고 그것이 B를 발견하는 경우 그래서, B 형의 암시 적 값을 찾습니다 => 스코프에서 (그것은 또한 B처럼 다른 장소를 확인하고 존재하는 경우 동반자는, 객체). 인증 된 정의는 함수 객체에 "ETA 발포"암시 데프 XYZ (: B ARG) 될 수 있기 때문에도 할 것이다.

    그래서 방법의 차이는 하나가 표시 암시 더블가 발견하지만, 지능이 필요한 경우 컴파일러에 의해 당신을 위해 삽입 될 것입니다.

    implicit def doubleToInt(d: Double) = d.toInt
    val x: Int = 42.0
    

    와 동일하게 작동합니다

    def doubleToInt(d: Double) = d.toInt
    val x: Int = doubleToInt(42.0)
    

    두 번째에서 우리는 수동으로 변환을 삽입 한; 처음에 컴파일러는 자동으로 동일한했다. 변환 때문에 왼쪽에있는 유형 약어의 필요합니다.

    플레이에서 첫 번째 조각에 관하여 :

    작업이 재생 문서에서이 페이지에 설명되어 있습니다 (또한 API 문서를 참조). 당신이 사용하는

    apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
    

    (동일한 이름의 형질 컴패니언) 동작 개체.

    그래서 우리는 형태의 문자로 기록 될 수있는 인수와 같은 기능을 제공해야

    request => ...
    

    함수 리터럴 당신이 원하는 경우에,하여 =>은 값을 선언하기 전에 일부, 그리고 다른 모든 발 선언처럼, 암시적인 표시 할 수 있습니다. 여기에,이 확인 입력에 대한 요청이 암시 적으로 표시 할 필요가 없습니다,하지만 그렇게하여이 함수 내에서 필요할 수있는 방법에 대한 암시 값으로 사용할 수 있습니다 (물론, 그것은 명시 적으로 사용할 수 있습니다 잘). Form 클래스에 bindFromRequest 방법은 암시 적 요청 인수를 필요로하기 때문에이 특정한 경우에,이 완료되었습니다.

  2. ==============================

    2.경고 : 신중하게 풍자가 들어 있습니다! YMMV ...

    경고 : 신중하게 풍자가 들어 있습니다! YMMV ...

    루이지의 대답은 완전하고 정확합니다. 이것은 하나의 예에 그것을 조금 확장하는 유일한 방법 할 수 있습니다 영광스럽게 남용 implicits, 그것은 꽤 자주 스칼라 프로젝트에서 발생한다. 사실 너무 자주, 당신은 아마 심지어 "모범 사례"가이드 중 하나에서 찾을 수 있습니다.

    object HelloWorld {
      case class Text(content: String)
      case class Prefix(text: String)
    
      implicit def String2Text(content: String)(implicit prefix: Prefix) = {
        Text(prefix.text + " " + content)
      }
    
      def printText(text: Text): Unit = {
        println(text.content)
      }
    
      def main(args: Array[String]): Unit = {
        printText("World!")
      }
    
      // Best to hide this line somewhere below a pile of completely unrelated code.
      // Better yet, import its package from another distant place.
      implicit val prefixLOL = Prefix("Hello")
    }
    
  3. ==============================

    3.왜 당신이 암시 적으로 요청 매개 변수를 표시해야하는 경우 :

    왜 당신이 암시 적으로 요청 매개 변수를 표시해야하는 경우 :

    예를 들어, Form.scala이 방법을 정의처럼 당신이 당신의 행동의 본문에 사용하게됩니다 일부 방법은 암시 적 매개 변수 목록을 가지고 :

    def bindFromRequest()(implicit request: play.api.mvc.Request[_]): Form[T] = { ... }
    

    당신은 반드시 당신은 그냥 myForm.bindFromRequest를 호출하는 것처럼이 () 명시 적으로 암시 적 인수를 제공 할 필요가 없습니다 통지하지 않습니다. 아니, 당신은 요청의 인스턴스를 필요로하는 메서드 호출을 통해 나오는 모든 시간에 전달하는 유효한 후보 개체를 찾기 위해 컴파일러를 둡니다. 당신이 요청이 가능한 않기 때문에, 당신이 할 필요가 암시 적으로 표시하는 것입니다.

    명시 적으로 암시 적 사용하기에로 사용할 표시합니다.

    당신은 "교활한에"그것은 (우리가 이름 "요청"을하는 듯했으나 그냥 "R"또는 "REQ"사용할 수도 있음) 필요한 곳을 플레이 프레임 워크에서 전송 된 요청 개체를 사용하여 "OK"의 컴파일러 힌트 .

    myForm.bindFromRequest()
    

    볼? 거기 아니지만이있다!

    그것은 단지 당신이 (당신이 그렇게 원하는 경우가 암시 적으로 표시하거나 있지 않은 경우하지만, 명시 적 상관없이 전달할 수)가 필요한 모든 장소에서 수동으로 슬롯 필요없이 발생합니다

    myForm.bindFromRequest()(request)
    

    암시 적으로 표시하지 않고, 당신은 위의 작업을 수행해야합니다. 이 같은 암시 당신이 필요가 없습니다 표시.

    때 암시 적으로 요청을 표시해야합니까? 당신은 정말 당신이 요청의 인스턴스를 기대 암시 적 매개 변수 목록을 선언하는 방법을 활용하는 경우에 필요합니다. 그러나 간단하게하기 위해, 당신은 항상 요청이 암시 표시하는 습관을 얻을 수 있습니다. 그런 식으로 당신은 아름다운 간결한 코드를 작성할 수 있습니다.

  4. ==============================

    4.또한, 상기의 경우에, 형태> 국제 = 이중 하나만 음함수이 있어야한다. 그렇지 않으면, 컴파일러는 혼동됩니다 제대로 컴파일되지 않습니다.

    또한, 상기의 경우에, 형태> 국제 = 이중 하나만 음함수이 있어야한다. 그렇지 않으면, 컴파일러는 혼동됩니다 제대로 컴파일되지 않습니다.

    //this won't compile
    
    implicit def doubleToInt(d: Double) = d.toInt
    implicit def doubleToIntSecond(d: Double) = d.toInt
    val x: Int = 42.0
    
  5. ==============================

    5.같은 스칼라 암시 적 작품에서 :

    같은 스칼라 암시 적 작품에서 :

    변환기

    매개 변수 값 인젝터

    암시 적 사용의 3 종류가 있습니다

    문자열 지능의 하위 유형이 아닌, 그래서 오류는 컴파일러가 암시 키워드를 가지고 있으며, 인자로 문자열을 받아 int를 반환 범위에서 이러한 방법을 찾습니다 오류를 해결하려면 라인 2에 발생합니다.

    그래서

    implicit def z(a:String):Int = 2
    
    val x :String = "1"
    
    val y:Int = x // compiler will use z here like val y:Int=z(x)
    
    println(y) // result 2  & no error!
    
        class Johnny{
    
        val haveTv:String = "Sony"
    
        }
    
       val mahadi = new Mahadi
    
    
    
       mahadi.haveTv // Error happening
    

    여기 mahadi.haveTv 오류를 생성합니다. 스칼라 컴파일러는 먼저 수신기를 mahadi하는 haveTv 속성을 찾습니다 때문입니다. 그것은 찾을 수 없습니다. 두 번째는 인수로 Mahadi 객체를 가지고 조니 객체를 반환 암시 키워드를 가진 범위 내에서 방법을 찾을 것이다. 그러나 여기가 없습니다. 그래서 오류를 생성합니다. 그러나 다음은 괜찮습니다.

    class Mahadi{
    
    val haveCar:String ="BMW"
    
    }
    
    class Johnny{
    
    val haveTv:String = "Sony"
    
    }
    
    val mahadi = new Mahadi
    
    implicit def z(a:Mahadi):Johnny = new Johnny
    
    mahadi.haveTv // compiler will use z here like new Johnny().haveTv
    
    println(mahadi.haveTv)// result Sony & no error
    

    매개 변수가 어떤 암시 키워드를 가지고 두 번째 경우는 값의 동일한 유형이 범위에있는 발을 찾습니다. 하지 않으면이 오류가 발생합니다.

    def x(implicit a:Int)= a
    
    x // error happening here
    

    이 문제 컴파일러는 매개 변수 a는 암시 키워드를 가지고 있기 때문에 지능의 유형을 갖는 암시 발을 찾습니다 풀기가합니다.

    def x(implicit a:Int)=a
    
    implicit val z:Int =10
    
    x // compiler will use implicit like this x(z)
    println(x) // will result 10 & no error.
    

    또 다른 예:

    def l(implicit b:Int)
    
    def x(implicit a:Int)= l(a)
    

    우리는 또한 그것을 같은 - 쓸 수 있습니다

    def x(implicit a:Int)= l
    

    L은 암시 적 매개 변수를 가지며, 방법 (X)의 본체의 범위에 내재 로컬 변수 (파라미터 로컬 변수)에있어서, 서명은 L의 암시 적 인수 값은 X 메소드의 본문에 있도록이 X의 파라미터 이는 있으므로 암시 X 방식의 로컬 암시 적 변수 (파라미터)에 의해 제기했다.

    그래서

     def x(implicit a:Int)= l
    

    이 같은 컴파일러에있을 것입니다

    def x(implicit a:Int)= l(a)
    

    또 다른 예:

    def c(implicit k:Int):String = k.toString
    
    def x(a:Int => String):String =a
    
    x{
    x => c
    }
    

    X = {(X)> (C)}의 C 명시 값 통과 범위에서 인수 또는 암시 브로 필요에 있기 때문에, 오류가 발생할 것이다.

    우리는 방법 X를 호출 할 때 그래서 우리는의 함수 리터럴 매개 변수를 명시 적으로 암시 할 수있다

    x{
    implicit x => c // the compiler will set the parameter of c like this c(x)
    }
    

    이것은 플레이 프레임 워크의 동작 방법에 사용 된

    def index = Action{
    implicit request =>
    
    Ok(views.html.formpage)
    
    }
    
  6. from https://stackoverflow.com/questions/10375633/understanding-implicit-in-scala by cc-by-sa and MIT license