The subject asks it all: Is funcName(...)
just syntactic sugar for (::funcName).invoke(...)
? I guess so, but is this correct?
I’m not really sure this question has an answer, both work and (I think) always have in Kotlin.
In many other languages funcName(...)
is the syntax to call a function. The Function
types and invoke
methods are abstractions added later on to make fuctions look like interfaces.
It is not the same. A function in itself is not an object and does not have any invoke function. Referencing the function via ::funcNamr wraps the function in an object which provides the invoke function.
When called directly no objects are created.
Since functions are first class in Kotlin, both ways of expressing things should be equivalent, at least conceptually, right?
I assume that the compiler on the JVM translates funcName(...)
to a method call and (::funcName).invoke(...)
is reflective in nature. But the JVM is not the only target platform, that’s why I’m interested in the conceptual aspect.
Maybe it’s not about syntactic sugar but semantic equivalence.
Maybe. I think the difference is that funcName(...)
calls a function directly. ::funcName
returns a callable reference so (::funcName).invoke(...)
is more like first creating a reference to a function and then calling the function via that reference. Both in the end have the same effect but the reference requires one more step in between.
So it’s very much like methods and method references in Java, but these are platform specific details.
I would say that, conceptually, funcName
is a name of a function factory, very much like ClassName
is a name of a class type. The name as such is a compile time thing. If funcName
is used syntactically in a call context such as funcName(...)
, the runtime experiences no trace of an entity representing that function (and no hook to that entity) nor a trace to a method such as invoke
being involved (and no hook to such a method). The runtime experiences just the result of a function call. That means the compiler is entitled to optimze a function call in whatever way as long as there is nothing observable or accessible to the runtime.
On the other hand, ::funcName
sets the function name in another syntactic context and refers to an instance of a KFunction
, an instance that is accessible to the runtime for reflection purposes and being callable as defined by the supertype KCallable
of KFunction
and being invokeable as defined by the supertype Function
of KFunction
.
That means: The function name of a function declaration used in a call context refers to the concept of a function call, which is not meant to be an instance of whatever type. Used in the context of a callable reference, the function name refers to an instance of Function
among others, namely KFunction
and KCallable
.