+inference bugs

+List.ensureCapacity
optimized List.fill
This commit is contained in:
Sergey Chernov 2026-04-20 13:56:47 +03:00
parent 6ba128f7ba
commit 87060c7eb7
5 changed files with 49 additions and 6 deletions

View File

@ -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 | | `[Range]` | get slice of the array (copy) | Range |
| `+=` | append element(s) (2) | List or Obj | | `+=` | append element(s) (2) | List or Obj |
| `List.fill(size, block)` | build a new list from indices `0..<size` | Int, Callable | | `List.fill(size, block)` | build a new list from indices `0..<size` | Int, Callable |
| `List.fill(size,capacity,block)` | same, pre-allocating capacity slots | Int, Int, Callable |
| `ensureCapacity(count)` | pre-allocate storage for at least `count` elements without reallocation (5) | Int |
| `sort()` | in-place sort, natural order | void | | `sort()` | in-place sort, natural order | void |
| `sortBy(predicate)` | in-place sort bu `predicate` call result (3) | void | | `sortBy(predicate)` | in-place sort bu `predicate` call result (3) | void |
| `sortWith(comparator)` | in-place sort using `comarator` function (4) | void | | `sortWith(comparator)` | in-place sort using `comarator` function (4) | void |
@ -197,6 +199,11 @@ order, e.g. is same as `list.sortWith { a,b -> predicate(a) <=> predicate(b) }`
positive if first is greater, and zero if they are equal. For example, the equvalent comparator 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 } 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. It inherits from [Iterable] too and thus all iterable methods are applicable to any list.
## Observable list hooks ## Observable list hooks

View File

@ -3424,6 +3424,10 @@ class Compiler(
index < expectedParams.size index < expectedParams.size
) { ) {
expectedParams[index] expectedParams[index]
} else if (param.type == TypeDecl.TypeAny && index == 0 && argsDeclaration.params.size == 1 &&
implicitItType != null
) {
implicitItType
} else { } else {
param.type param.type
} }

View File

@ -528,6 +528,22 @@ open class ObjList(initialList: MutableList<Obj> = mutableListOf()) : Obj() {
} else self.list.removeLast() } else self.list.removeLast()
self 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<ObjList>()
val list = self.list as ArrayList
val count = requireOnlyArg<ObjInt>().value.toInt()
list.ensureCapacity(count)
self
}
addFnDoc( addFnDoc(
name = "removeRange", name = "removeRange",

View File

@ -436,4 +436,12 @@ class StdlibTest {
assertEquals(2, x) assertEquals(2, x)
""".trimIndent()) """.trimIndent())
} }
@Test
fun testListFill() = runTest {
eval("""
val x = List.fill(5) { i -> i * 10 }
assertEquals([0, 10, 20, 30, 40], x)
""".trimIndent())
}
} }

View File

@ -432,11 +432,19 @@ fun List<T>.sort(): void {
sortWith { a, b -> a <=> b } sortWith { a, b -> a <=> b }
} }
/* Build a new list of `size` elements by calling `block(index)` for each index. */ /*
static fun List<T>.fill(size: Int, block: (Int)->T): List<T> { Build a new list of `size` elements by calling `block(index)` for each index.
val result = List<T>() `capacity` less size is ignored (size will be used as capacity).
for( i in 0..<size ) result += block(i) */
result static fun List<T>.fill(size: Int, capacity = -1, block: (Int)->T): List<T> {
require(size >= 0, "size must not be negative")
val capacity = capacity < size ? size : capacity
List<T>().also {
if( size > 0 ) {
it.ensureCapacity(capacity)
for( i in 0..<size ) it += block(i)
}
}
} }
/* Print this exception and its stack trace to standard output. */ /* Print this exception and its stack trace to standard output. */
@ -587,7 +595,7 @@ class LaunchPool(maxWorkers, maxQueueSize = Channel.UNLIMITED) {
mu.withLock { mu.withLock {
if (isClosed) throw IllegalStateException("LaunchPool is closed") if (isClosed) throw IllegalStateException("LaunchPool is closed")
} }
val d = CompletableDeferred() val d = CompletableDeferred()
val wrapper = { val wrapper = {
try { d.complete(lambda()) } try { d.complete(lambda()) }
catch(e) { d.completeExceptionally(e) } catch(e) { d.completeExceptionally(e) }