What is the kotlin version of out keyword for arguments?

as far as I know, the arguments can’t be declared out’s because they are val’s, hence readonly, but is there a substitute method for the out keyword in java for kotlin other than writing wrappers for every class? Also, if the only way to overcome this is writing wrappers, wouldn’t it better to just integrate it into the language at this point?

I’m not sure there is much use for out (aka, output parameters) in Kotlin like there is in C#.

I’m not very familiar with C# so forgive me if I’m misrepresenting it.
If I understand correctly, the popular uses for out in C# are:

  1. To avoid checked exceptions and being forced to write try-catch blocks. Kotlin doesn’t have checked exceptions.
  2. To return multiple values from a method instead of making another container. In Kotlin we have data classes and value classes. Microsoft says this is bad in their guidance
  3. Some other reason I’m missing?

For those coming from Java, output parameters are a major code smell. Unlike C++ where APIs often use output parameters, Java rarely does. In Clean Code by Robert Martin, there are some good insights into output parameters. Even Microsoft puts caution into using out (see Avoid using out).

Over the years of language evolution, I think it’s safe to say that the consensus of “output params” is that they are to be avoided when possible, and they might be a good target for eliminating the need for them in your language (for a language designer).

Maybe you could describe what you’re trying to do with out in Kotlin code? There’s a chance an alternative exists that might get you what you want :slight_smile:

2 Likes

+1 for saying out params is a very bad pattern. Functions have clearly defined input and outputs. Just don’t use inputs as they are outputs. So no, don’t use wrappers. Just return the value you need.

Out params make sense on low-level languages like C/C++, because it allows to pass data efficiently.

2 Likes

Why would you even need a wrapper for every class? You can have a generic ValueHolder<T> class which works for every type. Still this is a very bad idea and probably more typing still than returning an appropriate data class.

1 Like

the thing is, i have some optional outputs from a function, like the the result of the calculation of some other thing that gets calculated while the function is being processed

Cool! This is a more valuable question :slight_smile: Are those outputs optionally calculated or are they always calculated and optionally retrieved by the caller?

I’d still say output params are not a good answer for returning optional values (and according to Microsoft, is something you want to avoid in C# just as much as in Kotlin).

One solution is to return the calculation result in a container of some sort with all of the values. This means instead of wrapping the inputs you return a data class of results.
Alternatively, you could have your functions work within a contextual class that holds the state (ins/outs) of the calculation.

The nice thing is this kind of question is a common problem when designing functions and you’re not alone. The more info into what you’re trying to do the easier it is to suggest the best patterns. Output params and passing by reference will be close to last on the suggestion list :wink:

2 Likes

whether or not it’s calculated really depends, like in one algorithm, I sometimes might want to output some of the variables that are used, then some other time i might calculate it if the given argument != null, or I can just create a data class or a wrapper for being able to modify primitives like @al3c suggested

Just create a data class with all your mandatory and optional data and return it from the function. This is much easier to follow by anyone who use this function.

2 Likes

Most shader languages have this feature, they are just syntax-sugar so you don’t have to write wrapper-Struct to handle arbitrary multiple output (shaders do not have pointers, those are value copies anyway).

Since Kotlin can assign local variable in inline functions, I think having this compiler feature that does similar thing is great since you can avoid writing wrapper-class/ receiver-function just for 2 integer return.
To be more safe, I think it should only work on primitives and/ or must have a explicit keyword on variable declaration.

Something like:

fun compute(arg: Int, output out1: Int, output out2: Int) {}
fun main(){
  //must specify variable as output
  output var result1: Int
  output var result2: Int
  
  compute(arg=1,out1= result1,out2= result2)
  
  //similar to 
  computeWithReceiver(arg=1){ out1, out2 ->
     result1 = out1
     result2 = out2
  }

}

I randomly came across this old thread and I couldn’t help but dig it up.

Most of my career has been in Java (and now Kotlin) and a fair amount of C/C++.
The only use I have for C# is writing games in Unity 3D.

From a game development perspective, out-args provide a valuable optimization in C#.

In Java where we might define a class to envelop the data we wish to return, that class will be allocated from the heap and must later be garbage collected. In Java we are taught to embrace garbage collection because we’re typically not building a system that polls 120+ times per second and nit picking at every frame drop. If we are building such a thing, then we must turn to pooling in Java which has other forms of overhead and complexity.

C# gives us two options that Java does not:

  1. A struct instead of a class. Structs are allocated from the stack and the memory is freed when the instance falls out of scope (like local primitives in Java).

  2. Out-Args allow the ability to return multiple values from a method without defining a struct. This is arguably equal in performance to defining and returning a struct. However it supports the old-school pattern of using the return-value as an error/status which saves against null/value checks or constructing massive Exception objects (which also go on the heap).

So I agree with the bad pattern smell, but it does have it’s use.
The way I sleep at night is by limiting the use of out-args to private functions within a class. Any exposed functions must define a struct. This way we keep the ugly behind closed doors :wink:

In cases where optimizations are “worth it” it is our judgement call about whether or not we wish to maintain the smell, sometimes it is. I think its cool that C# gives us the option rather than choosing for us.

Just my 2 cents.

Please be aware there are works to support “structs” in Java: JEP 401: Value Classes and Objects (Preview)

2 Likes

Also be aware that some JVMs can do escape analysis and allocate objects (or even just their fields) on the stack where it’s safe to do so.

1 Like

why not just

fun compute(arg: Int): Pair<Int, Int> = // ...

fun main() {
    val (result1, result2) = compute(1)
}

We already have Pair (and the to infix function) in the stdlib and we have destructuring as a language feature. If you need one more return value, you can use Triple, and for every even more complicated use case I think you should use a dedicated data class anyway (but you could still use destructuring)