I was thinking about naming for comprehensions. Cu...
# arrow-contributors
p
I was thinking about naming for comprehensions. Currently we have the name of the result in lower case:
Copy code
nullable {}
option {} 
either {}
I can see two problems with this: • relatively easy to clash those names with local variables • Hard to discover them Should we do something like:
Copy code
bindingToNullable {}
bindingToOption {}
bindingToEither {}
This one would work nicely with autocomplete to give nice discoverability. Any thoughts? 🙂
i
if naming is an issue, one can still do that over the
import as
. But I am in favor of the existing names, because it implies that the result of the computation within leads to an Either, Option or nullable
p
I was thinking more for discovery on autocomplete of the IDE. You are right regarding the import alias for clashes though. Also, doing
xxxToOption
does imply that the computation within results in an Option, doesn't it?
I’m not set on the binding prefix tbh, maybe we could call like this instead:
Copy code
computeToNullable {}
computeToOption {}
computerToEither {}
Also, as a separate note we could probably have separate eager versions:
Copy code
computeEagerlyToNullable {}
computeEagerlyToOption {}
computerEagerlyToEither {}
Actually, maybe I've just thought of a way to make the API simpler and more flexible. Maybe something like:
Copy code
val c = compute {
   val a = sourceOfA.bind()
   val b = sourceOfB.bind()
   endWithEitherOf<Throwable, String>(a + b)
 }
Or
Copy code
val c = compute {
   val a = sourceOfA.bind()
   val b = sourceOfB.bind()
   endWithNullableOf<String>(a + b)
 }
So, the final call, which returns a token value type that cannot be instantiated outside of the scope, defines the type of the computation
Actually, may not need the end call. I need to check the generics and logistics though
Never mind, I gave the type inference too much hope 😅
👌🏽 1
😂 2
i
Yes discoverability in the IDE is always an interesting topic. What is possible is to enrich the implicit Import Scope per file in the IDE, in a compiler plugin. With that in mind it doesn't matter how we name toplevel functions or constructs.
r
@pablisco I tried something similar to your compute before the bind and current encoding but it will force you to ascribe type arguments manually on every block because
bind
is used in the body and the block can only infer based on arguments or return.
p
I had a think about this over the weekend and I think we could unify all into one when multiple receivers (i.e. context thingy) are supported. We can codify other bifunctors as Either, specially if we use value classes or unions from Meta 🤞 (since there would be zero overhead)
Copy code
Option, nullable -> Either<Unit, A>
Result -> Either<Throwable, A>
which means that potentially we could have a ComputeScope:
Copy code
interface ComputeScope<E, A> {
  fun Either<E, A>.bind(): A
}
With scoped extensions:
Copy code
context(ComputeScope<Unit, A>)
fun <A> A?.bind(): A

context(ComputeScope<Throwable, A>)
fun <A> Result<A>.bind(): A
Hopefully this should add the right type without explicit type definition. And then we can do a conversion at the end into the type that we want. But yeah, not quite ready for this as it is now 😅
Also, now I think of it, I guess it matches other builder patterns in Kotlin like
flow {}