switchIfEmpty is always called - kotlin

I have a method like this:
fun getActiveVersionWithCacheMiss(type: String): Mono<ActiveVersion> {
return activeVersionRepository.findByType(type)
.switchIfEmpty(
Mono.defer(return persist(ActiveVersion(type,1)))
)
}
persist method is a simple method that saves active version:
fun persist(activeVersion: ActiveVersion): Mono<ActiveVersion>{...}
In my test I mocked activeVersionRepository to return a simple value for findByType. During debug activeVersionRepository.findByType(type).block() evaluates to a value and is definitely not empty.
I'm wondering why despite using defer switchIfEmpty is still called?

The problem is return. The argument of switchIfEmpty needs to be evaluated regardless of whether findByType emits a value, which means the argument of defer needs to be evaluated, and return will return out of the entire function getActiveVersionWithCacheMiss.
Though I don't see how this code can compile; return persist(...) doesn't have a value which Mono.defer can use. Do you actually have braces {}, not parentheses () somewhere?

Related

Any significant differences between lambda expressions & anonymous function in Kotlin?

Kotlin has these 2 features and I think there're no significant differences between these two
regardless of :
syntax
// lambda
val toUpper = { value: String ->
if (value.isEmpty()) "empty value"
else value.toUpperCase()
}
// anonymous func
val toUpper = fun(value: String): String {
if (value.isEmpty()) return "empty value"
else return value.toUpperCase()
}
flexibility to use return statement on anonymous function
I'm still digesting these features and hope you guys can help me pass through it.
Thanks.
Two differences according to Kotlin Reference:
(I think the more significant one out of the two) An anonymous function is still a function, so returning from it behaves the same as returning from any function. Returning from a lambda, however, actually returns from the function enclosing the lambda.
The return type of a lambda is inferred, while you can explicitly specify a return type for an anonymous function.
This website states: "Lambdas Expressions are essentially anonymous functions that we can treat as values – we can, for example, pass them as arguments to methods, return them, or do any other thing we could do with a normal object." (link)
So the answer is no, there isn't a difference between the two, they are interchangeable. Both of the codes you show above, will in the end return the same value to that variable
Besides the differences pointed by #jingx, you can not local return from a lambda that is not inlined.
So, the next snippet will not compile unless you add inline to the extension() function, thus, instructing the compiler to copy the function's content whenever it is referenced:
fun doSomethingWithLambda(){
10.extension{
if(it == 10)
return//compiler error
}
println("hello")
}
fun Int.extension(f: (Int)->Unit){
f(this)
}

What does "lazy" mean with this code in Kotlin?

What is this code line doing?
fun<T:x>a.b(y: Int)=lazy{u.v<T>(y)}
I do not know what is 'lazy' doing or is 'lazy' something special in Kotlin.
fun<T:x>a.b(y: Int)=lazy{u.v(y)}
Let's break this down. First, let's reformat for readability :)
fun <T: x> a.b(y: Int) = lazy { u.v<T>(y) }
Now, let's go piece by piece.
fun means we're declaring a new method.
<T:x> means this is a generic method operating on type T where T is constrained to be of type x.
a.b means this is an extension function named b on type a.
(y: Int) means that the defined function b takes a single argument named y of type Int.
= is expression body syntax - shorthand for returning a short line of code. This means that a.b will return the value that is the result of evaluating lazy { }
lazy is a Kotlin standard library function that delays the evaluation of the function provided to it until it's needed and then caches the result. The return value of this function is actually a type Lazy that wraps the provided function.
{ u.v<T>(y) } is the function that will be executed by the Lazy object when it's value is obtained the first time and the return value of u.v<T>(y) will be saved as the lazy object's value.
Phew! So what does that mean? Let's look at an example. Suppose we add a print statement to the function to see when it's called.
fun <T: x> a.b(y: Int) = lazy {
println("Executing 'b'")
u.v<T>(y)
}
Now if you tried to use it:
fun main() {
val a = A<T>() // Assume some type T
val lazyObject = a.b<T>(42) // Call the extension method that returns a `Lazy`
// Get the value from the lazy object - prints "Executing 'b'",
// executes `u.v<T>(y)`, caches the result, returns it - then print it
println(lazyObject.value)
// Get the value from the lazy object again. This time, DOES NOT print
// "Executing 'b'", DOES NOT execute `u.v<T>(y)`, and just returns the
// result that was already computed and cached, then print it
println(lazyObject.value)
}
So, in summary, the code you posted is creating an extension method that returns a Lazy object that, when queried for its value, executes the lambda it's initialized with and caches that result for later use.
Hope that helps!

