From 34ee44b532c5b92b258e471a3a30b58f857aa21d Mon Sep 17 00:00:00 2001 From: Mike Hearn <mike@r3cev.com> Date: Thu, 8 Sep 2016 13:08:45 +0200 Subject: [PATCH 1/2] Minor: move ErrorOr into the core module and tweak its API a bit. Add a Path div operator. --- .../kotlin/com/r3corda/client/mock/ErrorOr.kt | 40 ----------------- .../com/r3corda/client/mock/Generator.kt | 23 ++++++---- .../src/main/kotlin/com/r3corda/core/Utils.kt | 43 ++++++++++++++++++- 3 files changed, 56 insertions(+), 50 deletions(-) delete mode 100644 client/src/main/kotlin/com/r3corda/client/mock/ErrorOr.kt diff --git a/client/src/main/kotlin/com/r3corda/client/mock/ErrorOr.kt b/client/src/main/kotlin/com/r3corda/client/mock/ErrorOr.kt deleted file mode 100644 index 1dee4278be..0000000000 --- a/client/src/main/kotlin/com/r3corda/client/mock/ErrorOr.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.r3corda.client.mock - -class ErrorOr<out A> private constructor( - val value: A?, - val error: Exception? -) { - constructor(value: A): this(value, null) - constructor(error: Exception): this(null, error) - - fun <T> match(onValue: (A) -> T, onError: (Exception) -> T): T { - if (value != null) { - return onValue(value) - } else { - return onError(error!!) - } - } - - fun getValueOrThrow(): A { - if (value != null) { - return value - } else { - throw error!! - } - } - - // Functor - fun <B> map(function: (A) -> B): ErrorOr<B> { - return ErrorOr(value?.let(function), error) - } - - // Applicative - fun <B, C> combine(other: ErrorOr<B>, function: (A, B) -> C): ErrorOr<C> { - return ErrorOr(value?.let { a -> other.value?.let { b -> function(a, b) } }, error ?: other.error) - } - - // Monad - fun <B> bind(function: (A) -> ErrorOr<B>): ErrorOr<B> { - return value?.let(function) ?: ErrorOr<B>(error!!) - } -} diff --git a/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt b/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt index 6991dec7a5..1d998c442d 100644 --- a/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt +++ b/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt @@ -1,5 +1,7 @@ package com.r3corda.client.mock +import com.r3corda.client.mock.Generator.Companion.choice +import com.r3corda.core.ErrorOr import java.util.* /** @@ -54,7 +56,7 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) { companion object { fun <A> pure(value: A) = Generator { ErrorOr(value) } fun <A> impure(valueClosure: () -> A) = Generator { ErrorOr(valueClosure()) } - fun <A> fail(error: Exception) = Generator<A> { ErrorOr(error) } + fun <A> fail(error: Exception) = Generator<A> { ErrorOr.of(error) } // Alternative fun <A> choice(generators: List<Generator<A>>) = intRange(0, generators.size - 1).bind { generators[it] } @@ -85,10 +87,11 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) { val result = mutableListOf<A>() for (generator in generators) { val element = generator.generate(it) - if (element.value != null) { - result.add(element.value) + val v = element.value + if (v != null) { + result.add(v) } else { - return@Generator ErrorOr(element.error!!) + return@Generator ErrorOr.of(element.error!!) } } ErrorOr(result) @@ -99,11 +102,12 @@ class Generator<out A>(val generate: (Random) -> ErrorOr<A>) { fun <A> Generator.Companion.oneOf(list: List<A>) = intRange(0, list.size - 1).map { list[it] } fun <A> Generator<A>.generateOrFail(random: Random, numberOfTries: Int = 1): A { - var error: Exception? = null + var error: Throwable? = null for (i in 0 .. numberOfTries - 1) { val result = generate(random) - if (result.value != null) { - return result.value + val v = result.value + if (v != null) { + return v } else { error = result.error } @@ -146,8 +150,9 @@ fun <A> Generator.Companion.replicatePoisson(meanSize: Double, generator: Genera ErrorOr(Unit) } } - if (errorOr.error != null) { - return@Generator ErrorOr(errorOr.error) + val e = errorOr.error + if (e != null) { + return@Generator ErrorOr.of(e) } } ErrorOr(result) diff --git a/core/src/main/kotlin/com/r3corda/core/Utils.kt b/core/src/main/kotlin/com/r3corda/core/Utils.kt index 33eecc541c..67a3eb4ed8 100644 --- a/core/src/main/kotlin/com/r3corda/core/Utils.kt +++ b/core/src/main/kotlin/com/r3corda/core/Utils.kt @@ -218,4 +218,45 @@ fun extractZipFile(zipPath: Path, toPath: Path) { // TODO: Generic csv printing utility for clases. -val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this) \ No newline at end of file +val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this) + +/** Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform separator problems. */ +operator fun Path.div(other: String): Path = resolve(other) + +/** Representation of an operation that may have thrown an error. */ +data class ErrorOr<out A> private constructor(val value: A?, val error: Throwable?) { + constructor(value: A) : this(value, null) + + companion object { + /** Runs the given lambda and wraps the result. */ + inline fun <T> catch(body: () -> T): ErrorOr<T> = try { ErrorOr(body()) } catch (t: Throwable) { ErrorOr.of(t) } + fun of(t: Throwable) = ErrorOr(null, t) + } + + fun <T> match(onValue: (A) -> T, onError: (Throwable) -> T): T { + if (value != null) { + return onValue(value) + } else { + return onError(error!!) + } + } + + fun getOrThrow(): A { + if (value != null) { + return value + } else { + throw error!! + } + } + + // Functor + fun <B> map(function: (A) -> B) = ErrorOr(value?.let(function), error) + + // Applicative + fun <B, C> combine(other: ErrorOr<B>, function: (A, B) -> C): ErrorOr<C> { + return ErrorOr(value?.let { a -> other.value?.let { b -> function(a, b) } }, error ?: other.error) + } + + // Monad + fun <B> bind(function: (A) -> ErrorOr<B>) = value?.let(function) ?: ErrorOr.of(error!!) +} \ No newline at end of file From af72978acef92fe528d6238cca262d40f2a5e4fa Mon Sep 17 00:00:00 2001 From: Mike Hearn <mike@r3cev.com> Date: Thu, 8 Sep 2016 14:41:17 +0200 Subject: [PATCH 2/2] Remove redundant import. --- client/src/main/kotlin/com/r3corda/client/mock/Generator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt b/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt index 1d998c442d..1ef0f64ae9 100644 --- a/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt +++ b/client/src/main/kotlin/com/r3corda/client/mock/Generator.kt @@ -1,6 +1,5 @@ package com.r3corda.client.mock -import com.r3corda.client.mock.Generator.Companion.choice import com.r3corda.core.ErrorOr import java.util.*