I feel like this has been asked before, but I can'...
# getting-started
r
I feel like this has been asked before, but I can't find it... What's the best way to do:
Copy code
if (someVar in listOf("value1", "value2", "value3")) {
  // do work
}
Like that, I assume the List gets allocated every time the code is run, which seems stupid. But pulling it out into a value somewhere substantially (to my mind) obfuscates the code. I really want syntax sugar for
(someVar == "value1" || someVar == "value2" || someVar == "value3")
, but I don't think that exists?
k
There isn't a way to do this currently, but there is a proposal for collection literals which might do what you want.
f
you could do
if(listOf(1,2,3).contains(3)){..}
k
@Francisco Noriega that's actually the same thing. The
in
operator calls
contains
. By the way, I usually write
someVar in arrayOf(...)
instead of
listOf
- as a naive microoptimization that won't actually make any difference but makes me feel a little bit better because
listOf(a, b, c, d)
really compiles to the equivalent of
listOf(arrayOf(a, b, c, d))
.
m
Ideally the collection of "value1", "value2", and "value3" represents something that you can then use as a named constant. Then it is not getting created all the time. There's also using a when block
Copy code
when (someVar) {
    "value1", "value2", "value3" -> 
}
👍 1
r
Ideally the collection of "value1", "value2", and "value3" represents something that you can then use as a named constant
As I said, in my case pulling it out into a value somewhere substantially (to my mind) obfuscates the code
There's also using a when block
That's really nice - sadly, in my case there's an
&& ...
as well which prevents that.
By the way, I usually write
someVar in arrayOf(...)
instead of
listOf
- as a naive microoptimization that won't actually make any difference
I considered that, but sort of vaguely hoped using a read only type would enable some future version of the compiler or runtime to deduce that it could optimise it into a single allocation... allocating an array feels like a more primitive operation that a responsible compiler / runtime will not seek to optimise away.
Thanks for the pointer to the collection literals
p
Isn't
any {}
what you are looking for?
Copy code
if (list.any {}) {
  // Do stuff 
}
c
some future version of the compiler or runtime to deduce that it could optimise it into a single allocation... allocating an array feels like a more primitive operation that a responsible compiler / runtime will not seek to optimise away.
Actually, it's the opposite: arrays are much lower-level and are entirely described by the JVM (you can't make custom subclasses of it) so it's easier for the compiler team to be sure they didn't miss an edge case.
h
I just write it as you did. It's a short lived allocation, it won't hurt in 99.999% of all cases. And in the rase cases when I have to optimize for performance, extracting the list as a constant will probably the least of my anti-readability sins... 🤷‍♂️
c
IMO just use
someVar == "value1" || someVar == "value2" || someVar == "value3"
, it's not hard to read and it's the most efficient ways of doing it 🤷
h
Yeah, I should probably start doing that instead. (But
in
reads so nice…)
c
@CLOVIS Actually it is rad to read as you need to make sure all used variables are the same one. That could be even more difficult if you have multiple similarly named variables. Creating a literal Array IMO won’t obfuscate if the name will be meaningful. Also, if this group is not arbitrary, same literal could be used later in other places of the code. I like the idea of
when
structure. Finally, in some cases may use the
lateinit
value with also meaningful name. In this case it won’t initialized at all unless needed.