How resolving Kotlin functions/properties with the same name work? - kotlin

The following statement compiles and prints "fun: called":
fun main(vararg args: String) {
fun toCall(arg: String) = println("fun: $arg")
val toCall = fun(arg: String) = println("val: $arg")
toCall("called")
}
Note: the same problem would arise if they were top level declarations or inside a class, this is just the simplest repro with local function/variable.
Looking for clarification on why this compiles in the first place?
What rule comes into play that picks the function over the property?
Note: it's possible to call the val one through:
(toCall)("called")
toCall.invoke("called")

This document regarding name resolution contains details about it.
I will just quote some passages out of it specifically dealing with your problem. It contains several other interesting things as well, but I think I would end up copying everything here then ;-) If you are interested, I can only recommend you to read it completely.
Summarizing, the compiler divides the functions (member/extension/member extension)/properties into groups and decides which one to call first... The properties are put in the group of the invoke-functions and in the following passage you already see why the function was taken before your val:
The property is considered together with the invoke function. Groups of properties with invoke functions are mixed with groups of regular functions, in a sense that a group of properties can have higher priority than a group of functions and vice versa. However, functions and properties can’t go in one group: the function always surpasses the property of the same category. Both the property and the invoke function determine the priority of the group: we compare the priority of the property and of the invoke function and the "lowest" one becomes the group priority.
That's why the function was considered first here and the property later. As soon as you specified invoke it was clear that it can only be the property as the function itself has no visible invoke (lets not go down the byte code now ;-)). Now (toCall) behaves similarly. Here it is clear, that toCall can only be the property. It isn't possible to call (toCall) with the function (compile errors: function invocation expected / the function invoke is not found).
The linked document also contains a sample with a member property function followed by this statement, which basically also confirms the previous regarding local functions:
Note that there is no member function named foo, but if it was present, it would be put into a separate group with the highest priority.

Related

Kotlin construction: function call with additional body - what such construction means or how it is called (if I want to look it up in the docs)?

I am seeing the Kotlin code:
navController.navigate("sales_order/" + it.toString()) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
which I can describe as "function call" (navController.navigate) "with additional body" ({...}). How such construction is called (if I want to look it up in the docs) and what does it mean?
When I checked the type of navController.navigate(...) args, then there are 2 arguments. The first argument - string - is provided in () and I am trying to guess, that everything inside {...} is the content for the second argument which has type NavOptionsBuilder in this case. So, I can guess that NavOptionsBuilder has 3 arguments: 1 function call popUpTo that returns some object and 2 named arguments (launchSingleTop, restoreState) which are Boolean type.
Am I deciphering this construction right - just another way of passing arguments - or is there something deeper?
Am I deciphering this construction right
Almost. You got the beginning right, but the end is not exactly correct.
Let's start with what you got right, and throw in some vocabulary here for posterity. Indeed, you seem to be using the overload of navigate that takes 2 arguments: a string route and a builder function.
Functions in kotlin can be passed in multiple ways, but the most common (and the one used here) is passing a lambda expression. Because the syntax for lambda expressions is based on braces ({ ... }), it makes it look like blocks of code, so the Kotlin language went one step further and allowed to pass lambda expressions outside of the parentheses of the function call when the lambda is the last argument. The reason for this is exactly to allow this kind of constructions which look like their own configuration language. This is what is usually referred to as DSLs (Domain Specific Languages).
Now about what you got wrong:
So, I can guess that NavOptionsBuilder has 3 arguments
Not really. NavOptionsBuilder is the receiver of the function that is passed as the second argument of navigate. This means that, within the lambda that you pass, a NavOptionsBuilder instance is implicitly available as this.
This, in turn, means that you can access methods and properties of NavOptionsBuilder within that lambda block. This is what popUpTo, launchSingleTop, and restoreState are: methods and properties of NavOptionsBuilder - not "arguments".
You can find more general info about this here.

Terraform module as "custom function"

It is possible to use some i.e. local module to return let' say same calculated output. But how can you pass some parameters? So each time you will ask for the output value you will get different value according to the parameter(ie different prefix)
Is it possible to pass resource to module and enhance it with tags?
I can imagine that both cases are more likely to be case for providers, but for some simple case it should work maybe. The best would be if they implemented some custom function that you will be able to call at will.
It is possible in principle to write a Terraform module that only contains "named values", which is the broad term for the three module features Input Variables (analogous to function arguments), Local Values (analogous to local declarations inside your function), and Output Values (analogous to return values).
Such a module would not contain any resource or data blocks at all and would therefore be a "computation-only" module, which therefore has all of the same capabilities as a function in a functional programming language.
variable "a" {
type = number
}
variable "b" {
type = number
}
locals {
sum = var.a + var.b
}
output "sum" {
value = local.sum
}
The above example is contrived just to show the principle. A "function" this simple doesn't really need the local value local.sum, because its expression could just be written inline in the value of output "sum", but I wanted to show examples of all three of the relevant constructs here.
You would "call the function" by declaring a module call referring to the directory containing the file with the above source code in it:
module "example" {
source = "./modules/sum"
a = 1
b = 2
}
output "result" {
value = module.example.sum
}
I included the output "result" block here to show how you can refer to the result of the "function" elsewhere in your module, as module.example.sum.
Of course, this syntax is much more "chunky" than a typical function call, so in practice Terraform module authors will use this approach only when the factored out logic is significant enough to justify it. Verbosity aside though, you can include as many module blocks referring to that same module as you like if you need to call the "function" with different sets of arguments. Each call to the module can take a different set of input variable values and therefore produce a different result.

