https://kotlinlang.org logo
Title
m

mitch

09/11/2021, 1:51 PM
@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

sam

09/11/2021, 2:15 PM
I'm away atm but it looks interesting when I glanced. Will review properly later.
🙇 1
g

Gavin Ray

09/11/2021, 4:02 PM
Seems like a really nice idea to me! Though I've no idea what would be involved from an implementation point-of-view
m

mitch

09/15/2021, 12:05 AM
@sam what do you reckon in general?
s

sam

09/15/2021, 12:06 AM
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

mitch

09/15/2021, 12:07 AM
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:
// 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
class BuildersKt {
  static Arb<T> arbitrary(Continuation, ArbitraryBuilderSyntax, RandomSource -> T) ...
}
i don’t like breaking changes hmmmm
s

sam

09/15/2021, 12:10 AM
you could come up with a new name for it
m

mitch

09/15/2021, 12:10 AM
what’s your recommendation @sam?
s

sam

09/15/2021, 12:12 AM
fun <T> fix(fn: suspend ArbitraryBuilderSyntax.(RandomSource) -> T): Arb<T>
not sure what the name should be
m

mitch

09/15/2021, 12:16 AM
in kotlin std lib these types of builders usually come as a lowercase of its classname. so thinking out loud
fun <T> gen(fn: suspend GenBuilderSyntax.(RandomSource) -> T): Gen<T>
or in a different package
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

sam

09/15/2021, 12:17 AM
we had arb before and just removed it
m

mitch

09/15/2021, 12:17 AM
yeah that’s my reluctance as well
s

sam

09/15/2021, 12:18 AM
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

mitch

09/15/2021, 12:18 AM
:lol:
s

sam

09/15/2021, 12:19 AM
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

mitch

09/15/2021, 12:19 AM
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

sam

09/15/2021, 12:19 AM
arbcomprehension
arbDo
arbitraryDo doArbitrary
m

mitch

09/15/2021, 12:19 AM
scouting arrow they name it under
.computation
package
s

sam

09/15/2021, 12:20 AM
bind
m

mitch

09/15/2021, 12:20 AM
bind isn’t bad
s

sam

09/15/2021, 12:20 AM
our existing binds won't clash I don't think
because they take > 1 args
m

mitch

09/15/2021, 12:21 AM
checking
s

sam

09/15/2021, 12:22 AM
I think you're good because bind takes arbs + a fn
m

mitch

09/15/2021, 12:23 AM
yeah they wont. in this case though, would you recommend
Arb.bind {
   val one = arbOne.bind()
   val two = arbTwo(one).bind()
   Foo(one, two)
}
or
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
arbitrary {
   val one = arbOne.bind()
   val two = arbTwo(one).bind()
   Foo(one, two)
}
s

sam

09/15/2021, 12:27 AM
I think arrow did something similar thought, like
either {
   val a = myeither.either()
   val b = myeither2.either()
}
m

mitch

09/15/2021, 12:31 AM
yeah they do that, they just put it under
arrow.core.computations.either
and
arrow.core.computations.option
either {
   val a = myeither.bind()
   val b = myeither2.bind()
   b
}
the nomenclature is also the same,
.bind()
s

sam

09/15/2021, 12:31 AM
so you don't like bind + bind
m

mitch

09/15/2021, 12:33 AM
yeah it feels clunky, especially with kotlin stdlib and arrow have converged to doing
val flowValue: Flow<X> = flow {
  ...
}

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

val sequenceValue: Sequence<A> = sequence {
  ...
}
s

sam

09/15/2021, 12:34 AM
well they have generateSequence too
and one is suspend
one isn't
exactly like you're doing
so maybe generateArbitrary
m

mitch

09/15/2021, 12:35 AM
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

sam

09/15/2021, 12:38 AM
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

mitch

09/15/2021, 12:40 AM
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

sam

09/15/2021, 12:42 AM
its not about adding the receiver but the fact you're restricting suspension
arbitrary { delay(100) }
that won't work anymore because you're using suspension for your bind
m

mitch

09/15/2021, 12:46 AM
does that ever work?
arbitrary { delay(100) }
currently arbitrary isn’t inline
s

sam

09/15/2021, 12:46 AM
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

mitch

09/15/2021, 12:49 AM
yeah that’s a new feature to be able to call suspend fun inside of the arbitrary builder.
s

sam

09/15/2021, 12:49 AM
yeah I assumed the function was already suspendable
well you know what they say about assumptions, it killed the cat
m

mitch

09/15/2021, 12:50 AM
😆 i wasn’t too keen to make breaking changes either
s

sam

09/15/2021, 12:50 AM
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

mitch

09/15/2021, 12:50 AM
thanks!
s

sam

09/15/2021, 12:52 AM
I think kotest property testing must be, or close to being, the most powerful out there now.
💯 1
m

mitch

09/15/2021, 12:53 AM
haha 100%!
@sam i just checked that
generateSequence
isn’t suspend
and i wasn’t sure what to name it, naming is hard 😢
s

sam

09/17/2021, 9:00 PM
not sure we need it then ?
sorry to waste your time
m

mitch

09/17/2021, 9:02 PM
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

sam

09/17/2021, 9:03 PM
right
m

mitch

09/17/2021, 9:48 PM
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