The subject asks it all: Is
funcName(...) just syntactic sugar for
(::funcName).invoke(...)? I guess so, but is this correct?
The subject asks it all: Is
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
KFunction and being invokeable as defined by the supertype
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