Hey guys, do you think you have time to change `Re...
# language-proposals
a
Hey guys, do you think you have time to change
Result
(also known as
SuccessOrError
) type before 1.3 release? I think it can be improved and you might want it to be improved for the future of language, I’m writing a KEEP but it takes a long time so I wanted to reach out so you know it’s coming
TL;TR: Provide better API, 3 changes: - Represent
Result
cases as public sealed class subtypes (can be as optimized as inline class with benefits of SmartCasts and more) - Allow a failure case to store anything instead of just
Throwable
- Change names of
Result
cases to more concise ones (
Ok
and
Er
)
Motivation: Given that the
Result
type is placed directly in
kotlin
package, and now that it’s [renamed](#159) to
Result
from
SuccessOrFailure
, it’s becoming clear that
Result
type might have a wide adoption outside of code generated by compiler for coroutines in future. That’s why it’s important to address several aspects of its API.
cc @elizarov
e
We don’t have time to work on any of that for 1.3
a
😞
any chance to mark type as Experimental and have a strategy to handle changes in future for generated coroutine code?
Result
is a very important type in many languages, rushing its design will be a costly mistake…
4
g
I think that having generic fail type would be valuable, but don’t think that it should be in Result for now, at least until we have default generic types, because still most common case is Throwable and just have write
Result<Foo, Throwable>
everywhere is tedious
e
We’ve thought though various potential future extensions (see this section of the KEEP: https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.md#future-advancements and made sure that we release minimal functionality in 1.3 that would not prevent us from doing any of those enhancements in the future
g
But if default generics will be available at some point you could add it additional generic argument for error case to Result without breaking backward compatibility
d
btw, why i can't use
kotlin.Result
as a function return type?
t
Wow, that KEEP about Result type so changed since I visited last time. Also there is mapCatching which is a
flatMap
g
You can use Result as return flag with experimental flag:
-Xallow-result-return-type
But I found some issue, cannot reproduce on minimal example yet
👍 1
runCatching is not flatMap, because lambda signature is
(T) -> R
, to have flatMap semantics that allows you chain multiple Results lambda should be
(T) -> Result<R>
So runCatching is just a "safe" version of map
t
@gildor if you look at the function that can throw an exception as implicitly returning Result (just as void functions implicitly returning Unit) you’ll see that
mapCatching
is effectively the same as a
flatMap
, but more of imperative style
@elizarov I see that you plan to expand usage of safe-call operators on
Result
. For me
Result<T>
looks like specialised
Either<T, Throwable>
and so the
T?
looks like
Either<T, Nothing>
. Any chances that it would be allowed to overload safe-call operators? That would allow other
Either
patterns like chained validation to be used with this concise syntax.
g
@themishkun It still not flatMap, otherwise even RxJava map you could call flatMap (map in RxJava Single works exactly like mapCatching of result), also throw an exception doesn't look really idiomatic for me, I would rather just write flatMap for Result (what I already did to replace our existing self written Try implementation)
e
We have no plans to make
Result
into a specialized
Either
, because the names of the components types and operators that
Either
supports make no sense for
Result
. Of cause, you can learn that “left” is a failure, while “right” is a success, but why ruin the readability of your code if you can simply use a type that is tailed to its use with the names that fit? The code will be oh so much more readable.
e
I second the request that it be marked experimental, and preferably moved to
kotlin.experimental
as well. I already use a type named
Result
through my app that has better semantics (in my use cases, at least; for example, representing it as a sealed class hierarchy as Artem described). It does indeed feel like Result as-is has been rushed. I think preferring the optimization that
inline class
brings over useful semantics is a mistake. (As the KEEP says, if sealed + inline class support comes in the future it can be added later, but I’d prefer to have
sealed
now instead of
inline
.)
g
Result is used for coroutines and I would avoid creation of additional objects just to wrap success result
When with sealed can be easily replaced existing fold function, I wouldn't say that it big problem for now
e
Then I’d still rather it be moved elsewhere instead of polluting the
kotlin
namespace, especially if it can’t be used in regular signatures out of the gate
that makes it sound like an (unfinished) implementation detail
e
@eddie You can use your own
Result
no problem. kotlin automatically imported names have lower priority in resolution than project-specific names.
We cannot move it, because moving it in the future will be breaking change. We cannot make it experimental either, because it is required for non-experimental coroutines.
g
Yes and you cannot use Result for now as return type. What is the reason to move Result to experimental package if you do not expect source or binary incompatible changes, even if not all the features are available now
e
It does not prevent you from using your own Result types in any way just like you’ve been doing before
e
That’s a relief, I suppose.
e
@gildor Right. We’ll be just adding features to it over time. No need to move it to add more features
t
@elizarov I was asking to consider giving the ability to overload safe-calls not only for Result, but also for custom Either-like types (if it would be implemented for Result in the first place, of course)
e
We can consider this, too.
f
@artem_zin is it really
Ok
and
Er
? Not
Err
?
Er
is definitely not proper English.
t
@Fleshgrinder
Ok
and
Er
both have 2 symbols, so they would align nicely in
when
-expression
f
This sounds like a weak argument to me, especially if I consider that I've never heard this complain in Rust.
Copy code
when (result) {
    Ok  -> // ...
    Err -> // ...
}
Problem solved. 😉
- https://doc.rust-lang.org/std/result/enum.Result.html#variants - https://www.merriam-webster.com/dictionary/err Whereas https://www.merriam-webster.com/dictionary/er is a pretty complicated situation. For me it's a personal pronoun (I'm a native German speaker) or an ER diagram. 😛
a
I'm not pushing hard for the rename,
Success
and
Failure
are also aligned horizontally as they're each
7
symbols However it is painful in Rust (I code a bit in it),
Ok
and
Err
don't align automatically
f
Success
and
Failure
sound good to me. As I said, I don't really share this sentiment as correctness is more important to me than solving special cases. Anyone who wants his `when`/`match` to align should, well, align them.
j
@elizarov Will you (or someone else @JB) tell more about the plans you have with Result type in the future during KotlinConf ? You said you had few ideas inspired from Rust so I am quite curious what it would look like in Kotlin 🙂
e
Most of the ideas are written down in the KEEP document. There’s not much more to talk about at the moment.