Skip to content

Instantly share code, notes, and snippets.

@slaykovsky
Created March 20, 2018 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slaykovsky/e5c762b5816c0e37e0fbddfe2c57b89d to your computer and use it in GitHub Desktop.
Save slaykovsky/e5c762b5816c0e37e0fbddfe2c57b89d to your computer and use it in GitHub Desktop.
import java.math.BigDecimal
import java.util.*
inline fun <T> Iterable<T>.sumByPrice(selector: (T) -> Price): Price {
return this.fold(Price.identity) { a: Price, b: T -> a + selector(b) }
}
inline fun <T> Iterable<T>.sumByWeight(selector: (T) -> Weight): Weight {
return this.fold(Weight.identity) { a: Weight, b: T -> a + selector(b) }
}
data class Price private constructor(private val value: BigDecimal) {
override fun toString() = value.toString()
operator fun plus(price: Price) = Price(this.value + price.value)
operator fun times(num: Int) = Price(this.value * BigDecimal(num))
companion object {
val identity = Price(BigDecimal.ZERO)
operator fun invoke(value: BigDecimal): Optional<Price> {
if (value > BigDecimal.ZERO)
return Optional.of(Price(value))
else
throw IllegalArgumentException("Price must be positive")
}
}
}
data class Weight private constructor(private val value: BigDecimal) {
override fun toString() = value.toString()
operator fun plus(weight: Weight) = Weight(this.value + weight.value)
operator fun times(num: Int) = Weight(this.value * BigDecimal(num))
companion object {
val identity = Weight(BigDecimal.ZERO)
operator fun invoke(value: BigDecimal): Optional<Weight> {
if (value > BigDecimal.ZERO)
return Optional.of(Weight(value))
else throw IllegalArgumentException("Weight must be positive")
}
}
}
data class Product(val name: String, val price: Optional<Price>, val weight: Optional<Weight>)
data class OrderLine(private val product: Product, private val count: Int) {
fun weight() = product.weight.get() * count
fun amount() = product.price.get() * count
}
object Store {
@JvmStatic
fun main(args: Array<String>) {
val toothPaste = Product(
"Tooth paste",
Price(BigDecimal(1.5)),
Weight(BigDecimal(0.5)))
val toothBrush = Product(
"Tooth brush",
Price(BigDecimal(3.5)),
Weight(BigDecimal(0.3)))
val orderLines = listOf(
OrderLine(toothPaste, 2),
OrderLine(toothBrush, 3)
)
val weight = orderLines.sumByWeight { it.weight() }
val price = orderLines.sumByPrice { it.amount() }
println("Total price: $price")
println("Total weight: $weight")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment