복붙노트

[SCALA] 익명 함수 대에 의해-name 매개 변수

SCALA

익명 함수 대에 의해-name 매개 변수

게으른 평가 및 기타 혜택 (있는 경우)의 관점에서 익명 함수를 통해 장점으로 이름 매개 변수를 무엇이고 무엇은 아직 불분명하다 :

def func1(a: => Int)
def func2(a: () => Int)

언제 두 번째 제 때를 사용해야합니까?

이 =의 차이는 무엇의 사본 아니다> () => 및 단위 =>

해결법

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

    1.게으름은 두 경우 모두 동일하지만, 약간의 차이가 있습니다. 치다:

    게으름은 두 경우 모두 동일하지만, 약간의 차이가 있습니다. 치다:

    def generateInt(): Int = { ... }
    def byFunc(a: () => Int) { ... }
    def byName(a: => Int) { ... }
    
    // you can pass method without
    // generating additional anonymous function
    byFunc(generateInt)
    
    // but both of the below are the same
    // i.e. additional anonymous function is generated
    byName(generateInt)
    byName(() => generateInt())
    

    통화 별 이름을 가진 기능 그러나 DSL을 만들기위한 유용합니다. 예를 들어 :

    def measured(block: ⇒ Unit): Long = {
      val startTime = System.currentTimeMillis()
      block
      System.currentTimeMillis() - startTime
    }
    
    Long timeTaken = measured {
      // any code here you like to measure
      // written just as there were no "measured" around
    }
    
  2. ==============================

    2.

      def func1(a: => Int) {
        val b = a // b is of type Int, and it`s value is the result of evaluation of a
      }
    
    def func2(a: () => Int) {
        val b = a // b is of type Function0 (is a reference to function a)
      }
    
  3. ==============================

    3.예는 차이가 꽤 철저한 투어를 줄 수 있습니다.

    예는 차이가 꽤 철저한 투어를 줄 수 있습니다.

    당신은 스칼라의 진정한 while 루프의 자신의 버전을 쓰고 싶었다 것을 고려하십시오. 스칼라에있는 동안 내가 사용 ... 알아, 알아? 그러나 이것은이 주제를 잘 보여주는 예입니다, 함수형 프로그래밍에 대해 없습니다. 그래서 나와 함께 걸어. 우리는 우리 자신의 버전 whyle 전화 할게. 또한, 우리는 스칼라의 내장 동안 사용하지 않고 그것을 구현하고자합니다. 우리는 우리의 whyle 구조의 순환을 할 수 떨어져 있음을 당깁니다. 또한, 우리는 우리의 구현을위한 실제 대용으로 사용 할 수 있는지 확인하기 위해 @tailrec 주석을 추가 할 것입니다 내장 동안. 여기에서 첫 번째 이동이다 :

    @scala.annotation.tailrec
    def whyle(predicate: () => Boolean)(block: () => Unit): Unit = {
      if (predicate()) {
        block()
        whyle(predicate)(block)
      }
    }
    

    의이 어떻게 작동하는지 살펴 보자. 우리는 whyle에 파라미터로 코드 블록에 전달할 수 있습니다. 먼저 조건 매개 변수 기능입니다. 두번째 블록 파라미터 함수이다. 우리는 이것을 어떻게 사용해야합니까?

    우리의 최종 사용자가 당신이 것 동안 제어 구조처럼 whyle를 사용하는 우리가 원하는 것은 :

    // Using the vanilla 'while'
    var i = 0
    while(i < args.length) {
      println(args(i))
      i += 1
    }
    

    우리의 코드 블록이 파라미터되기 때문에 그러나, 우리의 whyle 루프의 최종 사용자 작업에 얻을 못생긴 문법 설탕을 추가해야합니다 :

    // Ouch, our whyle is hideous
    var i = 0
    whyle( () => i < args.length) { () =>
      println(args(i))
      i += 1
    }
    

    그래서. 우리가 최종 사용자가 더 잘 알고, 기본보고 스타일로 우리의 whyle 루프를 호출 할 수 있도록하려면, 우리가 사용하는 매개 변수가 함수에 필요합니다 것으로 보인다. 그러나 우리는 정말 큰 문제가있다. 즉시이 매개 변수가없는 함수를 사용하여, 당신은 더 이상 케이크를 가질 수와도 그것을 먹는다. 당신은 당신의 케이크를 먹을 수 있습니다. 보다:

    @scala.annotation.tailrec
    def whyle(predicate: => Boolean)(block: => Unit): Unit = {
      if (predicate) {
        block
        whyle(predicate)(block)  // !!! THIS DOESN'T WORK LIKE YOU THINK !!!
      }
    }
    

    와. 이제 사용자가 우리의 whyle 루프가 예상대로 호출 할 수 있습니다 ...하지만 우리의 구현은 이해가되지 않습니다. 당신은 둘 다 매개 변수가 함수를 호출하고 값으로 주위의 기능 자체를 전달하는 방법이 없습니다. 당신은 그것을 호출 할 수 있습니다. 그건 내가 단지 당신의 케이크를 먹고 무엇을 의미합니다. 당신도 그것을 가질 수 없습니다. 그러므로 우리의 재귀 구현은 지금 창 밖을 간다. 그것은 단지 불행하게도 꽤 추한 인 파라미터 기능을 사용할 수 있습니다.

    우리는 속임수를이 시점에서 유혹 될 수 있습니다. 우리는 스칼라를 사용하는 우리의 whyle 루프를 다시 쓸 수있는 내장에있는 동안 :

    def whyle(pred: => Boolean)(block: => Unit): Unit = while(pred)(block)
    

    우리는 우리의 케이크를 먹을 수있을 필요가 있었기 때문에 이제 우리는 우리가 너무, 그것을 가지고 필요가 없었다 ... 정확히 동안 같은 우리의 whyle를 사용할 수 있습니다.

    var i = 0
    whyle(i < args.length) {
      println(args(i))
      i += 1
    }
    

    그러나 우리는 사기! 사실, 여기에 while 루프의 우리 자신의 꼬리에 최적화 된 버전을 사용하는 방법이있다 :

    def whyle(predicate: => Boolean)(block: => Unit): Unit = {
      @tailrec
      def whyle_internal(predicate2: () => Boolean)(block2: () => Unit): Unit = {
        if (predicate2()) {
          block2()
          whyle_internal(predicate2)(block2)
        }
      }
      whyle_internal(predicate _)(block _)
    }
    

    당신은 우리가 무슨 짓을했는지 알아낼 수 있습니까 ?? 우리는 여기에 내부 기능에 우리의 파라미터 원래 (하지만 추한) 기능을 가지고 있습니다. 우리는 인수 매개 변수가 함수로 취하는 함수에 싸여있다. 그러므로 내부 함수를 호출하고 (일부 적용 함수로 돌려) 파라미터 함수에 매개 변수가 함수를 변환한다.

    그것이 작동하는 경우의 그것을 밖으로 시도하고 보자 :

    var i = 0
    whyle(i < args.length) {
      println(args(i))
      i += 1
    }
    

    그리고 그것은 않습니다!

    스칼라에서 우리는 클로저를 갖고 있기 때문에 다행히, 우리는 큰 시간까지이 문제를 정리할 수 있습니다 :

    def whyle(predicate: => Boolean)(block: => Unit): Unit = {
      @tailrec
      def whyle_internal: Unit = {
        if (predicate) {
          block
          whyle_internal
        }
      }
      whyle_internal
    }
    

    시원한. 어쨌든, 사람들은 매개 변수가 매개 변수화 기능 사이에 정말 큰 차이가 있습니다. 나는 이것이 당신에게 몇 가지 아이디어를 제공 바랍니다!

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

    4.두 형식은 같은 의미로 사용됩니다,하지만 우리는 테마의 하나를 사용할 수있는 몇 가지 경우가 있습니다.

    두 형식은 같은 의미로 사용됩니다,하지만 우리는 테마의 하나를 사용할 수있는 몇 가지 경우가 있습니다.

    우리는 두 개의 매개 변수가있는 경우 클래스를 정의 할 필요가 가정의 예에 의해 설명 할 수 있습니다 :

    {
      .
      .
      .
      type Action = () => Unit;
    
      case class WorkItem(time : Int, action : Action);
      .
      .
      .
    
    }
    

    우리가 볼 수 있듯이, 작업 항목 클래스의 두 번째 매개 변수는 유형의 조치가 있습니다.

    우리는 다른 형식이 매개 변수를 대체하려고하면 =>,

    경우 클래스 WorkItem1 (시간 : 지능은 S : => 단위) 컴파일러 메시지 오류가 표시됩니다 :

    우리는 () 형식을 볼 수있을 정도로 => 더 일반적인이며, 우리는 방법을 매개 변수로 사용하지만 클래스 필드로 할 수있는 다른 측면 => 형식으로 클래스 필드 나 메소드의 매개 변수로, 유형을 정의하는 데 사용할 수 있습니다.

  5. ==============================

    5.당신이 인수 이름으로 int로 전달하려는 경우 첫 번째 함수 정의를 사용해야합니다. 당신은 인수가 int를 반환하는 매개 변수가 함수가 될하려는 경우 두 번째 정의를 사용합니다.

    당신이 인수 이름으로 int로 전달하려는 경우 첫 번째 함수 정의를 사용해야합니다. 당신은 인수가 int를 반환하는 매개 변수가 함수가 될하려는 경우 두 번째 정의를 사용합니다.

  6. from https://stackoverflow.com/questions/19948598/by-name-parameter-vs-anonymous-function by cc-by-sa and MIT license