Try.Failure is no longer parameterised on Nothing, to avoid any issues with Java

This commit is contained in:
Shams Asari 2017-09-10 14:10:57 +01:00
parent f76ce0f0ce
commit 4c3ac89d6b
3 changed files with 22 additions and 17 deletions

View File

@ -59,7 +59,7 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
fun generateOrFail(random: SplittableRandom, numberOfTries: Int = 1): A {
var error: Throwable? = null
for (i in 0..numberOfTries - 1) {
for (i in 0 until numberOfTries) {
val result = generate(random)
error = when (result) {
is Try.Success -> return result.value
@ -115,13 +115,14 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
fun <A> frequency(vararg generators: Pair<Double, Generator<A>>) = frequency(generators.toList())
fun <A> sequence(generators: List<Generator<A>>) = Generator<List<A>> {
fun <A> sequence(generators: List<Generator<A>>) = Generator {
val result = mutableListOf<A>()
for (generator in generators) {
val element = generator.generate(it)
@Suppress("UNCHECKED_CAST")
when (element) {
is Try.Success -> result.add(element.value)
is Try.Failure -> return@Generator element
is Try.Failure -> return@Generator element as Try<List<A>>
}
}
Try.Success(result)
@ -135,12 +136,12 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
fun intRange(range: IntRange) = intRange(range.first, range.last)
fun intRange(from: Int, to: Int): Generator<Int> = Generator.success {
(from + Math.abs(it.nextInt()) % (to - from + 1)).toInt()
(from + Math.abs(it.nextInt()) % (to - from + 1))
}
fun longRange(range: LongRange) = longRange(range.first, range.last)
fun longRange(from: Long, to: Long): Generator<Long> = Generator.success {
(from + Math.abs(it.nextLong()) % (to - from + 1)).toLong()
(from + Math.abs(it.nextLong()) % (to - from + 1))
}
fun double() = Generator.success { it.nextDouble() }
@ -153,7 +154,7 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
if (Character.isValidCodePoint(codePoint)) {
return@Generator Try.Success(codePoint.toChar())
} else {
Try.Failure(IllegalStateException("Could not generate valid codepoint"))
Try.Failure<Any>(IllegalStateException("Could not generate valid codepoint"))
}
}
@ -174,7 +175,7 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
}
fun <A> replicatePoisson(meanSize: Double, generator: Generator<A>, atLeastOne: Boolean = false) = Generator<List<A>> {
fun <A> replicatePoisson(meanSize: Double, generator: Generator<A>, atLeastOne: Boolean = false) = Generator {
val chance = (meanSize - 1) / meanSize
val result = mutableListOf<A>()
var finish = false
@ -190,7 +191,8 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
}
}
if (res is Try.Failure) {
return@Generator res
@Suppress("UNCHECKED_CAST")
return@Generator res as Try<List<A>>
}
}
Try.Success(result)
@ -200,11 +202,11 @@ class Generator<out A>(val generate: (SplittableRandom) -> Try<A>) {
fun <A> pickN(number: Int, list: List<A>) = Generator<List<A>> {
val mask = BitSet(list.size)
val size = Math.min(list.size, number)
for (i in 0..size - 1) {
for (i in 0 until size) {
// mask[i] = 1 desugars into mask.set(i, 1), which sets a range instead of a bit
mask[i] = true
}
for (i in 0..list.size - 1) {
for (i in 0 until list.size) {
val bit = mask[i]
val swapIndex = i + it.nextInt(size - i)
mask[i] = mask[swapIndex]

View File

@ -35,27 +35,30 @@ sealed class Try<out A> {
abstract fun getOrThrow(): A
/** Maps the given function to the value from this [Success], or returns `this` if this is a [Failure]. */
@Suppress("UNCHECKED_CAST")
inline fun <B> map(function: (A) -> B): Try<B> = when (this) {
is Success -> Success(function(value))
is Failure -> this
is Failure -> this as Try<B>
}
/** Returns the given function applied to the value from this [Success], or returns `this` if this is a [Failure]. */
@Suppress("UNCHECKED_CAST")
inline fun <B> flatMap(function: (A) -> Try<B>): Try<B> = when (this) {
is Success -> function(value)
is Failure -> this
is Failure -> this as Try<B>
}
/**
* Maps the given function to the values from this [Success] and [other], or returns `this` if this is a [Failure]
* or [other] if [other] is a [Failure].
*/
@Suppress("UNCHECKED_CAST")
inline fun <B, C> combine(other: Try<B>, function: (A, B) -> C): Try<C> = when (this) {
is Success -> when (other) {
is Success -> Success(function(value, other.value))
is Failure -> other
is Failure -> other as Try<C>
}
is Failure -> this
is Failure -> this as Try<C>
}
data class Success<out A>(val value: A) : Try<A>() {
@ -65,10 +68,10 @@ sealed class Try<out A> {
override fun toString(): String = "Success($value)"
}
data class Failure(val exception: Throwable) : Try<Nothing>() {
data class Failure<out A>(val exception: Throwable) : Try<A>() {
override val isSuccess: Boolean get() = false
override val isFailure: Boolean get() = true
override fun getOrThrow(): Nothing = throw exception
override fun getOrThrow(): A = throw exception
override fun toString(): String = "Failure($exception)"
}
}

View File

@ -170,7 +170,7 @@ object RPCApi {
override fun writeToClientMessage(context: SerializationContext, message: ClientMessage) {
message.putIntProperty(TAG_FIELD_NAME, Tag.RPC_REPLY.ordinal)
message.putLongProperty(RPC_ID_FIELD_NAME, id.toLong)
message.bodyBuffer.writeBytes(result.safeSerialize(context) { Try.Failure(it) }.bytes)
message.bodyBuffer.writeBytes(result.safeSerialize(context) { Try.Failure<Any>(it) }.bytes)
}
}