From 87060c7eb7e688d893fc6559e702ec8be1e5f37a Mon Sep 17 00:00:00 2001 From: sergeych Date: Mon, 20 Apr 2026 13:56:47 +0300 Subject: [PATCH] +inference bugs +List.ensureCapacity optimized List.fill --- docs/List.md | 7 +++++++ .../kotlin/net/sergeych/lyng/Compiler.kt | 4 ++++ .../kotlin/net/sergeych/lyng/obj/ObjList.kt | 16 +++++++++++++++ lynglib/src/commonTest/kotlin/StdlibTest.kt | 8 ++++++++ lynglib/stdlib/lyng/root.lyng | 20 +++++++++++++------ 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/docs/List.md b/docs/List.md index d857c26..a218f4e 100644 --- a/docs/List.md +++ b/docs/List.md @@ -175,6 +175,8 @@ List could be sorted in place, just like [Collection] provide sorted copies, in | `[Range]` | get slice of the array (copy) | Range | | `+=` | append element(s) (2) | List or Obj | | `List.fill(size, block)` | build a new list from indices `0.. predicate(a) <=> predicate(b) }` positive if first is greater, and zero if they are equal. For example, the equvalent comparator for `sort()` will be `sort { a, b -> a <=> b } +(5) +: if the current capacity is already ≥ `count`, this is a no-op. Otherwise the internal storage +is reallocated to hold at least `count` elements. Use this before a bulk `+=` loop to avoid +repeated reallocations. `List.fill(size, capacity, block)` calls this automatically. + It inherits from [Iterable] too and thus all iterable methods are applicable to any list. ## Observable list hooks diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt index 3b9d7c0..3313fbe 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/Compiler.kt @@ -3424,6 +3424,10 @@ class Compiler( index < expectedParams.size ) { expectedParams[index] + } else if (param.type == TypeDecl.TypeAny && index == 0 && argsDeclaration.params.size == 1 && + implicitItType != null + ) { + implicitItType } else { param.type } diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt index 5e800f1..73d93f7 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjList.kt @@ -528,6 +528,22 @@ open class ObjList(initialList: MutableList = mutableListOf()) : Obj() { } else self.list.removeLast() self } + addFnDoc( + name= "ensureCapacity", + doc = """ + ensure the list capacity allows storing specified amount if items without reallocation. + If current capacity is greater or equal to `count`, does nothing. Note that possible reallocation + could be a costly operation, + """.trimIndent(), + params = listOf(ParamDoc("count", type("lyng.Int"))), + moduleName = "lyng.stdlib" + ) { + val self = thisAs() + val list = self.list as ArrayList + val count = requireOnlyArg().value.toInt() + list.ensureCapacity(count) + self + } addFnDoc( name = "removeRange", diff --git a/lynglib/src/commonTest/kotlin/StdlibTest.kt b/lynglib/src/commonTest/kotlin/StdlibTest.kt index 233ca8c..14bff4e 100644 --- a/lynglib/src/commonTest/kotlin/StdlibTest.kt +++ b/lynglib/src/commonTest/kotlin/StdlibTest.kt @@ -436,4 +436,12 @@ class StdlibTest { assertEquals(2, x) """.trimIndent()) } + + @Test + fun testListFill() = runTest { + eval(""" + val x = List.fill(5) { i -> i * 10 } + assertEquals([0, 10, 20, 30, 40], x) + """.trimIndent()) + } } diff --git a/lynglib/stdlib/lyng/root.lyng b/lynglib/stdlib/lyng/root.lyng index 744b9af..e3615ff 100644 --- a/lynglib/stdlib/lyng/root.lyng +++ b/lynglib/stdlib/lyng/root.lyng @@ -432,11 +432,19 @@ fun List.sort(): void { sortWith { a, b -> a <=> b } } -/* Build a new list of `size` elements by calling `block(index)` for each index. */ -static fun List.fill(size: Int, block: (Int)->T): List { - val result = List() - for( i in 0...fill(size: Int, capacity = -1, block: (Int)->T): List { + require(size >= 0, "size must not be negative") + val capacity = capacity < size ? size : capacity + List().also { + if( size > 0 ) { + it.ensureCapacity(capacity) + for( i in 0..