From 4ce13c950359e2bb8fe0d2bc9142c47ea74fa772 Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Wed, 18 Sep 2024 09:43:00 +0000 Subject: [PATCH] Introduce more detailed documentation to primitive iterators #KT-67379 Fixed Merge-request: KT-MR-17854 Merged-by: Vsevolod Tolstopyatov --- generators/builtins/iterators.kt | 63 +++- .../kotlin/collections/PrimitiveIterators.kt | 304 +++++++++++++++++- 2 files changed, 344 insertions(+), 23 deletions(-) diff --git a/generators/builtins/iterators.kt b/generators/builtins/iterators.kt index 5b1db9f214e29..7a59c4f6b145d 100644 --- a/generators/builtins/iterators.kt +++ b/generators/builtins/iterators.kt @@ -23,16 +23,65 @@ import java.io.PrintWriter class GenerateIterators(out: PrintWriter) : BuiltInsSourceGenerator(out) { override fun getPackage() = "kotlin.collections" override fun generateBody() { - for (kind in PrimitiveType.values()) { - val s = kind.capitalized - out.println("/** An iterator over a sequence of values of type `$s`. */") - out.println("public abstract class ${s}Iterator : Iterator<$s> {" ) - out.println(" final override fun next(): $s = next$s()") + for (kind in PrimitiveType.entries) { + val type = kind.capitalized + out.println(""" +/** + * An iterator over a sequence of values of type `${type}`. + * + * This is a substitute for `Iterator<${type}>` that provides a specialized version of `next(): T` method: `next${type}(): $type` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class ${type}Container(private val data: ${type}Array) { + * + * // ${type}Iterator instead of Iterator<${type}> in the signature + * operator fun iterator(): ${type}Iterator = object : ${type}Iterator() { + * private var idx = 0 + * + * override fun next${type}(): $type { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in ${type}Container(${kind.arraySample()})) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ + """.trimIndent()) + out.println("public abstract class ${type}Iterator : Iterator<$type> {") + out.println(" final override fun next(): $type = next$type()") out.println() - out.println(" /** Returns the next value in the sequence without boxing. */") - out.println(" public abstract fun next$s(): $s") + out.println(""" + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */""") + out.println(" public abstract fun next$type(): $type") out.println("}") out.println() } } + + private fun PrimitiveType.arraySample(): String { + return when (this) { + PrimitiveType.BYTE -> "byteArrayOf(1, 2, 3)" + PrimitiveType.CHAR -> "charArrayOf('1', '2', '3')" + PrimitiveType.SHORT -> "shortArrayOf(1, 2, 3)" + PrimitiveType.INT -> "intArrayOf(1, 2, 3)" + PrimitiveType.LONG -> "longArrayOf(1, 2, 3)" + PrimitiveType.FLOAT -> "floatArrayOf(1f, 2f, 3f)" + PrimitiveType.DOUBLE -> "doubleArrayOf(1.0, 2.0, 3.0)" + PrimitiveType.BOOLEAN -> "booleanArrayOf(true, false, true)" + } + } } diff --git a/libraries/stdlib/src/kotlin/collections/PrimitiveIterators.kt b/libraries/stdlib/src/kotlin/collections/PrimitiveIterators.kt index e3ef3346b6dde..769743b073731 100644 --- a/libraries/stdlib/src/kotlin/collections/PrimitiveIterators.kt +++ b/libraries/stdlib/src/kotlin/collections/PrimitiveIterators.kt @@ -8,67 +8,339 @@ package kotlin.collections -/** An iterator over a sequence of values of type `Byte`. */ +/** + * An iterator over a sequence of values of type `Byte`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextByte(): Byte` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class ByteContainer(private val data: ByteArray) { + * + * // ByteIterator instead of Iterator in the signature + * operator fun iterator(): ByteIterator = object : ByteIterator() { + * private var idx = 0 + * + * override fun nextByte(): Byte { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in ByteContainer(byteArrayOf(1, 2, 3))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class ByteIterator : Iterator { final override fun next(): Byte = nextByte() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextByte(): Byte } -/** An iterator over a sequence of values of type `Char`. */ +/** + * An iterator over a sequence of values of type `Char`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextChar(): Char` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class CharContainer(private val data: CharArray) { + * + * // CharIterator instead of Iterator in the signature + * operator fun iterator(): CharIterator = object : CharIterator() { + * private var idx = 0 + * + * override fun nextChar(): Char { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in CharContainer(charArrayOf('1', '2', '3'))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class CharIterator : Iterator { final override fun next(): Char = nextChar() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextChar(): Char } -/** An iterator over a sequence of values of type `Short`. */ +/** + * An iterator over a sequence of values of type `Short`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextShort(): Short` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class ShortContainer(private val data: ShortArray) { + * + * // ShortIterator instead of Iterator in the signature + * operator fun iterator(): ShortIterator = object : ShortIterator() { + * private var idx = 0 + * + * override fun nextShort(): Short { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in ShortContainer(shortArrayOf(1, 2, 3))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class ShortIterator : Iterator { final override fun next(): Short = nextShort() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextShort(): Short } -/** An iterator over a sequence of values of type `Int`. */ +/** + * An iterator over a sequence of values of type `Int`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextInt(): Int` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class IntContainer(private val data: IntArray) { + * + * // IntIterator instead of Iterator in the signature + * operator fun iterator(): IntIterator = object : IntIterator() { + * private var idx = 0 + * + * override fun nextInt(): Int { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in IntContainer(intArrayOf(1, 2, 3))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class IntIterator : Iterator { final override fun next(): Int = nextInt() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextInt(): Int } -/** An iterator over a sequence of values of type `Long`. */ +/** + * An iterator over a sequence of values of type `Long`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextLong(): Long` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class LongContainer(private val data: LongArray) { + * + * // LongIterator instead of Iterator in the signature + * operator fun iterator(): LongIterator = object : LongIterator() { + * private var idx = 0 + * + * override fun nextLong(): Long { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in LongContainer(longArrayOf(1, 2, 3))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class LongIterator : Iterator { final override fun next(): Long = nextLong() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextLong(): Long } -/** An iterator over a sequence of values of type `Float`. */ +/** + * An iterator over a sequence of values of type `Float`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextFloat(): Float` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class FloatContainer(private val data: FloatArray) { + * + * // FloatIterator instead of Iterator in the signature + * operator fun iterator(): FloatIterator = object : FloatIterator() { + * private var idx = 0 + * + * override fun nextFloat(): Float { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in FloatContainer(floatArrayOf(1f, 2f, 3f))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class FloatIterator : Iterator { final override fun next(): Float = nextFloat() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextFloat(): Float } -/** An iterator over a sequence of values of type `Double`. */ +/** + * An iterator over a sequence of values of type `Double`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextDouble(): Double` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class DoubleContainer(private val data: DoubleArray) { + * + * // DoubleIterator instead of Iterator in the signature + * operator fun iterator(): DoubleIterator = object : DoubleIterator() { + * private var idx = 0 + * + * override fun nextDouble(): Double { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in DoubleContainer(doubleArrayOf(1.0, 2.0, 3.0))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class DoubleIterator : Iterator { final override fun next(): Double = nextDouble() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextDouble(): Double } -/** An iterator over a sequence of values of type `Boolean`. */ +/** + * An iterator over a sequence of values of type `Boolean`. + * + * This is a substitute for `Iterator` that provides a specialized version of `next(): T` method: `nextBoolean(): Boolean` + * and has a special handling by the compiler to avoid platform-specific boxing conversions as a performance optimization. + * + * In the following example: + * + * ```kotlin + * class BooleanContainer(private val data: BooleanArray) { + * + * // BooleanIterator instead of Iterator in the signature + * operator fun iterator(): BooleanIterator = object : BooleanIterator() { + * private var idx = 0 + * + * override fun nextBoolean(): Boolean { + * if (!hasNext()) throw NoSuchElementException() + * return data[idx++] + * } + * + * override fun hasNext(): Boolean = idx < data.size + * } + * } + * + * for (element in BooleanContainer(booleanArrayOf(true, false, true))) { + * ... handle element ... + * } + * ``` + * No boxing conversion is performed during the for-loop iteration. + * Note that the iterator itself will still be allocated. + */ public abstract class BooleanIterator : Iterator { final override fun next(): Boolean = nextBoolean() - /** Returns the next value in the sequence without boxing. */ + + /** + * Returns the next element in the iteration without boxing conversion. + * @throws NoSuchElementException if the iteration has no next element. + */ public abstract fun nextBoolean(): Boolean }