Hi folks, I’m playing with elvis(?:) operator and ...
# getting-started
b
Hi folks, I’m playing with elvis(?:) operator and looking for some help, I want to return from the method when my object is null but before returning from the method I want to add a log statements, what is the correct way of doing that?
Copy code
val record = (repository.findById(id) ?: (<http://log.info|log.info>("log message here") return))
😬 1
p
IMO if you have more than a single statement you should just use a regular if statement. That said, you can use
run
for this;
Copy code
val record = repository.findById(id) ?: run { 
	<http://log.info|log.info>("log message here") 
	return 
}
👍 2
r
I agree with Paul: readable code is better than clever code.
e
to be clear:
Copy code
val record = repository.findById(id)
if (id == null) {
    <http://log.info|log.info>("log message here")
    return
}
will work equivalently, as the
val
is smart-cast to non-null after the conditional
👍 5
although if
<http://log.info|log.info>
returns
Unit
you can get away with
Copy code
val record = repository.findById("id") ?: return <http://log.info|log.info>("log message here")
but I do not recommend it; stylistically, I would tend to avoid treating
Unit
as a value where unnecessary
👍 1
m
This seems to be one of these situations where the “old-fashioned” ways of doing things work best. Just like in Java you don’t always use Optional, in Kotlin you shouldn’t always use the elvis operator and/or scope functions. Simple > clever.
👍 6
k
Do the "clever" examples of syntax above actually compile? They don't for me. The compiler says that a value of type Record is required where I instead return Unit.
s
you never gave us the return type of the function you're in, so people assumed it's
Unit
😉 Assuming your method returns
Record
(which is what your error message seems to tell us), this leads to the question: So what do you want to return in case
repository.findById(..)
returns
null
? I see three possibilities: • return a nullable Record • throw an exception
Copy code
val record = repository.findById(id) ?: run { 
	<http://log.info|log.info>("log message here") 
	throw NoSuchElementException("no record found with id $id") 
}
• return a default
Copy code
val defaultRecord = ... //should be outside of the method, so you always return the same instance
...
val record = repository.findById(id) ?: run { 
	<http://log.info|log.info>("log message here") 
	return defaultRecord
}
of course you can only return a default value if a logical/useful default value exists. otherwise return null. null in Kotlin is more benevolent than in Java, since it can't surprise you, so use it where appropriate.
m
May be beside the point, but the logging you want to do is a little excessive. If not finding the record could be a problem, maybe it would be better to throw an exception and do the logging elsewhere. Another good solution could be to change the signature of the method so that it requires a record to start with. Methods with a lot of guard clauses that do “silent” returns can be difficult to maintain.