elect
09/22/2021, 5:23 AMephemient
09/22/2021, 5:28 AMkotlin.jvm.internal.Ref
as needed, I think using that to implement out-parameters would be more likely to get into the compiler than forcing a function to be inlined at every callsite just for the sake of removing some allocationsephemient
09/22/2021, 5:37 AMephemient
09/22/2021, 5:43 AM@JvmInline value class SignalLevel private constructor(private val value: ULong) {
constructor(signal: Int, levels: Int) : this(signal.toULong() shl 32 or levels.toUInt().toULong())
val signal: Int get() = (value shr 32).toInt()
val levels: Int get() = value.toInt()
}
as JVM's long
is already a supported method to use two stack slots for return valuelouiscad
09/22/2021, 5:54 AMelect
09/22/2021, 6:08 AMephemient
09/22/2021, 6:45 AMelect
09/22/2021, 7:13 AMelect
09/22/2021, 7:15 AMtypealias Callback = (Int, Foo) -> (Long, Bar)
val callback = { int, foo ->
...
-> long, bar
}
...
val (a, b) = callback(c, d)
ephemient
09/22/2021, 8:05 AMelect
09/22/2021, 8:33 AMinline
the compiler may do the work for usephemient
09/22/2021, 8:36 AMkotlin.jvm.internal.Ref
boxes for anything it mutates.
callback with inlining needs to be done with care to avoid code explosion.
using a temporary immutable data structure for returning multiple values is almost always fine. it should come from the bump allocator, if it's temporary and never stored as a reference anywhere then nursery collection is fast. it's the best trade-off for most general purposes.christophsturm
09/22/2021, 11:09 AMchristophsturm
09/22/2021, 11:11 AMfun return2(): Pair<String, Int> = Pair("String", 10)
val (a, b) = return2()
elect
09/22/2021, 12:10 PMchristophsturm
09/22/2021, 12:14 PMchristophsturm
09/22/2021, 12:16 PMelect
09/22/2021, 3:59 PMlouiscad
09/22/2021, 4:24 PMelect
09/22/2021, 7:52 PMlouiscad
09/22/2021, 8:02 PMLong
can work for storage even for Float
types.ephemient
09/23/2021, 2:19 AMYoussef Shoaib [MOD]
10/04/2021, 2:01 PMfun main(){
val (stuff, bonus) = getStuff()
}
inline fun getStuff(): ZeroCostPair<Stuff, Bonus> {
val stuff = grabStuffFromCargoBikeBasket()
val bonus = inspirationElixir()
return ZeroCostPair(stuff, bonus)
}
//Implementation details
typealias ZeroCostPair<F, S> = (PairCall, F?, S?) -> Any?
enum class PairCall {
First,
Second
}
// Mimicking a constructor for the type.
inline fun <F, S> ZeroCostPair(first: F, second: S): ZeroCostPair<F, S> =
{ call, _, _ ->
when (call) {
PairCall.First -> first
PairCall.Second -> second
}
}
// Again, the parameters are useless, so just pass in null for them since during runtime the JVM won't actually know what
// F and S are since they get erased.
// We can safely cast the result of invoking the function as F or S because we know that ZeroCostPairs created using
// the factory function always follow the pattern of returning an F if PairCall.First is passed in and likewise for S.
inline val <F, S> ZeroCostPair<F, S>.first get() = this(PairCall.First, null, null) as F
inline val <F, S> ZeroCostPair<F, S>.second get() = this(PairCall.Second, null, null) as S
Youssef Shoaib [MOD]
10/04/2021, 2:12 PMgrabStuffFromCargoBikeBasket
and inspirationElixir
and so the issue of code explosion is almost eliminated here). I think this could also be implemented on a compiler level, albeit with a compile-time performance hit, by some analysis of how much each part of a function affects the rest, and sense in general programmers are shifting towards a functional style of programming, code like this is quite common:
inline fun foo(param1: A, param2: B): Pair<X, Y>{
val firstThing = //some calculations
val secondThing = //even more calculations
// do stuff with firstThing and secondThing
// derive x and y from firstThing and secondThing
return x to y
}
and so in that case this function could be split into 5 parts: 2 parts for the first 2 calculations. one part for the processing stuff in the middle, then 2 parts for the derivation of both x and y. In a case like this, the compiler, by noticing that foo is inline, can split foo into 5 different synthetic methods and then whenever foo gets inlined it'll only add the bytecode needed to call those 5 methods. It can even be done on a case-by-case basis by calculating what the bytecode impact of the splitting could be compared to just letting it be inlined normally. The compiler already does some pretty complex analysis stuff, and so it seems as though this wouldn't be heretic to suggest.elect
10/04/2021, 4:26 PMYoussef Shoaib [MOD]
10/04/2021, 4:45 PMelect
10/04/2021, 4:50 PMYoussef Shoaib [MOD]
10/04/2021, 5:06 PMelect
10/04/2021, 5:09 PMVkResult
.
On vkk you get instead directly the object in return, which is much more useful and common, and then if you want to inspect the result
, at the very moment you can use the inlined lambda at the end and put there your logic about that.
With your plugin, I'd be able to return directly object and result
val (obj, res) = vk..
ephemient
10/04/2021, 8:14 PMU?(Byte|Short|Int|Float)(Pair|Quad|Oct)
that can be packed into a (Int|Long)
, all tested including checking that they all get returned as primitives on JVMelect
10/05/2021, 7:58 AMlouiscad
10/05/2021, 7:59 AMelect
10/05/2021, 7:59 AMlouiscad
10/05/2021, 8:00 AMjimn
10/11/2021, 12:10 PMchristophsturm
10/11/2021, 3:21 PMelect
10/19/2021, 4:34 AMelect
12/12/2021, 10:47 AMinline
on destructurizations would lead to automatically this kind of code, ie:
val (theStuff, theBonus) = getStuff()