scala sbt - 스칼라에서 함축적 인 이해




twirl (5)

아래의 implicits의 주요 사용 사례를 설명 하겠지만 자세한 내용은 Programming in Scala관련 장을 참조하십시오.

암시 적 매개 변수

메소드의 최종 매개 변수 목록은 implicit 으로 표시 될 수 있습니다. 즉, 값은 호출 된 컨텍스트에서 가져옵니다. 범위에 올바른 유형의 암시 적 값이 없으면 컴파일되지 않습니다. 암시 적 값은 단일 값으로 해결되어야하고 충돌을 피하기 위해 형식을 용도에 맞게 만드는 것이 좋습니다. 예를 들어 암시 적 Int 를 찾기 위해 메서드를 요구하지 않아도됩니다.

예:

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

암시 적 전환

컴파일러가 컨텍스트에 대해 잘못된 형식의 식을 찾으면 형식 검사를 허용하는 형식의 암시 적 Function 값을 찾습니다. 따라서 A 가 필요하고 B 찾으면 범위에 B => A 유형의 암시 적 값을 찾습니다 (존재하는 경우 BA 부속 객체와 같은 다른 장소도 검사 함). defFunction 객체로 "η 확장"될 수 있기 때문에 implicit def xyz(arg: B): A 도 마찬가지입니다.

그래서 당신의 메소드의 차이점은 Double 이 발견되었지만 Int 가 필요할 때 컴파일러에 의해 implicit 으로 삽입 된 것이 삽입된다는 것입니다.

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

같이 작동합니다.

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

두 번째에서는 수동으로 변환을 삽입했습니다. 처음에는 컴파일러가 자동으로 동일한 작업을 수행했습니다. 왼쪽에 유형 주석이 있기 때문에 변환이 필요합니다.

Play의 첫 번째 스 니펫에 관해서 :

액션은 Play 문서 에서이 페이지 에 설명되어 있습니다 ( API 문서 참조). 사용중인

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

Action 객체 (동일한 이름의 특성에 대한 동반자)에서

그래서 함수를 인수로 제공해야합니다.이 함수는 형식으로 리터럴로 쓸 수 있습니다.

request => ...

함수 리터럴에서 => 앞에있는 부분은 값 선언이며 원하는 경우 다른 val 선언과 마찬가지로 implicit 으로 표시 될 수 있습니다. 여기서 request 이 형식 검사에 대해 implicit 으로 표시 할 필요는 없지만 그렇게하면 함수 내에서 필요할 수있는 모든 메서드에 대해 암시 적 값 으로 사용할 수 있습니다 (물론 물론 명시 적으로 사용할 수 있습니다). 잘). 이 특별한 경우 Form 클래스의 bindFromRequest 메서드는 암시 적 Request 인수가 필요하기 때문에이 작업이 수행되었습니다.

Scala playframework 튜토리얼을 통해 내 길을 찾고 있었고, 나는이 코드 스 니펫을 통해 나를 혼란스럽게 만들었습니다.

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

명백한 사실 이외에 다른 메소드 이름을 가지고있다.

implicit 사용해야하는시기와 이유는 무엇입니까?


경고 : 현명하게 풍자를 포함합니다! YMMV ...

루이지의 대답 은 완전하고 정확합니다. 이것은 스칼라 프로젝트에서 아주 자주 일어나는 것처럼, 영리를 지나치게 과도하게 사용하는 방법에 대한 예제로 약간 확장하는 것입니다. 실제로 "Best Practice" 가이드 중 하나에서 찾을 수 있습니다.

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")
}

또한 위의 경우에는 double => Int 인 암시 적 함수가 only one 있어야합니다. 그렇지 않으면 컴파일러가 혼란스럽고 올바르게 컴파일되지 않습니다.

//this won't compile

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

request 매개 변수를 implicit 으로 표시해야하는 이유와시기 :

액션 본문에서 사용할 일부 메서드는 암시 적 매개 변수 목록 ( 예 : Form.scala)을 사용하여 메서드를 정의합니다.

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

myForm.bindFromRequest() 호출 할 때 반드시이를 myForm.bindFromRequest() 것은 아닙니다. 암시 적 인수를 명시 적으로 제공 할 필요는 없습니다. 아니요, 컴파일러 는 요청의 인스턴스가 필요한 메소드 호출을 찾을 때마다 전달할 유효한 후보 객체를 찾습니다. 요청을 사용할 수 있으므로 implicit 으로 표시해야합니다.

명시 적으로 암시 적 으로 사용할 수있는 것으로 표시합니다.

컴파일러는 Play 프레임 워크에서 전송 한 요청 객체를 "OK"라고 지정 했으므로 ( "요청"이라는 이름을 지정했지만 "r"또는 "req"만 사용할 수도 있음) 필요할 때마다 "교활한" .

myForm.bindFromRequest()

보지? 거기 있지는 않지만 거기에있다!

필요한 모든 장소에서 수작업으로 삽입하지 않아도됩니다 ( implicit 표시 되었든 원하지 않든 명시 적으로 전달할 수 있음).

myForm.bindFromRequest()(request)

암시 적으로 표시하지 않으면 위와 같은 조치 취해야합니다. 암시 적으로 표시하면 필요가 없습니다.

요청을 implicit 표시해야하는 시기언제 입니까? 요청의 인스턴스를 예상하는 암시 적 매개 변수 목록 을 선언하는 메서드를 사용하는 경우에만 필요합니다. 그러나 간단하게 유지하려면 요청을 implicit 으로 표시하는 습관을 들일 수 있습니다. 그렇게하면 멋진 간결한 코드를 작성할 수 있습니다.


"_"을 사용하는 특정 예제가 있습니다.

  type StringMatcher = String => (String => Boolean)

  def starts: StringMatcher = (prefix:String) => _ startsWith prefix

다음과 같을 수 있습니다.

  def starts: StringMatcher = (prefix:String) => (s)=>s startsWith prefix

일부 시나리오에서 "_"을 적용하면 자동으로 "(x $ n) => x $ n"





scala syntax playframework keyword