Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Note] "funtion literal with receiver 언제 쓰세요?? #50

Closed
cwdoh opened this issue Sep 11, 2017 · 2 comments
Closed

[Note] "funtion literal with receiver 언제 쓰세요?? #50

cwdoh opened this issue Sep 11, 2017 · 2 comments

Comments

@cwdoh
Copy link
Member

cwdoh commented Sep 11, 2017

선데이사당 모임에서 문득 @Pluu 님의 질문:

"function literal with receiver 언제 쓰세요??"

차이를 알아보기 위해 간단하게 decompile

fun main(args: Array<String>) {
    100.pluu {
        print(it)
    }

    100.pluu2 {
        print(this)
    }
}

fun Int.pluu(block: (it: Int) -> Unit) = block(this)
fun Int.pluu2(block: Int.() -> Unit) = block()
  • 간단하게 보면 this의 사용 가능여부인데,
public final class DemoKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      pluu(100, (Function1)null.INSTANCE);
      pluu2(100, (Function1)null.INSTANCE);
   }

   public static final void pluu(int $receiver, @NotNull Function1 block) {
      Intrinsics.checkParameterIsNotNull(block, "block");
      block.invoke(Integer.valueOf($receiver));
   }

   public static final void pluu2(int $receiver, @NotNull Function1 block) {
      Intrinsics.checkParameterIsNotNull(block, "block");
      block.invoke(Integer.valueOf($receiver));
   }
}

똑같다. -_-;

2차 시도

일단 내용을 알아보도록 하자.

사실 이 답변이 제일 맞다고 생각한다.

A lambda with receiver is something that you can pass to another function, so that the other function would call it, and pass the receiver object that you would be able to access in the body of the lambda. An extension function is something that you can only call directly.

수신자를 가지는 람다는 다른 함수로 전달 가능한 존재이다. 즉, 다른 함수가 이를 호출하고, 람다의 바디에 접근할 수 있는 수신자 객체를 전달할 수 있다. 익스텐션 함수는 그저 직접 호출 가능한 존재이다.
내가 써놓고도 뭔소린가 싶다.

간단하게 이런 뜻이다.

  • this의 사용 유무를 가장 중요한 기준으로 할 때
  • this를 사용할 수 있다는 것은 람다 자체를 넘기는 것만으로도 객체에 대한 레퍼런스는 따라 간다는 뜻이다.
  • 반대로 this를 사용할 수 없음은 객체에 대한 레퍼런스를 유지하기 위해 이를 직접 매개 변수로 넘겨야 한다.

with receiver

fun Int.pluu2(block: Int.() -> Unit) = block()
fun main(args: Array<String>) {
    100.pluu2 {
        print(this)
    }
}

pluu2에서 그저 block()을 호출했음에도 this는 자연스럽게 따라간다.

fun Int.pluu(block: (it: Int) -> Unit) = block(this)
fun main(args: Array<String>) {
    100.pluu {
        print(it)
    }
}

pluu는 매개 변수를 넘겨야 한다.

TODO: Standard.kt를 파보기로 한다.

public inline fun <R> run(block: () -> R): R = block()

public inline fun <T, R> T.run(block: T.() -> R): R = block()

public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()

public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
@Pluu
Copy link
Contributor

Pluu commented Sep 11, 2017

=ㅅ= 파고파고하면 자동으로 this를 넘겨주냐 아니냐의 느낌이...

@cwdoh
Copy link
Member Author

cwdoh commented Sep 13, 2017

매개변수로 this를 넘길 수는 있지만 그냥 리시버로 만들면 계속 this가 따라다니는 편리함이지 않을런지

@cwdoh cwdoh closed this as completed Nov 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants