What is a "receiver"?

I’m brand new to Kotlin, and have never used OOP ever. I’m trying to learn this language from scratch. I’m reading books, taking online courses, etc.
There are several concepts that I just can’t comprehend, and one of them at this time is “receivers”. In the Big Nerd Ranch book, chapter 9 “Standard Functions”, the “let”, “run”, “apply”, etc. scoping functions are introduced.
I’m having the darndest time understanding these functions and how they are all different. I think one thing that will help me understand these functions better, is understanding what a “receiver” is in general. I’ve found just a few explanations online, particularly over at stackoverflow, but I’m hoping somebody can speak more to my level, explain things a bit more simply and concisely.
So, what exactly is a receiver?

2 Likes

The question is answered pretty thoroughly in the official documentation. Have you read it? The same goes for scope functions. There are also several very low level articles about scope functions (just enter kotlin scope functions in google). StackOverflow is not the best place for learning kotlin. The starting point is the official documentation, then google for articles.

ADDENDUM: Those two particular questions are not about OOP, they are closer to kotlin functional side.

2 Likes

Indeed, I have read those resources including the official documentation. Indeed, I have done much google searching and reading. I find the official documentation to be too official–what I mean is that it is clearly written for software design professionals and experts, and I find it difficult to understand at my current level; especially when it gives the definition of a function using actual computer code and generics (generics are yet another thing I’m having difficulty grasping). For example, the Let function:
inline fun <T, R> T.let(block: (T) -> R): R
What I have found when trying to read and understand receivers and the scoping functions, is that many resources talk about a difference between “this” and “it”. These resources will say that the difference between let and run is that let references “it”, and run references “this”, as if I am supposed to understand based off of this fact alone. So, this in turn has been another point of confusion for me. I feel like that if I can better understand what a receiver is, perhaps I can better understand the difference between “it” and “this”, and then better understand the scoping functions.
I really learn best by asking questions. I can’t ask books, online tutorials, or even the official documentation questions. My hope was that I could join a group of knowledgeable Kotlin-ers and ask questions in a safe and understanding place, and perhaps get some teaching and explanations at my level.

I’d like to better understand what a receiver is, and how “this” and “it” relate to a receiver, what the difference between “this” and “it” are, and how they are different.
Thank you!

1 Like

OK, I just needed to check that. To many people are asking questions without trying to read first.

Let’s assume that we have the following code:

class A{
  val b: Int = 2

  fun doSomethingWithB(){
    println(this.b) // this will work because `this` references the object instance of A
    println(b) // this will work as well, because inside the object, you can omit a reference.
  }

The this identified points to the enclosing instance of the class. And it could be committed since we are inside of this instance. The receiver works the same way. The function called with a receiver is not actually inside the class, but public methods and field of the object could be called as though as from the inside.

For example, you can do this:

fun A.doOtherWithB(){
  println(b) // called as though as from the inside
}
1 Like

Thank you for the response. I’m not sure if I am understanding exactly what you are saying though.
That looks like a good example of the usage of “this”.
But I’m still not fully understanding what a receiver is.

I have continued to read sources, blogs, forums, code examples etc to try to understand better, and I do feel like I’m getting a better grasp.

From what I understand, a receiver is simply some object that has an extended function called on it, right? Nothing more complicated than that?

Now when it comes to “this” vs “it”: these are just shortcut keywords. “This” is used to refer to the object or “receiver” that an extended function is called on, while “it” is used to refer to a parameter being passed in a lambda/anonymous function. Do I have that right?
They clearly refer to different things, but both are still shortcuts available to make code more concise. I’m assuming that “this” and “it” can NOT be used in the same block of code, is that correct? For example, with Kotlin’s standard functions, like Let, “this” isn’t available because the scope is on the receiver as a parameter, not an object, whereas “it” can be used to refer to the parameter which is the receiver itself. But for functions like apply and run, “this” can be used because the receiver isn’t being passed into the lambda as a parameter, but they are acting on the receiver as an object, whereas “it” can’t be used because there is no parameter scoped in the apply or run function call.
Am I getting it?

1 Like

Yes.

Yes and no. For for functions like let and run this is right. You can construct a function which takes a lambda with both it and this.

fun foo(code: String.(Int) -> Unit){
    "test".code(5)
}

fun main(){
   foo {
       println(this)
       println(it)
   }
}

Here the code lambda has a reciever (of type String) and a single parameter (of type Int). So you can mix this and it but I can’t remember any real world example where this is done.


So the reciever is the part in an extension function before the function name. It pretends to be the class the function belongs to. It can either be accessed with this but same as for normal methods you can omitt the this keyword for properties like this.foo or function calls like this.bar().

It is another special case. Normaly when you create a lambda you need to name the parameters of that lambda

someList.filter { entry -> entry !=  foo }

However if a lambda only has a single parameter it will have a default name it.

someList.filter { it != foo }

If you want to you can still give it any name you like with the above syntax.

1 Like

Thanks Wasabi!

This lambda having a receiver is a new concept for me, and I’m confused about how this code is working. Would you be able to point me to several resources where I can find out more about passing a receiver in a lambda?

Thanks!!

1 Like

Not sure I can point you to a tutorial about it or anything specificly about this. There is a short paragraph about it in the official documentation:
https://kotlinlang.org/docs/reference/lambdas.html#function-types

Function types can optionally have an additional receiver type, which is specified before a dot in the notation: the type A.(B) -> C represents functions that can be called on a receiver object of A with a parameter of B and return a value of C . Function literals with receiver are often used along with these types.

As well as a part at the end of that page:
https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver

This SO answer could also be helpful

1 Like

A receiver is a special function argument. It differs from ordinary arguments in the following ways:

