Maybe this is something "basic" but I had some arg...
# announcements
e
Maybe this is something "basic" but I had some argue with a colleague.... about the run scope function, when I do:
Copy code
val result = run { ... }
result is not actually calculated there, but when is needed (lazy), isn't it? I know this is the usual behaviour when using a functional style but I couldn't find any reference to give a clear explanation to my colleague.
n
No, it's calculated immediately
specifically, run invokes the lambda
however,
{ ... }
creates a lambda, which isn't immediately invoked
🤔 1
☝️ 1
a good example is something like
myMap.getOrPut(key) { expensiveFunctionCall() }
In this example, I'm not really invoking the expensive function and passing the result to getOrPut
I'm passing a lambda that does the work, and getOrPut will decide whether to actually invoke it
Kind of like a "lazy" function parameter
🤔 1
e
Sorry, then I am confused with the explanation, sorry,... If I undersand, I declare
result
and I can use
result
but their actual value, that is the value from the execution inside the lambda (maybe an expensiveFunction) is invoked (and then, and the end, executed) and defered only when
result
is really needed... for me is "result is not actually calculated there",...
If I do
val result = someMethodAsUsual(...)
then someMethodAsUsual is executed and assigned to
result
just in that very moment...
c
This of it like this:
.run
is a function which immediately invokes a lambda. Thus, you create a lambda, and then by passing that lambda to
.run
invoke it immediately. You can define that lambda elsewhere and assign it to a variable, and that lambda is lazily invoked, but by calling
.run { }
with a lambda, the lambda itself only exists inside the
.run
function, which invokes it immediately. Consider the following snippet: https://pl.kotl.in/3oxgHL623
👆 1
n
if you have
val result = { foo() }
then result isn't the return value of foo, and technically it's not "the return value of foo but lazy" either
instead its just a function, that when invoked, will invoke foo
Now, in kotlin those lambdas can be passed to other functions
val result = bar({ foo() } )
now, we are passing a function that calls foo, into bar. To do what? Dont' know, depends on bar.
Kotlin has syntactic sugar for this, so the above line is the same as:
val result = bar { foo() }
If I change
bar
to
run
:
val result = run { foo() }
then result is the return value of foo(), because that's what
run
does: it executes the lambda you pass it
Copy code
fun <R> dontRun(x: () -> R): Int { return 0 }
val result = dontRun { foo() }
now result is just 0
and
foo()
is never invoked
v
Or to make it concise, your colleague is right. If you want it lazy, do
val result by lazy { ... }
e
Aha! Thanks to all, now it's clear. 🙏