so local functions cannot be recursive?
# announcements
v
so local functions cannot be recursive?
d
Yes they can, but their declarations are not hoisted, meaning you cannot have a reference to a local function that is declared later.
This is because local functions can reference local variables of the containing function and if you were to call a local function before it's declaration it might have references to local variables of the parent function, which are by that point not even declared...
v
hmm. How does it work in all other languages then?..
d
Can you give an example?
v
example of what?
a
example of other language that has this
v
ah. F#
C#
image.png
d
How does C# deal with the fact that
Two
can reference local variables declared in
Foo
?
What if you call
One
before the declaration of
Two
?
v
I just was about to implement an FSM inside
actor { }
with a bunch of local functions and oops.
d
In Javascript you will get a
ReferenceError
at runtime
Example in JS:
Copy code
function asd() {
    function one() {
        two()
    }
    one();
    const x = 123;	
    function two() {
        console.log(x);
    }
}
Will produce
Uncaught ReferenceError: x is not defined
.
What does C# do in this case?
v
I'm not sure I understand the problem.
Is it possible to declare an outer function local var??
d
You are calling
one
, which calls
two
, which then references
x
. But at the time you are calling it
x
is not even declared or assigned yet
v
why it's not declared? I don't think C# executes code line by line 🙂
r
You can work around this by using lambdas instead of actual functions and using lateinit declaration:
Copy code
fun foo() {
    lateinit var two: () -> Unit
    fun one() {
        two()
    }
    two = {
        
    }
    one()
}
That compiles fine
d
Even if it is declared, it is certainly not assigned
What should it's value be?
a
@vaskir can you just translate that javascript code into C# and run it and see what happens? 😉
v
image.png
this one?
d
No. That is completely different to what I posted.
You can call
One
before your
void Two
declaration, which is the entirety of the problem.
a
nope, the one that is said to produce
Uncaught ReferenceError: x is not defined
.
r
@diesieben07 That's not the point though, @vaskir doesn't want to call it earlier, just declare them and use them afterwards
Look at my message to see how that can work in kotlin
d
Yes, I am just explaining why this is not allowed in Kotlin.
Your way with
lateinit
just brings JS' "explode at runtime" behavior to kotlin.
r
Yeah, which is exactly is wanted here.
d
"explode at runtime" should never be wanted 😛
r
So there's never a usecase for using
!!
then?
It definitely is wanted if the language provides no more elegant way to do what you want to do
d
I have written a lot of Kotlin and I've yet to use
!!
outside of quick and dirty experimental code
a
use case for
!!
is java interop I think, if you have only kotlin, then I don’t see much use
d
In Java interop you have platform types
You do not need !! there.
r
Please propose a better way of doing what @vaskir is trying to do then
v
d
Well, there was only a very limited contrived example posted.
@vaskir What if
x
does not have a constant initializer but is computed? E.g. random number?
It only works because
x
is marked
const
and can be inlined by the compiler.
v
it fails
r
@diesieben07 And what if it does? You can simply define all your functions at the top of the closure, and do any code that actually does something afterwards. Yeah, it's not checked by the compiler so it depends on the programmer checking that, but it's simple enough to keep straight. I really don't understand why you you're insisting to bring your example of doing something between the functions into it
v
at compile time
a
For now just use regular functions instead of local functions
and submit a feature request
v
or use another lang
a
exactly
v
Scala allows forward referencing to local functions. It solves the problem mentioned by Take Weiland by imposing some restrictions on how local variables can be positioned. Basically what I understand about the restriction is that a local function, say foo() cannot forward reference another local function, say bar() which references a local variables declared after foo() is declared. This restriction is fair and makes sense, and it does not limit us from a lot of good use cases for local functions.
I really hope Kotlin can support this local function hoisting feature like the way Scala does. It would allow us to write code according to the "stepdown" rule suggested by Uncle Bob in his Clean Code book.
See this thread for discussion about Scala's local function with forward referencing: https://stackoverflow.com/questions/22108579/calling-functions-before-they-are-defined-forward-reference-extends-over-defini