I was very surprised to see that in sequenceOf(foo(), bar())
both foo()
and bar()
actually get called when constructing the sequence, which seems counter-intuitive to me. I know I can work around this by using the construct sequence { yield(foo()); yield(bar()) }
instead, but that seems very verbose. So I’m wondering, why wasn’t the former designed to simply be an alias for the latter?
In a function call, each argument is evaluated before making the call.⠀So it doesn’t matter what the implementation of sequenceOf()
contains; foo()
and bar()
will have been called before getting there.
The difference in the second case is that the argument to sequence()
is a function; evaluating the parameter gives a lambda, but does not execute it yet.
You couldn’t make the one an alias for the other without making its arguments evaluated lazily.⠀(Which would be a huge change to the language, affect interoperability and backward compatibility, and be very surprising in general.)
You could probably write your own sequenceOf()
-like function which took a list of lambdas (or function references), avoiding the need for explicit yield()
calls when you call it.
Simplest solution is:
sequenceOf({ foo() }, { bar() }).map { it() }.find { it == "foo" }
or maybe
sequenceOf(::foo, ::bar).map { it() }.find { it == "foo" }
Is it more “intuitive”? Intuition is a strange thing.