added static List.fill(size) { ... }
This commit is contained in:
parent
f1003f5b95
commit
a7ab0d3905
11
docs/List.md
11
docs/List.md
@ -45,6 +45,16 @@ You can concatenate lists or iterable objects:
|
||||
assert( [4,5] + (1..3) == [4, 5, 1, 2, 3])
|
||||
>>> void
|
||||
|
||||
## Constructing lists
|
||||
|
||||
Besides literals, you can build a list by size using `List.fill`:
|
||||
|
||||
val squares = List.fill(5) { i -> i * i }
|
||||
assertEquals([0, 1, 4, 9, 16], squares)
|
||||
>>> void
|
||||
|
||||
`List.fill(size) { ... }` calls the block once for each index from `0` to `size - 1` and returns a new mutable list.
|
||||
|
||||
## Appending
|
||||
|
||||
To append to lists, use `+=` with elements, lists and any [Iterable] instances, but beware it will
|
||||
@ -164,6 +174,7 @@ List could be sorted in place, just like [Collection] provide sorted copies, in
|
||||
| `[index]` | get or set element at index | Int |
|
||||
| `[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..<size` | Int, Callable |
|
||||
| `sort()` | in-place sort, natural order | void |
|
||||
| `sortBy(predicate)` | in-place sort bu `predicate` call result (3) | void |
|
||||
| `sortWith(comparator)` | in-place sort using `comarator` function (4) | void |
|
||||
|
||||
@ -1020,6 +1020,14 @@ For example, we want to create an extension method that would test if a value ca
|
||||
assert( ! "5.2".isInteger() )
|
||||
>>> void
|
||||
|
||||
Extension methods normally act like instance members. If declared as `static`, they are called on the type object itself:
|
||||
|
||||
```lyng
|
||||
static fun List<T>.fill(size: Int, block: (Int)->T): List<T> { ... }
|
||||
|
||||
val tens = List.fill(5) { it * 10 }
|
||||
```
|
||||
|
||||
## Extension properties
|
||||
|
||||
Just like methods, you can extend existing classes with properties. These can be defined using simple initialization (for `val` only) or with custom accessors.
|
||||
|
||||
@ -116,6 +116,7 @@ Primary sources used: `lynglib/src/commonMain/kotlin/net/sergeych/lyng/{Parser,T
|
||||
- shorthand: `fun f(x) = expr`.
|
||||
- generics: `fun f<T>(x: T): T`.
|
||||
- extension functions: `fun Type.name(...) { ... }`.
|
||||
- static extension functions are callable on the type object: `static fun List<T>.fill(...)` -> `List.fill(...)`.
|
||||
- delegated callable: `fun f(...) by delegate`.
|
||||
- Type aliases:
|
||||
- `type Name = TypeExpr`
|
||||
|
||||
@ -46,7 +46,8 @@ Sources: `lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt`, `lynglib/s
|
||||
- Iteration/filtering: `forEach`, `filter`, `filterFlow`, `filterNotNull`, `filterFlowNotNull`, `drop`, `dropLast`, `takeLast`.
|
||||
- Search/predicates: `findFirst`, `findFirstOrNull`, `any`, `all`, `count`, `first`, `last`.
|
||||
- Mapping/aggregation: `map`, `flatMap`, `flatten`, `sum`, `sumOf`, `minOf`, `maxOf`.
|
||||
- Ordering: `sorted`, `sortedBy`, `shuffled`, `List.sort`, `List.sortBy`.
|
||||
- Ordering and list building: `sorted`, `sortedBy`, `shuffled`, `List.sort`, `List.sortBy`, `List.fill`.
|
||||
- `List.fill(size) { index -> ... }` constructs a new `List<T>` by evaluating the block once per index from `0` to `size - 1`.
|
||||
- String helper: `joinToString`, `String.re`.
|
||||
|
||||
### 4.3 Delegation helpers
|
||||
|
||||
@ -811,6 +811,12 @@ Lyng has built-in mutable array class `List` with simple literals:
|
||||
many collection based methods are implemented there.
|
||||
For immutable list values, use `list.toImmutable()` and [ImmutableList].
|
||||
|
||||
To construct a list programmatically, use the static helper `List.fill`:
|
||||
|
||||
val tens = List.fill(5) { index -> index * 10 }
|
||||
assertEquals([0, 10, 20, 30, 40], tens)
|
||||
>>> void
|
||||
|
||||
Lists can contain any type of objects, lists too:
|
||||
|
||||
val list = [1, [2, 3], 4]
|
||||
|
||||
@ -4359,6 +4359,7 @@ class Compiler(
|
||||
is ListLiteralRef -> inferListLiteralTypeDecl(ref)
|
||||
is MapLiteralRef -> inferMapLiteralTypeDecl(ref)
|
||||
is ConstRef -> inferTypeDeclFromConst(ref.constValue)
|
||||
is RangeRef -> TypeDecl.Simple("Range", false)
|
||||
is CallRef -> {
|
||||
val targetDecl = resolveReceiverTypeDecl(ref.target) ?: seedTypeDeclFromRef(ref.target)
|
||||
val targetName = when (val target = ref.target) {
|
||||
@ -4394,6 +4395,7 @@ class Compiler(
|
||||
is ObjString -> TypeDecl.Simple("String", false)
|
||||
is ObjBool -> TypeDecl.Simple("Bool", false)
|
||||
is ObjChar -> TypeDecl.Simple("Char", false)
|
||||
is ObjRange -> TypeDecl.Simple("Range", false)
|
||||
is ObjNull -> TypeDecl.TypeNullableAny
|
||||
is ObjList -> TypeDecl.Generic("List", listOf(TypeDecl.TypeAny), false)
|
||||
is ObjMap -> TypeDecl.Generic("Map", listOf(TypeDecl.TypeAny, TypeDecl.TypeAny), false)
|
||||
@ -8714,7 +8716,7 @@ class Compiler(
|
||||
startPos = start
|
||||
)
|
||||
val declaredFn = FunctionDeclStatement(spec)
|
||||
if (isStatic) {
|
||||
if (isStatic && parentIsClassBody) {
|
||||
currentInitScope += declaredFn
|
||||
NopStatement
|
||||
} else
|
||||
|
||||
@ -169,6 +169,16 @@ internal suspend fun executeFunctionDecl(
|
||||
spec.extTypeName?.let { typeName ->
|
||||
val type = scope[typeName]?.value ?: scope.raiseSymbolNotFound("class $typeName not found")
|
||||
if (type !is ObjClass) scope.raiseClassCastError("$typeName is not the class instance")
|
||||
if (spec.isStatic) {
|
||||
type.createClassField(
|
||||
spec.name,
|
||||
compiledFnBody,
|
||||
isMutable = false,
|
||||
visibility = spec.visibility,
|
||||
pos = spec.startPos,
|
||||
type = ObjRecord.Type.Fun,
|
||||
)
|
||||
} else {
|
||||
scope.addExtension(
|
||||
type,
|
||||
spec.name,
|
||||
@ -181,6 +191,7 @@ internal suspend fun executeFunctionDecl(
|
||||
typeDecl = spec.typeDecl
|
||||
)
|
||||
)
|
||||
}
|
||||
val wrapperName = spec.extensionWrapperName ?: extensionCallableName(typeName, spec.name)
|
||||
val wrapper = ObjExtensionMethodCallable(spec.name, compiledFnBody)
|
||||
scope.addItem(
|
||||
|
||||
@ -4021,6 +4021,14 @@ class ScriptTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListFill() = runTest {
|
||||
eval("""
|
||||
val x = List.fill(5) { it*10 }
|
||||
assertEquals( [0,10,20,30,40], x)
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun binarySearchTest() = runTest {
|
||||
eval(
|
||||
|
||||
@ -422,6 +422,13 @@ fun List<T>.sort(): void {
|
||||
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> {
|
||||
val result = List<T>()
|
||||
for( i in 0..<size ) result += block(i)
|
||||
result
|
||||
}
|
||||
|
||||
/* Print this exception and its stack trace to standard output. */
|
||||
fun Exception.printStackTrace(): void {
|
||||
println(this)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user