Programming

=>, () => 및 Unit =>의 차이점은 무엇입니까?

procodes 2020. 6. 18. 21:59
반응형

=>, () => 및 Unit =>의 차이점은 무엇입니까?


인수를 취하지 않고 값을 반환하지 않는 함수를 나타내려고합니다 (알아야하는 경우 JavaScript에서 setTimeout 함수를 시뮬레이션하고 있습니다).

case class Scheduled(time : Int, callback :  => Unit)

"val"매개 변수가 이름별로 호출되지 않을 수 있습니다 "라고 컴파일하지 않습니다.

case class Scheduled(time : Int, callback :  () => Unit)  

컴파일하지만 대신 이상하게 호출해야합니다.

Scheduled(40, { println("x") } )

나는 이것을해야한다

Scheduled(40, { () => println("x") } )      

작동하는 것은

class Scheduled(time : Int, callback :  Unit => Unit)

그러나 똑같이 합리적인 방식으로 호출됩니다

 Scheduled(40, { x : Unit => println("x") } )

(Unit 유형의 변수는 무엇입니까?) 물론 원하는 것은 일반적인 함수 인 경우 호출하는 방식을 호출 할 수있는 생성자입니다.

 Scheduled(40, println("x") )

아기에게 병을 줘!


이름 별 전화 : => 유형

=> Type표기법은 이름 별 호출을 나타내며 매개 변수를 전달할 수있는 많은 방법 중 하나입니다 . 익숙하지 않다면 요즘 위키 백과 기사를 읽어 보는 것이 좋습니다. 요즘은 대부분의 가치 별 기준이며 기준 별 기준입니다.

의미는 전달 된 것이 함수 내부의 값 이름으로 대체 된다는 것입니다 . 예를 들어 다음 기능을 사용하십시오.

def f(x: => Int) = x * x

이렇게 전화하면

var y = 0
f { y += 1; y }

그런 다음 코드는 다음과 같이 실행됩니다

{ y += 1; y } * { y += 1; y }

식별자 이름 충돌이 발생하면 어떤 일이 발생하는지 지적합니다. 기존의 이름 별 통화에서는 이름 충돌을 피하기 위해 캡처 방지 대체라는 메커니즘이 사용됩니다. 그러나 Scala에서는 동일한 결과로 다른 방식으로 구현됩니다. 즉, 매개 변수 내의 식별자 이름은 호출 된 함수의 식별자를 참조하거나 섀도 잉 할 수 없습니다.

다른 두 가지를 설명한 후에 언급 할 이름 별 통화와 관련된 몇 가지 다른 점이 있습니다.

0-arity 함수 : () => Type

구문 () => Type은의 유형을 나타냅니다 Function0. 즉, 매개 변수를 사용하지 않고 무언가를 반환하는 함수입니다. 이는 메서드를 호출하는 것과 같습니다 size(). 매개 변수를 사용하지 않고 숫자를 반환합니다.

그러나이 구문은 익명 함수 리터럴 의 구문과 매우 유사하다는 점이 흥미 롭습니다. 이는 혼동의 원인이됩니다. 예를 들어

() => println("I'm an anonymous function")

arity 0의 익명 함수 리터럴이며 유형

() => Unit

그래서 우리는 쓸 수 있습니다 :

val f: () => Unit = () => println("I'm an anonymous function")

그러나 유형과 값을 혼동하지 않는 것이 중요합니다.

단위 => 유형

이것은 실제로 단지 Function1첫 번째 매개 변수 유형 Unit입니다. 작성하는 다른 방법은 (Unit) => Type또는 Function1[Unit, Type]입니다. 문제는 ... 이것이 원하는 것이 아닐 것입니다. Unit유형의 주요 목적은 그래서 이해가되지 않습니다에 관심되지 않은 값을 표시한다 받을 그 값을.

예를 들어,

def f(x: Unit) = ...

무엇을 할 수 x있습니까? 단일 값만 가질 수 있으므로받을 필요가 없습니다. 가능한 함수 중 하나는 다음을 반환하는 체인 함수입니다 Unit.

val f = (x: Unit) => println("I'm f")
val g = (x: Unit) => println("I'm g")
val h = f andThen g

andThen정의되어 Function1있고 우리가 연결하는 함수가 반환되고 있기 때문에이를 연결 시킬 수 Unit있는 유형으로 정의해야 Function1[Unit, Unit]했습니다.

혼란의 근원

혼동의 첫 번째 원인은 0-arity 함수에 존재하는 유형과 리터럴의 유사성이 이름 별 호출에도 존재한다고 생각하는 것입니다. 다른 말로하면

() => { println("Hi!") }

의 리터럴입니다 () => Unit.

{ println("Hi!") }

의 리터럴이됩니다 => Unit. 그렇지 않습니다. 그것은 리터럴이 아닌 코드 블록입니다 .

Another source of confusion is that Unit type's value is written (), which looks like a 0-arity parameter list (but it is not).


case class Scheduled(time : Int, callback :  => Unit)

The case modifier makes implicit val out of each argument to the constructor. Hence (as someone noted) if you remove case you can use a call-by-name parameter. The compiler could probably allow it anyway, but it might surprise people if it created val callback instead of morphing into lazy val callback.

When you change to callback: () => Unit now your case just takes a function rather than a call-by-name parameter. Obviously the function can be stored in val callback so there's no problem.

The easiest way to get what you want (Scheduled(40, println("x") ) where a call-by-name parameter is used to pass a lambda) is probably to skip the case and explicitly create the apply that you couldn't get in the first place:

class Scheduled(val time: Int, val callback: () => Unit) {
    def doit = callback()
}

object Scheduled {
    def apply(time: Int, callback: => Unit) =
        new Scheduled(time, { () => callback })
}

In use:

scala> Scheduled(1234, println("x"))
res0: Scheduled = Scheduled@5eb10190

scala> Scheduled(1234, println("x")).doit
x

In the question, you want to simulate SetTimeOut function in JavaScript. Based on previous answers, I write following code:

class Scheduled(time: Int, cb: => Unit) {
  private def runCb = cb
}

object Scheduled {
  def apply(time: Int, cb: => Unit) = {
    val instance = new Scheduled(time, cb)
    Thread.sleep(time*1000)
    instance.runCb
  }
}

In REPL, we can get something like this:

scala> Scheduled(10, println("a")); Scheduled(1, println("b"))
a
b

Our simulation doesn't behave exactly the same as SetTimeOut, because our simulation is blocking function, but SetTimeOut is non-blocking.

참고URL : https://stackoverflow.com/questions/4543228/whats-the-difference-between-and-unit

반응형