How can one invoke the non-extension `run` function (the one without scope / "object reference") in environments where there is an object scope?

Example:
data class T(val flag: Boolean) {
constructor(n: Int) : this(run {
// Some computation here...
<Boolean result>
})
}
In this example, the custom constructor needs to run some computation in order to determine which value to pass to the primary constructor, but the compiler does not accept the run, citing Cannot access 'run' before superclass constructor has been called, which, if I understand correctly, means instead of interpreting it as the non-extension run (the variant with no object reference in https://kotlinlang.org/docs/reference/scope-functions.html#function-selection), it construes it as a call to this.run (the variant with an object reference in the above table) - which is invalid as the object has not completely instantiated yet.
What can I do in order to let the compiler know I mean the run function which is not an extension method and doesn't take a scope?
Clarification: I am interested in an answer to the question as asked, not in a workaround.
I can think of several workarounds - ways to rewrite this code in a way that works as intended without calling run: extracting the code to a function; rewriting it as a (possibly highly nested) let expression; removing the run and invoking the lambda (with () after it) instead (funnily enough, IntelliJ IDEA tags that as Redundant lambda creation and suggests to Inline the body, which reinstates the non-compiling run). But the question is not how to rewrite this without using run - it's how to make run work in this context.
A good answer should do one of the following things:
Explain how to instruct the compiler to call a function rather than an extension method when a name is overloaded, in general; or
Explain how to do that specifically for run; or
Explain that (and ideally also why) it is not possible to do (ideally with supporting references); or
Explain what I got wrong, in case I got something wrong and the whole question is irrelevant (e.g. if my analysis is incorrect, and the problem is something other than the compiler construing the call to run as this.run).
If someone has a neat workaround not mentioned above they're welcome to post it in a comment - not as an answer.
In case it matters: I'm using multi-platform Kotlin 1.4.20.
Kotlin favors the receiver overload if it is in scope. The solution is to use the fully qualified name of the non-receiver function:
kotlin.run { //...
The specification is explained here.
Another option when the overloads are not in the same package is to use import renaming, but that won't work in this case since both run functions are in the same package.

Is there a Kotlin std lib function to copy a list, removing all elements equal to ONE single element? A function taking only one non-collection arg?

Given a list of arbitrary objects
input = listOf(a, b, c, a)
... is there a function (with one non-collection argument) in the Kotlin standard library that I can use to make a copy of this list, removing all instances of ONE object?
Something like:
val filtered = input.removeAllInstancesOf(a)
To clarify, I'm aware of other (potential) solutions to this task:
Using the filter function to do this. → val output = input.filterNot { it == a }
Using the minus function with a collection → val output = input.minus(listOf(a))
Using the minus function with a non-collection argument → val output = input.minus(a) ← Only removes the first instance of a!
Removing all instances from a mutable list.
Writing such a function. → Wrap any of the above.
... but I'm wondering why I can't find a function which takes just ONE, non-collection value.
but I'm wondering why I can't find a function which takes just ONE, non-collection value.
Because that's a hyper-specific use-case of the already existing filter function. As you yourself showed it can be done in one line, and is probably the first thing a Kotlin dev would try to do (at least I would). So adding new function to the standard library probably doesn't add much value.

Kotlin syntax issue

Sorry for the terrible title, but I can't seem to find an allowable way to ask this question, because I don't know how to refer to the code constructs I am looking at.
Looking at this file: https://github.com/Hexworks/caves-of-zircon-tutorial/blob/master/src/main/kotlin/org/hexworks/cavesofzircon/systems/InputReceiver.kt
I don't understand what is going on here:
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (_, _, uiEvent, player) = context
I can understand some things.
We are overriding the update function, which is defined in the Behavior class, which is a superclass of this class.
The update function accepts two parameters. A GameEntity named entity, and a GameContext called context.
The function returns a Boolean result.
However, I do not understand the next line at all. Just open and close parentheses, two underscores as the first two parameters, and then an assignment to the context argument. What is it we are assigning the value of context to?
Based on IDE behavior, apparently the open-close parentheses are related to the constructor for GameContext. But I would not know that otherwise. I also don't understand what the meaning is of the underscores in the argument list.
And finally, I have read about the declaration-site variance keyword "out", but I don't really understand what it means here. We have GameEntity<out EntityType>. So as I understand it, that means this method produces EntityType, but does not consume it. How is that demonstrated in this code?
val (_, _, uiEvent, player) = context
You are extracting the 3rd and 4th value from the context and ignoring the first two.
Compare https://kotlinlang.org/docs/reference/multi-declarations.html .
About out: i don't see it being used in the code snippet you're showing. You might want to show the full method.
Also, maybe it is there only for the purpose of overriding the method, to match the signature of the function.
To cover the little bit that Incubbus's otherwise-great answer missed:
In the declaration
override fun update(entity: GameEntity<out EntityType>, // …
the out means that you could call the function and pass a GameEntity<SubclassOfEntityType> (or even a SubclassOfGameEntity<SubclassOfEntityType>).
With no out, you'd have to pass a GameEntity<EntityType> (or a SubclassOfGameEntity<EntityType>).
I guess that's inherited from the superclass method that you're overriding.  After all, if the superclass method could be called with a GameEntity<SubclassOfEntityType>, then your override will need to handle that too.  (The Liskov substitution principle in action!)