What does a Kotlin function signature with T.() mean?

This is a standard Kotlin function (as far as I know)

inline fun<T> with(t: T, body: T.() -> Unit) { t.body() }

But could anyone write in simple English what does exactly the signature mean? It's a generic function for T, with first argument "t" of type T and second, "body" of function type, accepting a function of ???? and returning nothing (Unit)

I see this notation Something.() -> Something is used pretty frequently, i.e. for Anko:

inline fun Activity.coordinatorLayout(init: CoordinatorLayout.() -> Unit) = ankoView({ CoordinatorLayout(it) },init)

but I don't think it was explained anywhere what .() means...


T.() -> Unit is an extension function type with receiver.

Besides ordinary functions, Kotlin supports extension functions. Such function differs from an ordinary one in that it has a receiver type specification. Here it's a generic T. part.

The this keyword inside an extension function corresponds to the receiver object (the one that is passed before the dot), so you can call its methods directly (referring to this from parent scopes is still possible with qualifiers).


Function with is a standard one, yes. It's current code:

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
 */
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()

So it's a generic function for T and R, with first argument "receiver" of type T and second, f of extension function type, which extends T, returning type R which in turn returned by the with.

For example, you can use it like this:

val threadInfoString = with (Thread.currentThread()) {
    // isDaemon() & getPriority() are called with new property syntax for getters & setters
    "${getName()}[isDaemon=$isDaemon,priority=$priority]"
}


See documentation for extension functions here:
kotlinlang.org/docs/reference/lambdas.html#extension-function-expressions
kotlinlang.org/docs/reference/scope-functions.html#with kotlinlang.org/docs/reference/extensions.html


Added:

So the only valid f would be any 0-argument function defined for T?

Not really. In Kotlin function types and extension function types are unified, so that they can be used interchangeably. For example, we can pass String::length where a function (String) -> Int is expected.

// map() expects `(String) -> Int`
// argument has type `String.() -> Int`
strings.map(String::length)

Types like Thread.() -> String & (Thread) -> String are the same from the background side – receiver, in fact, is the first argument.

So any of the following functions is suitable for Thread.() -> String argument:

fun main(args: Array<String>) {
    val f1 = fun Thread.(): String = name
    val f2 = fun Thread.() = name
    val f3: Thread.() -> String = { name }
    val f4: (Thread) -> String = { it.name }
    val f5 = { t: Thread -> t.name }
    val f6: (Thread) -> String = Thread::getNameZ
    val f7: Thread.() -> String = Thread::getNameZ
    val f8 = Thread::getNameZ
}

fun Thread.getNameZ() = name

Or you can simply use function literal ({}) as in the example with threadInfoString, but it works only when the receiver type can be inferred from the context.


This is another amazing concept named Function literals with receiver, It looks similar with extension function with difference that it has "receiver".

inline fun doSomethingWithInt(receiver: Int.() -> Unit) {

    5.receiver() //Possible as receiver is Int type

    receiver(5) //possible as receiver should be passed as first Argument
}

Let's break this apart

(receiver: Int.() -> Unit)

How this is different from Regular lambda like () -> Unit is it has receiver which is Type of Int

So similar to Extension function this receiver can invoke on Int type

5.receiver()

And as per the Documentation Here

A value of a function type can be invoked by using its invoke(...) operator:

f.invoke(x) or just f(x).

If the value has a receiver type, the receiver object should be passed as the first argument. Another way to invoke a value of a function type with receiver is to prepend it with the receiver object, as if the value were an extension function: 1.foo(2)

So You can also write receiver(5)

Now we can write DSL style code because of this. Let's see kotlin standard library function Apply

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

As you can see apply is an Extension function of T, block will be function with receiver type T,

Because of T.() T will be available as the first argument in lambda.

Now here block is invoked by block() inside function body, but you can also write this.block() or block(this)

And after invoking this lambda we will return instance of T(same instance on which apply is called)

So, what we did in apply is took lambda in argument, executed it on same instance T on which it was called, and return the same T instance

Example

Calling of this function will look like:

(StringBuilder("Hello ").apply({ append("Kotliner") }))

But in kotlin if lambda is last argument then instead of writing like funName({}) you can simply write funName{}.

so above code can be also written as

StringBuilder("Hello ").apply {
        append("Kotliner")
        append("! ")
    }

which looks more clear and concise. So this way Kotlin provides DSL structure like Groovy.

This is very nice blog about same Topic