Is funcName(...) syntactic sugar for (::funcName).invoke(...)?

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.

1 Like

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.

2 Likes

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.

1 Like

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.

2 Likes

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.

1 Like