Add an abstraction for Natural Numbers

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