Hello, I’ve a question regarding `inline functions...
# announcements
m
Hello, I’ve a question regarding
inline functions
. How can I make an inline function stopping/returning the calling function?
Basically, I would like this :
Copy code
//This method should return the calling function
inline fun onUserNull() = run {
  Timber.e("User is null")
  return
}

fun fetchUserIdentity() {
  val currentUser = userDataSource.currentUser ?: onUserNull()

  presenter.displayUserIdentity(currentUser)
}
Would do the same as:
Copy code
fun fetchUserIdentity() {
  val currentUser = userDataSource.currentUser ?: run {
    Timber.e("User is null")
    return
  }

  presenter.displayUserIdentity(currentUser)
}
a
I don't think it's possible (except for throwing) I also don't think it's a good idea Why not do
val currentUser = userDataSource.currentUser ?: return Timber.e("User is null")
l
You need to take a function that returns
Nothing
, then at use site, you can put
return
in that lambda argument.
m
@Alowaniak I could, but this code is used in a lot of places, and I wanted to factorize it. 😕 From what I understood,
inline functions
content are more or less just copied in the call site. So, why couldn’t I do
return
from an inline function?
@louiscad This is what I wanted to do, but how can I return
Nothing
? From what I read, the only way is to throw an exception, which is not what I wanted.
l
@Melvin
return
evaluates to
Nothing
too 😉
If it didn't, you could just throw after the return expression, since it'd never be executed anyway, being unreachable. That's why
return
expression already evaluates to `Nothing`: it makes code below unreachable.
m
@louiscad I tried this code:
Copy code
inline fun reportUserNull(): Nothing {
    Timber.e("User is null")

    return
    error("user is null")
}
But, it tells me
This function must return a value of type Nothing
I think I can’t just use
return
😕
Hmmm,
Copy code
inline fun reportUserNull(): Nothing {
    Timber.e("User is null")

    return error("user is null")
}
Like this seems okay. (I’ll try it)
Arrgh, but it crashes. Looks like the
error("user is null")
is reachable ˆˆ
a
@louiscad I don't follow how you suggest to achieve what @Melvin Biamont wants. I don't see how it's possible to call a function which will return the caller's function (without
return
in the caller via for example a lambda) other than throwing an exception? The reason why I would say you shouldn't want it in the first place is because IMO it would get totally unclear what happens at call-site Also I'm not sure but I don't think an
inline
function is always inlined (for example when calling from java, or when function is virtual) I really think you should just do
val x = foo ?: return onBar()
or
val x = foo ?: onBar().also { return }
l
@Melvin Biamont I don't think you understood what I said. Here's an example :
Copy code
inline fun returnFromMyLambda(returnYourself: () -> Nothing) {
    stuff()
    if (shouldDoIt) returnYourself()
}

fun computeNumber(): Int {
    if (Random.nextBoolean()) {
        return 1 + 1
    } else {
        returnFromMyLambda {
            return 0 + 3 // returns from computeNumber
        }
    }
}
m
Yeah, but can I do it without passing lambda?
l
No, it's impossible. It'd be dangerous to allow a function to go beyond its boundaries like that. inline higher order functions is the best we got, and IMHO, the best we can get, unless a new thing is introduced in the language to allow functions that make their caller return (which would anyway be unpractical because the return type is not necessarily
Unit
, so would put return type constraints on the caller).
c
from a readability point of view- it would be a nightmare if seemingly innocuous method calls exited my method
m
You’re probably right. I gave up and did it using lambda. Thanks @louiscad @Alowaniak @czuckie 🙂
👍 1