When do I use another function without paramters in Kotlin?

I'm a novice of Kotlin.
I found that I can use another function without parameters even if it has.
Let me know when I can use it.
Q1) Why can I use 2 types? (with parameters & without parameters) Is it Kotlin's feature?
Q2) What does it mean? ((Result!) -> Unit)!
It seems you are confused, you can never use a function without arguments. If the function has arguments then you have to fill the slot somehow.
The closest thing that could relate to what you are referring to is default values for arguments.
fun example(boolean: Boolean = true) {}
example()
example(true)
example(false)
You can omit the argument because it has defaulted in the function signature.
The documentation
What you are showing in the image file is a lambda.
In the first example:
signIn(listener: Session...)
That seems to be a callback. So it is gonna be an interface or maybe an abstract class called when some async operation is finished.
The second example, it is the callback implemented as a lambda
signIn() { result ->
//do something
}
In Kotlin the last argument if it is a lambda or something that can be implemented as a lambda can be moved out of the parenthesis for syntactic sugar. A lambda is like an anonymous function, it is a literal of a function.
By example you can declare a lambda:
val lambda = {text: String -> text.lenght % 2 == 0}
fun setRuleForText(rule: (String)-> Boolean) {...}
setRuleForText(lambda)
setRuleForText() { text: String
text.isNotEmpty()
}
In this case, the argument is a kotlin function. The argument rule is a function that receives a String as an argument and returns Boolean. Something to point out is that expressions return the last written value without the need for the reserved return word.
This is the documentation. And here you can see from a good source more about functions (the author is a Kotlin certified trained by Jetbrains)
In your case (Result) -> Unit means the lambda should receive a Result type as argument and then return Unit (unit is like void in Java but is more than that), no explicit return type.
signIn() { result ->
//do something
}
Most of the types, the argument on lambdas is inferred automatically, but if not, then
signIn() { result: Result ->
//do something
}
Both of the listed functions take a parameter.
The first is:
signIn(listener: Session.SignInListener!)
That takes a single parameter, of type Session.SignInListener.  (The ! means that Kotlin doesn't know whether it's nullable or not, because it's from Java and isn't annotated.)
The other is:
signIn {...} (listener: ((Result!) -> Unit)!)
That's the IDE's representation of the function with this signature:
signIn(listener: ((Result!) -> Unit)!)
That takes a single parameter, which is a function type (see below).
The reason the IDE shows it with braces is that in Kotlin, if the last parameter to a function is a lambda, you can move it outside the parentheses.  So a call like this:
signIn({ println(it) })
could equally well be written like this:
signIn() { println(it) }
The two forms mean exactly the same.  And, further, if the lambda is the only parameter, you can omit the parens entirely:
signIn { println(it) }
Again, it means exactly the same thing.
That syntax allows you to write functions that look like new language syntax.  For example:
repeat (10) {
// ...
}
looks like a new form of loop construct, but it's really just a function called repeat, which takes two parameter (an integer, and a lambda).
OK, let's look at that function type: ((Result!) -> Unit)!
That's the type of a function which takes one parameter of type Result, and returns Unit (i.e. nothing useful; think of it as the equivalent of void).  Again, it's complicated because Kotlin doesn't know about the nullability; both the Result parameter and the parameter holding this function have !s to indicate this.  (Without them, it would just be (Result) -> Unit.)

calling overloaded function with default arguments in Kotlin

Hi i am confused in invoking concept of a function with default arguments in case of function overloading.
My use case is -
i have two functions with same name(function overloading) and i have added few default arguments, so it is not clear which function will be called.
Example-
fun add(a:Int, b:Int=2, c:Int=2):Int
{
return a+b+c
}
fun add(a:Int, b:Int=1):Int
{
return a+b
}
Now i am calling
add(5)
add(5,2)
which method should be called.
if i check
fun foo(p1:Int,p2:String?=null)
fun foo(p1:Int,p2:Int=0)
this will cause of
"overload resolution ambiguity" error.
But in my case every time fun add(a:Int, b:Int=1):Int
{
return a+b
}
is called.
So how ?
2nd function (fun add(a:Int, b:Int=1):Int) is called because it is a closer match (less parameter difference) as zapl pointed out.
DETAILS:
Resolution of overloaded method calls with default params is described in Kotlinlang spec:
The candidate with the least number of non-specified default
parameters is a more specific candidate
So when you call add(5), then the number of non-specified default parameters is:
2 for fun add(a:Int, b:Int=2, c:Int=2):Int
1 for fun add(a:Int, b:Int=1):Int
That's why the 2nd function is called. Based on the same logic, the 2nd function wins also when add(5,2) is called.
But when you have that 3rd function (fun foo(p1:Int,p2:String?=null)), the compiler can't decide which one to call, because the parameter difference is the same. Based on docs:
If there are still more than one most specific candidate afterwards, this is an overload ambiguity which must be reported as a compile-time error.

What is the difference between require and assert?

With Kotlin 1.3 came a new feature, contracts, and with them the function require(), but it seems pretty similar to assert(). Here is what their KDoc says:
require(value: Boolean): Throws an IllegalArgumentException if the value is false.
assert(value: Boolean): Throws an AssertionError if the value is false and runtime assertions have been enabled on the JVM using the -ea JVM option.
So when should I use require() and when should I use assert()?
require and assert work differently. For this, you need to dive into the code.
assert(condition) calls a different method internally, which is where you see the actual code:
#kotlin.internal.InlineOnly
public inline fun assert(value: Boolean, lazyMessage: () -> Any) {
if (_Assertions.ENABLED) {
if (!value) {
val message = lazyMessage()
throw AssertionError(message)
}
}
}
AFAIK, this ties to the -ea flag; if -ea isn't present (or disabled), assert will not throw an exception.
As a result, this will not compile:
fun something(string: String?){
assert (string != null)
nonNull(string) // Type mismatch
}
fun nonNull(str: String){}
This is where require comes in. require(condition) also calls a different method under the hood. If you replace assert with require, you'll see that smart cast will successfully cast it as non-null, because require is guaranteed to throw an exception if the condition fails.
#kotlin.internal.InlineOnly
public inline fun require(value: Boolean, lazyMessage: () -> Any): Unit {
contract {
returns() implies value
}
if (!value) {
val message = lazyMessage()
throw IllegalArgumentException(message.toString())
}
}
The boolean-only function does the contract too, then calls that method if the contract fails.
Contracts are new, and I am not entirely sure how they work, but this is how I understand it:
The implies keyword is an infix fun; what this does is that it tells the compiler the condition is true if it returns from the method. This helps with auto-casting, like in the example I mentioned earlier. It doesn't actually cause the method to return (or at least that's what my current testing points to), but it's for the compiler.
It's also readable: returning implies condition is true
That's the contact part: the exception here is always thrown, as you can see by the condition. require uses if(!value), where as assert checks if(_Assertions.ENABLED && !value).
This isn't the only use for require though. It can also be used for validation of arguments. I.e. if you have this:
operator fun get(index: Int) : T {
if (index < 0 || index >= size)
throw IllegalArgumentException("Index out of range")
// return here
}
You could replace it with:
operator fun get(index: Int) : T {
require (index >= 0 && index < size) { "Index out of range" }
// return here
}
There are a lot different uses for this, but these are just some examples.
What this means:
assert is like in Java; it is only triggered if assertions are enabled. Using it does not guarantee the condition is met.
require always works, regardless of VM flags
Which means require can be used to help the compiler with i.e. smart cast, and it's better to use than assert for making sure arguments are valid. And since it also works regardless of VM flags, it can be used outside debugging cases, as forpas mentioned. If you're making a library written in Kotlin, you can replace argument checking with manual throwing with require, and it will still work. Obviously, this assumes Kotlin 1.3.0, but that's beside the point.
And it can be used internally to ensure smart cast works as expected, but throw an exception if the condition isn't met.
To answer your question though:
Use require when you want to to argument checking, even if it's in production.
Use assert if you're doing local debugging, and have the -ea flag enabled.
Let's say you want a function to calculate n! (factorial) like this:
fun factorial(n: Long): Long {
require(n >= 0) { "Number must not be negative" }
// code
}
In this case require() checks the validity of the argument passed to the function and throws an IllegalArgumentException if the argument is not what it's supposed to be and for debugging you also have the explanatory message.
On the other hand assert() can be used anywhere in your code to make your own specialized checks if runtime assertions have been enabled.
There is also
check(Boolean) throws IllegalStateException when its argument is false,
which is used to check object state.
So each of the above has its own place in your code and you can use it if you find it useful.