<@U12AGS8JG> i’ve got a proposition for you. It’s ...
# kotest
m
@sam i’ve got a proposition for you. It’s about introducting continuation-passing style to the current arbitrary builder to improve its ergonomics and simplify how we might build, compose, and generate arbs. I’ve got a PR up for you to hopefully illustrate the proposed solution as well as the problem that solves. Hope you can take a bit of a peek when you’ve got the time https://github.com/kotest/kotest/issues/2493
👍 2
s
I'm away atm but it looks interesting when I glanced. Will review properly later.
🙇 1
g
Seems like a really nice idea to me! Though I've no idea what would be involved from an implementation point-of-view
m
@sam what do you reckon in general?
s
Yeah we can merge it, I just want to understand it first, and I haven't had chance to look at it again
I think its a breaking change right? Bcause you can't use suspend instead arbs anymore (in case someone was doing that)
m
thinking
you’re right initially i thought that wouldn’t be breaking but in terms of signature when it got compiled down it might we changed:
Copy code
// from this
fun <T> arbitrary(fn: (RandomSource) -> T): Arb<T>

// to this
fun <T> arbitrary(fn: suspend ArbitraryBuilderSyntax.(RandomSource) -> T): Arb<T>
and that’ll generate a different function
Copy code
class BuildersKt {
  static Arb<T> arbitrary(Continuation, ArbitraryBuilderSyntax, RandomSource -> T) ...
}
i don’t like breaking changes hmmmm
s
you could come up with a new name for it
m
what’s your recommendation @sam?
s
Copy code
fun <T> fix(fn: suspend ArbitraryBuilderSyntax.(RandomSource) -> T): Arb<T>
not sure what the name should be
m
in kotlin std lib these types of builders usually come as a lowercase of its classname. so thinking out loud
Copy code
fun <T> gen(fn: suspend GenBuilderSyntax.(RandomSource) -> T): Gen<T>
or in a different package
Copy code
package io.kotest.property.arbitrary.builders

fun <T> arb(fn: suspend GenBuilderSyntax.(RandomSource) -> T): Arb<T>
I just realized we can also support
Exhaustive<T>.bind()
if you’re cool with it.
s
we had arb before and just removed it
m
yeah that’s my reluctance as well
s
and gen is a bit too generic, I think its better to come up with a name that indicates this builder is a bit funky
lol arblicative
m
lol
s
what are some words that cover what we're doing, we're building, and extracting, its like a special do notation, a comprehensive of sorts
m
this solves a lot of our problem, we had like a very deeply nested data class that currently looking like callback hell because each of the fields have some sort of edge cases.
s
arbcomprehension
arbDo
arbitraryDo doArbitrary
m
scouting arrow they name it under
.computation
package
s
bind
m
bind isn’t bad
s
our existing binds won't clash I don't think
because they take > 1 args
m
checking
s
I think you're good because bind takes arbs + a fn
m
yeah they wont. in this case though, would you recommend
Copy code
Arb.bind {
   val one = arbOne.bind()
   val two = arbTwo(one).bind()
   Foo(one, two)
}
or
Copy code
bind {
   val one = arbOne.bind()
   val two = arbTwo(one).bind()
   Foo(one, two)
}
I personally like the latter
but it’s also confusing, i’d rather see something like
Copy code
arbitrary {
   val one = arbOne.bind()
   val two = arbTwo(one).bind()
   Foo(one, two)
}
s
I think arrow did something similar thought, like
Copy code
either {
   val a = myeither.either()
   val b = myeither2.either()
}
m
yeah they do that, they just put it under
arrow.core.computations.either
and
arrow.core.computations.option
Copy code
either {
   val a = myeither.bind()
   val b = myeither2.bind()
   b
}
the nomenclature is also the same,
.bind()
s
so you don't like bind + bind
m
yeah it feels clunky, especially with kotlin stdlib and arrow have converged to doing
Copy code
val flowValue: Flow<X> = flow {
  ...
}

val eitherValue: Either<L, R> = either {
  ...
}

val sequenceValue: Sequence<A> = sequence {
  ...
}
s
well they have generateSequence too
and one is suspend
one isn't
exactly like you're doing
so maybe generateArbitrary
m
ah nice
recap say we do that: •
sequence
is suspend,
generateSequence
is non-suspend, •
arbitrary
is non-suspend,
generateArbitrary
is suspend we’ve flipped the definition in stdlib. does that matter?
s
I would say this kind of bind is advanced functionality, so you're only likely to use it if you know about it, and see it in the docs, so it doesn't matter hugely what it's called
but it's not ideal that it's opposite to the std lib in this case
you could call it arbitrary and put it in another package
m
i think i’m more inclined to do that now. i’m weighing the options
are you sure if we change the signature of the current arbitrary that’s a breaking change?
s
its not about adding the receiver but the fact you're restricting suspension
Copy code
arbitrary { delay(100) }
that won't work anymore because you're using suspension for your bind
m
does that ever work?
Copy code
arbitrary { delay(100) }
currently arbitrary isn’t inline
s
is arbitrary not marked as suspend
aha !
then you get a get out of jail free card, there's nothing to break
you can change the existing one then, and add a generateArbitrary that is suspendable, mirroring the std lib ?
m
yeah that’s a new feature to be able to call suspend fun inside of the arbitrary builder.
s
yeah I assumed the function was already suspendable
well you know what they say about assumptions, it killed the cat
m
😆 i wasn’t too keen to make breaking changes either
s
well sounds like we're set 🙂
I'll review it again later as I wanted to read the comments you added
but we'll merge it before 5 M2
m
thanks!
s
I think kotest property testing must be, or close to being, the most powerful out there now.
💯 1
m
haha 100%!
@sam i just checked that
generateSequence
isn’t suspend
and i wasn’t sure what to name it, naming is hard 😢
s
not sure we need it then ?
sorry to waste your time
m
hmm, not really a waste of time i don’t think. that suspend arb is actually quite cool
that’ll allow an arb to coordinate something with ext service, or gather data from local postgres or stopping / starting dynamo for instance
s
right
m
Mockk name the methods
coXYZ
, i don't like it but it's an idea, 🤔 another idea that i got is
suspendArbitrary
This is such an advanced feature though @sam
Actually I am overthinking it, you're right generateArbitrary is actually a great name. It does imply that some more effectful operation can happen
I'll update the PR
done! thanks @sam