I ignored it, but main problem will be that Kotlin is (for the best I think) staticaly typed.
If I take my previous example, you really need a strong type to be able to use, it.
To illustrate, my purpose, I add a typealias (but this syntax does not work in Kotlin could work in Ceylon or Typescript).
typealias NaturalNumber = Int|Long|BigInteger
typealias NaturalNumberRange = IntRange|LongRange
typealias FizzBuzzSet = Map<NaturalNumber, String>
/**
* This is the main extension function solving
*/
val NaturalNumber.fizzBuzz: String
get() {
//just an example of 'by lazy usage', here we could simply
//initialize isFizz or isBuzz directly
//but the examples shows how lambda can be smart
val isFizz by lazy { this % 3 == 0 }
val isBuzz by lazy { this % 5 == 0 }
return when {
isFizz && isBuzz -> "FizzBuzz"
isFizz -> "Fizz"
isBuzz -> "Buzz"
else -> this.toString()
}
}
/**
* Using property exension to add fizzBuzz to IntRange
*/
val NaturalNumberRange.fizzBuzz: FizzBuzzSet
get() = asIterable().fizzBuzz
/**
* Iterable is a Java interface more general than Collection. It just means i can browse some values. A lot of Kotlin extensions functions are avaialable through Iterable.
*
*
*/
val Iterable<NaturalNumber>.fizzBuzz: FizzBuzzSet
get() = associate { value -> Pair(value, value.fizzBuzz) }.toSortedMap()
val FizzBuzzSet.plainText: String
get() = when {
isEmpty() -> "No fizz buzz !"
else -> "FizzBuzz all !!!! :\n" + map { (key, value) -> "$key : $value" }.reduce { prev, next -> "$prev\n$next" }
}
Note that having typelias with multiple possible type could solve the problem too (and even more). The only problem is to find a subset of property/methods commons to all types defined in the alias.
And you could do in that case :
1.fizzBuzz
1L.fizzBuzz
1.toBigInteger().fizzBuzz