  • it does not have an explicit argument name
  • its implicit name within the function is “this”
  • its type is not provided within the paranthese after the function name, but instead before the function name separated by dot
  • when calling the function, the receiver’s value is not provided within the paranthese after the function name, but instead before the function name separated by dot
  • when calling the function, the receiver’s value does not need to be provided explicitly. If the current scope has a “this” already it can be provided implicitly
  • within the function body “this” can be omitted when accessing the receiver’s members or other extension functions

I am sure there are some more differences, but at your current level this should get you started understanding them.

1 Like

I am not sure if it will help you, but you can look through my article on more philosophical aspects of receivers. The idea is that in kotlin, the function not only have its arguments, but it also has a scope or context, where it is called. You have the same thing in any language that have objects with member functions, but in Kotlin you can detach the function from object and keep the reference to the context in the receiver. The receiver is designed that way in order for internal function logic to be the same when called inside and outside of the object.

1 Like

Here is a method call expression:

agent?.takeAction()

The ?. operator is used to create that method call expression. The expression on the left of the ?. is called the “receiver” of the method call.

Now, let’s look at a call to let.

agentFactory.createAgent()?.let { agent ->
    agent.takeAction()
}

The “receiver” of the let method call is the value of agentFactory.createAgent(). The agent variable in the lambda is bound to that value.

I could have written that code as

agentFactory.createAgent()?.let {
    it.takeAction()
}

If you do not specify a parameter in a single-parameter lambda, the parameter is implicitly given the name it. Just like agent before, it is bound to the value of the receiver of the let method call: agentFactory.createAgent().

I hope that helps.

Yes. It does indeed help. Just to quickly clarify the “?.” operator. You stated is it used to create a method call expression. From what I’ve been reading, that specific operator is used as a null safety operator/check, only running the code following the ?. operator if the receiver(?) isn’t null. Is that still true?

Yes indeed. Think of thing?.method(param) { //Do Stuff } as being basically syntatic sugar for the following code:

val localThing = thing
if (localThing != null) {
    localThing.method(param) { //Do Stuff }
}

(Notice the rescoping there. This basically captures the current value of thing, checks if it is not null, and then runs the method on it. This is what provides the power of extension scoping functions and makes stuff like thing?.let { } a really idiomatic way to do a null check and capture the value in just a couple characters in a clear way.)

I’ll throw my own, hopefully simple, explanation in.

When you call foo.bar(), the object foo is the receiver of the function call. This means that in the context of bar() there is a magic parameter called this which contains a reference to the object foo. The function bar() can use that to access properties and call functions in foo. For example, if foo has a property baz then from within the function bar() you could access it with this.baz. Becuase this is magic, you can leave it out and the compiler will know what you are talking about, so from within bar() you could directly reference baz without the this. part.