standard library: 'sum' function added (KT-3714, KT-3843, KT-3126)
This commit is contained in:
@@ -408,3 +408,45 @@ public inline fun <T> Array<out T>.withIndices() : Iterator<Pair<Int, T>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Byte>.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Short>.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Int>.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Long>.sum() : Long {
|
||||||
|
return fold(0.toLong(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Float>.sum() : Float {
|
||||||
|
return fold(0.toFloat(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Array<Double>.sum() : Double {
|
||||||
|
return fold(0.0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun ByteArray.withIndices() : Iterator<Pair<Int, Byte>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun ByteArray.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun DoubleArray.withIndices() : Iterator<Pair<Int, Double>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun DoubleArray.sum() : Double {
|
||||||
|
return fold(0.0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun FloatArray.withIndices() : Iterator<Pair<Int, Float>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun FloatArray.sum() : Float {
|
||||||
|
return fold(0.toFloat(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun IntArray.withIndices() : Iterator<Pair<Int, Int>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun IntArray.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -376,3 +376,31 @@ public inline fun <T> Iterable<T>.withIndices() : Iterator<Pair<Int, T>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Iterable<Int>.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Iterable<Long>.sum() : Long {
|
||||||
|
return fold(0.toLong(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Iterable<Float>.sum() : Float {
|
||||||
|
return fold(0.toFloat(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun Iterable<Double>.sum() : Double {
|
||||||
|
return fold(0.0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun LongArray.withIndices() : Iterator<Pair<Int, Long>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun LongArray.sum() : Long {
|
||||||
|
return fold(0.toLong(), {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -381,3 +381,10 @@ public inline fun ShortArray.withIndices() : Iterator<Pair<Int, Short>> {
|
|||||||
return IndexIterator(iterator())
|
return IndexIterator(iterator())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sums up the elements
|
||||||
|
*/
|
||||||
|
public fun ShortArray.sum() : Int {
|
||||||
|
return fold(0, {a,b -> a+b})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,4 +58,14 @@ class ArraysJVMTest {
|
|||||||
intArray().reduceRight { a, b -> a + b}
|
intArray().reduceRight { a, b -> a + b}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test fun sum() {
|
||||||
|
expect(0) { intArray().sum() }
|
||||||
|
expect(14) { intArray(2, 3, 9).sum() }
|
||||||
|
expect(3.0) { doubleArray(1.0, 2.0).sum() }
|
||||||
|
expect(200) { byteArray(100, 100).sum() }
|
||||||
|
expect(50000) { shortArray(20000, 30000).sum() }
|
||||||
|
expect(3000000000000) { longArray(1000000000000, 2000000000000).sum() }
|
||||||
|
expect(3.0) { floatArray(1.0, 2.0).sum() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,16 @@ class ArraysTest {
|
|||||||
assertEquals(false, arr[1])
|
assertEquals(false, arr[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test fun sum() {
|
||||||
|
expect(0) { array<Int>().sum() }
|
||||||
|
expect(14) { array(2, 3, 9).sum() }
|
||||||
|
expect(3.0) { array(1.0, 2.0).sum() }
|
||||||
|
expect(200) { array<Byte>(100, 100).sum() }
|
||||||
|
expect(50000) { array<Short>(20000, 30000).sum() }
|
||||||
|
//TODO: uncomment when toLong() will be supported
|
||||||
|
//expect(3000000000000) { array<Long>(1000000000000, 2000000000000).sum() }
|
||||||
|
expect(3.0) { array<Float>(1.0, 2.0).sum() }
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
TODO FIXME ASAP: These currently fail on JS due to missing upto() method on numbers
|
TODO FIXME ASAP: These currently fail on JS due to missing upto() method on numbers
|
||||||
|
|||||||
@@ -414,6 +414,14 @@ class CollectionTest {
|
|||||||
expect(arrayList(2, 3, 1)) { list }
|
expect(arrayList(2, 3, 1)) { list }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test fun sum() {
|
||||||
|
expect(0) { ArrayList<Int>().sum() }
|
||||||
|
expect(14) { arrayListOf(2, 3, 9).sum() }
|
||||||
|
expect(3.0) { arrayListOf(1.0, 2.0).sum() }
|
||||||
|
expect(3000000000000) { arrayListOf<Long>(1000000000000, 2000000000000).sum() }
|
||||||
|
expect(3.0) { arrayListOf<Float>(1.0, 2.0).sum() }
|
||||||
|
}
|
||||||
|
|
||||||
class IterableWrapper<T>(collection : Iterable<T>) : Iterable<T> {
|
class IterableWrapper<T>(collection : Iterable<T>) : Iterable<T> {
|
||||||
private val collection = collection
|
private val collection = collection
|
||||||
|
|
||||||
|
|||||||
@@ -29,27 +29,27 @@ fun main(args: Array<String>) {
|
|||||||
generateDomEventsAPI(File(jsCoreDir, "domEvents.kt"))
|
generateDomEventsAPI(File(jsCoreDir, "domEvents.kt"))
|
||||||
|
|
||||||
iterators().writeTo(File(outDir, "_Iterators.kt")) {
|
iterators().writeTo(File(outDir, "_Iterators.kt")) {
|
||||||
buildFor(Iterators, "")
|
buildFor(Iterators, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val iterables = iterables()
|
val iterables = iterables()
|
||||||
iterables.writeTo(File(outDir, "_Arrays.kt")) {
|
val sumFunctions = PrimitiveType.values().map(::sumFunction).filterNotNull()
|
||||||
buildFor(Arrays, "")
|
(iterables + sumFunctions).writeTo(File(outDir, "_Arrays.kt")) {
|
||||||
|
buildFor(Arrays, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
val otherArrayNames = arrayListOf("Boolean", "Byte", "Char", "Short", "Int", "Long", "Float", "Double")
|
for (primitive in PrimitiveType.values()) {
|
||||||
for (a in otherArrayNames) {
|
(iterables + sumFunction(primitive)).filterNotNull().writeTo(File(outDir, "_${primitive.name}Arrays.kt")) {
|
||||||
iterables.writeTo(File(outDir, "_${a}Arrays.kt")) {
|
buildFor(PrimitiveArrays, primitive)
|
||||||
buildFor(PrimitiveArrays, a)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterables.writeTo(File(outDir, "_Iterables.kt")) {
|
(iterables + sumFunctions).writeTo(File(outDir, "_Iterables.kt")) {
|
||||||
buildFor(Iterables, "")
|
buildFor(Iterables, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
collections().writeTo(File(outDir, "_Collections.kt")) {
|
collections().writeTo(File(outDir, "_Collections.kt")) {
|
||||||
buildFor(Collections, "")
|
buildFor(Collections, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
generateDownTos(File(outDir, "_DownTo.kt"), "package kotlin")
|
generateDownTos(File(outDir, "_DownTo.kt"), "package kotlin")
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ enum class Family {
|
|||||||
class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
||||||
var doc : String = ""
|
var doc : String = ""
|
||||||
var toNullableT : Boolean = false
|
var toNullableT : Boolean = false
|
||||||
val isInline : Boolean = true;
|
var isInline : Boolean = true;
|
||||||
|
private val customReceivers = HashMap<Family, String>()
|
||||||
val blockedFor = HashSet<Family>()
|
val blockedFor = HashSet<Family>()
|
||||||
val bodies = HashMap<Family, String>()
|
val bodies = HashMap<Family, String>()
|
||||||
val returnTypes = HashMap<Family, String>()
|
val returnTypes = HashMap<Family, String>()
|
||||||
@@ -44,6 +45,10 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
returnTypes[this] = r
|
returnTypes[this] = r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Family.customReceiver(r: String) {
|
||||||
|
customReceivers[this] = r
|
||||||
|
}
|
||||||
|
|
||||||
fun typeParam(t:String) {
|
fun typeParam(t:String) {
|
||||||
typeParams.add(t)
|
typeParams.add(t)
|
||||||
}
|
}
|
||||||
@@ -54,7 +59,7 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
|
|
||||||
private fun effectiveTypeParams(f : Family) : List<String> {
|
private fun effectiveTypeParams(f : Family) : List<String> {
|
||||||
val types = ArrayList(typeParams)
|
val types = ArrayList(typeParams)
|
||||||
if (typeParams.find { it.startsWith("T") } == null) {
|
if (typeParams.find { it.startsWith("T") } == null && !customReceivers.containsKey(f)) {
|
||||||
types.add(0, "T")
|
types.add(0, "T")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +72,7 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun buildFor(f: Family, arrName : String = "") : String {
|
fun buildFor(f: Family, primitiveType: PrimitiveType?) : String {
|
||||||
if (blockedFor.contains(f)) return ""
|
if (blockedFor.contains(f)) return ""
|
||||||
|
|
||||||
if (returnTypes[f] == null) throw RuntimeException("No return type specified for $signature")
|
if (returnTypes[f] == null) throw RuntimeException("No return type specified for $signature")
|
||||||
@@ -78,7 +83,7 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
Collections -> "Collection<T>"
|
Collections -> "Collection<T>"
|
||||||
Iterators -> "Iterator<T>"
|
Iterators -> "Iterator<T>"
|
||||||
Arrays -> "Array<out T>"
|
Arrays -> "Array<out T>"
|
||||||
PrimitiveArrays -> "${arrName}Array"
|
PrimitiveArrays -> "${primitiveType!!.name}Array"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.renderType() : String {
|
fun String.renderType() : String {
|
||||||
@@ -89,7 +94,7 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
val token = t.nextToken()
|
val token = t.nextToken()
|
||||||
answer.append(when (token) {
|
answer.append(when (token) {
|
||||||
"SELF" -> selftype
|
"SELF" -> selftype
|
||||||
"T" -> if (f == Family.PrimitiveArrays) arrName else token
|
"T" -> if (f == Family.PrimitiveArrays) primitiveType!!.name else token
|
||||||
else -> token
|
else -> token
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -120,7 +125,7 @@ class GenericFunction(val signature : String): Comparable<GenericFunction> {
|
|||||||
builder.append(types.makeString(separator = ", ", prefix = "<", postfix = "> ").renderType())
|
builder.append(types.makeString(separator = ", ", prefix = "<", postfix = "> ").renderType())
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append((
|
builder.append((customReceivers[f] ?:
|
||||||
if (toNullableT) {
|
if (toNullableT) {
|
||||||
selftype.replace("T>", "T?>")
|
selftype.replace("T>", "T?>")
|
||||||
}
|
}
|
||||||
@@ -160,6 +165,6 @@ fun f(signature : String, init : GenericFunction.() -> Unit): GenericFunction {
|
|||||||
fun main(args : Array<String>) {
|
fun main(args : Array<String>) {
|
||||||
val templates = collections()
|
val templates = collections()
|
||||||
for (t in templates) {
|
for (t in templates) {
|
||||||
print(t.buildFor(PrimitiveArrays, "Byte"))
|
print(t.buildFor(PrimitiveArrays, PrimitiveType.Byte))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package templates
|
||||||
|
|
||||||
|
import templates.Family.*
|
||||||
|
|
||||||
|
enum class PrimitiveType(val name: String) {
|
||||||
|
Boolean: PrimitiveType("Boolean")
|
||||||
|
Byte: PrimitiveType("Byte")
|
||||||
|
Char: PrimitiveType("Char")
|
||||||
|
Short: PrimitiveType("Short")
|
||||||
|
Int: PrimitiveType("Int")
|
||||||
|
Long: PrimitiveType("Long")
|
||||||
|
Float: PrimitiveType("Float")
|
||||||
|
Double: PrimitiveType("Double")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PrimitiveType.zero() = when (this) {
|
||||||
|
PrimitiveType.Int -> "0"
|
||||||
|
PrimitiveType.Byte -> "0"
|
||||||
|
PrimitiveType.Short -> "0"
|
||||||
|
PrimitiveType.Long -> "0.toLong()"
|
||||||
|
PrimitiveType.Double -> "0.0"
|
||||||
|
PrimitiveType.Float -> "0.toFloat()"
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun returnTypeForSum(primitive: PrimitiveType) = when (primitive) {
|
||||||
|
PrimitiveType.Byte -> PrimitiveType.Int
|
||||||
|
PrimitiveType.Short -> PrimitiveType.Int
|
||||||
|
else -> primitive
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sumFunction(primitive: PrimitiveType) = primitive.zero()?.let { zero ->
|
||||||
|
f("sum()") {
|
||||||
|
doc = "Sums up the elements"
|
||||||
|
isInline = false
|
||||||
|
if (returnTypeForSum(primitive) != primitive) {
|
||||||
|
//this is required to avoid clash of erasured method signatures (Iterables.sum(): Int)
|
||||||
|
absentFor(Iterables)
|
||||||
|
}
|
||||||
|
Iterables.customReceiver("Iterable<${primitive.name}>")
|
||||||
|
Arrays.customReceiver("Array<${primitive.name}>")
|
||||||
|
returns(returnTypeForSum(primitive).name)
|
||||||
|
body {
|
||||||
|
"return fold($zero, {a,b -> a+b})"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user