I realized having to host this potentially indefinitely might not be the best idea, so I am going to shut down this gitea instance eventually.
You’ll have time, at least until the end of 2022, probably longer, but please just get all your stuff somewhere safe in case we ever disappear.
If any of your build scripts rely on my (kageru’s) projects hosted here, check my Github or IEW on Github for encoding projects. If you can’t find what you’re looking there, tell me to migrate it.

initial commit

master
kageru 2 years ago
commit 1cdf942f9d
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
  1. 46
      Option.kt
  2. 40
      OptionTest.kt
  3. 14
      README.md

@ -0,0 +1,46 @@
@Suppress("NON_PUBLIC_PRIMARY_CONSTRUCTOR_OF_INLINE_CLASS", "UNCHECKED_CAST")
inline class Option<A> private constructor(val value: Any?) {
inline fun <R> map(op: (A) -> R): Option<R> =
if (this.value === EmptyOptionValue) {
this as Option<R>
} else {
Option.just(op(this.value as A))
}
inline fun filter(op: (A) -> Boolean): Option<A> =
if (this.value === EmptyOptionValue || !op(this.value as A)) {
none()
} else {
this
}
inline fun <R> fold(ifPresent: (A) -> R, ifEmpty: () -> R): R =
if (this.value === EmptyOptionValue) {
ifEmpty()
} else {
ifPresent(this.value as A)
}
fun getOrNull(): A? =
if (this.value === EmptyOptionValue) {
null
} else {
this.value as A
}
companion object {
private val EMPTY = Option<Any>(EmptyOptionValue)
fun <A> none() = EMPTY as Option<A>
fun <A> just(value: A) = Option<A>(value)
}
}
/**
* Marker for empty options.
* This is necessary to allow nullable types in the option.
* TODO: Somehow dont expose this.
*/
object EmptyOptionValue

@ -0,0 +1,40 @@
fun main() {
testMap()
testFilter()
testFold()
shouldHandleNullableTypes()
}
fun testMap() {
assertEquals(Option.just(3).map { it * 2 }.map { "$it" }.getOrNull(), "6")
assertEquals(Option.just(listOf(1)).map { it.first() }.getOrNull(), 1)
assertEquals(Option.none<Int>().map { error("Should not be executed") }.getOrNull(), null)
}
fun testFilter() {
assertEquals(Option.just(6).filter { it > 5 }.getOrNull(), 6)
assertEquals(Option.just(6).filter { it < 5 }.getOrNull(), null)
}
fun testFold() {
assertEquals(Option.just(2).map { it * 2 }.fold({ it / 2 }, { error("Should not be executed") }), 2)
assertEquals(Option.none<Int>().fold({ error("Should not be executed") }, { 2 }), 2)
}
fun shouldHandleNullableTypes() {
assertEquals(Option.just<Int?>(null).map { it ?: 5 }.getOrNull(), 5)
assertEquals(
Option.just<List<String>>(emptyList())
.map { it.firstOrNull() }
.fold({ it }, { error("Should not be executed") }),
null
)
}
private fun <T> assertEquals(x: T, y: T) {
if (x != y) {
error("$x was not equal to $y")
}
}

@ -0,0 +1,14 @@
# inline-option
An implementation of an `Option<A>` type in Kotlin using the `inline class` feature.
See https://kotlinlang.org/docs/reference/inline-classes.html
It’s just a small proof of concept which is why I decided to omit the usual gradle bloat.
Build and test via:
```sh
$ kotlinc-native Option.kt OptionTest.kt
$ ./program.kexe
```
The implementation uses an empty value placeholder to allow for nullable types (i.e. `Option<Int?>`).
I don’t think those are ever a good idea to have, but I saw no reason not to support them.
Loading…
Cancel
Save