Compare commits
No commits in common. "0ec0ed96ee85acf1e5de10d3b42c67418b6594e8" and "cf791638029b75f7027dce382bd6e8e82f05d0a7" have entirely different histories.
0ec0ed96ee
...
cf79163802
@ -6,12 +6,6 @@ Is a [Iterable] with known `size`, a finite [Iterable]:
|
|||||||
val size
|
val size
|
||||||
}
|
}
|
||||||
|
|
||||||
| name | description |
|
|
||||||
|------------------------|------------------------------------------------------|
|
|
||||||
|
|
||||||
(1)
|
|
||||||
: `comparator(a,b)` should return -1 if `a < b`, +1 if `a > b` or zero.
|
|
||||||
|
|
||||||
See [List], [Set] and [Iterable]
|
See [List], [Set] and [Iterable]
|
||||||
|
|
||||||
[Iterable]: Iterable.md
|
[Iterable]: Iterable.md
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
# Iterable interface
|
# Iterable interface
|
||||||
|
|
||||||
The interface for anything that can be iterated, e.g. finite or infinite ordered set of data that can be accessed
|
The interface for anything that can be iterated, e.g. finite or infinite ordered set of data that can be accessed sequentially. Almost any data container in `Lyng` implements it: `List`, `Set`, `Buffer`, `RingBuffer`, `BitBuffer`, `Range` and many others are `Iterable`, also `Collection` and `Array` interfaces inherit it.
|
||||||
sequentially. Almost any data container in `Lyng` implements it: `List`, `Set`, `Buffer`, `RingBuffer`, `BitBuffer`,
|
|
||||||
`Range` and many others are `Iterable`, also `Collection` and `Array` interfaces inherit it.
|
|
||||||
|
|
||||||
`Map` and `String` have `Iterable` members to access its contents too.
|
`Map` and `String` have `Iterable` members to access its contents too.
|
||||||
|
|
||||||
Please see also [Collection] interface: many iterables are also collections, and it adds important features.
|
|
||||||
|
|
||||||
## Definition:
|
## Definition:
|
||||||
|
|
||||||
Iterable is a class that provides function that creates _the iterator_:
|
Iterable is a class that provides function that creates _the iterator_:
|
||||||
@ -27,8 +23,7 @@ Iterator itself is a simple interface that should provide only to method:
|
|||||||
|
|
||||||
Just remember at this stage typed declarations are not yet supported.
|
Just remember at this stage typed declarations are not yet supported.
|
||||||
|
|
||||||
Having `Iterable` in base classes allows to use it in for loop. Also, each `Iterable` has some utility functions
|
Having `Iterable` in base classes allows to use it in for loop. Also, each `Iterable` has some utility functions available, for example
|
||||||
available, for example
|
|
||||||
|
|
||||||
val r = 1..10 // Range is Iterable!
|
val r = 1..10 // Range is Iterable!
|
||||||
assertEquals( [9,10], r.takeLast(2).toList() )
|
assertEquals( [9,10], r.takeLast(2).toList() )
|
||||||
@ -39,8 +34,7 @@ available, for example
|
|||||||
|
|
||||||
## joinToString
|
## joinToString
|
||||||
|
|
||||||
This methods convert any iterable to a string joining string representation of each element, optionally transforming it
|
This methods convert any iterable to a string joining string representation of each element, optionally transforming it and joining using specified suffix.
|
||||||
and joining using specified suffix.
|
|
||||||
|
|
||||||
Iterable.joinToString(suffux=' ', transform=null)
|
Iterable.joinToString(suffux=' ', transform=null)
|
||||||
|
|
||||||
@ -55,23 +49,11 @@ Here is the sample:
|
|||||||
assertEquals( (1..3).joinToString { it * 10 }, "10 20 30")
|
assertEquals( (1..3).joinToString { it * 10 }, "10 20 30")
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
## `sum` and `sumBy`
|
|
||||||
|
|
||||||
These, again, does the thing:
|
|
||||||
|
|
||||||
assertEquals( 6, [1,2,3].sum() )
|
|
||||||
assertEquals( 12, [1,2,3].sumOf { it*2 } )
|
|
||||||
|
|
||||||
// sum of empty collections is null:
|
|
||||||
assertEquals( null, [].sum() )
|
|
||||||
assertEquals( null, [].sumOf { 2*it } )
|
|
||||||
|
|
||||||
>>> void
|
|
||||||
|
|
||||||
## Instance methods:
|
## Instance methods:
|
||||||
|
|
||||||
|
|
||||||
| fun/method | description |
|
| fun/method | description |
|
||||||
|------------------------|---------------------------------------------------------------------------------|
|
|-------------------|---------------------------------------------------------------------------|
|
||||||
| toList() | create a list from iterable |
|
| toList() | create a list from iterable |
|
||||||
| toSet() | create a set from iterable |
|
| toSet() | create a set from iterable |
|
||||||
| contains(i) | check that iterable contains `i` |
|
| contains(i) | check that iterable contains `i` |
|
||||||
@ -88,23 +70,13 @@ These, again, does the thing:
|
|||||||
| taleLast(n) | return [Iterable] of up to n last elements |
|
| taleLast(n) | return [Iterable] of up to n last elements |
|
||||||
| drop(n) | return new [Iterable] without first n elements |
|
| drop(n) | return new [Iterable] without first n elements |
|
||||||
| dropLast(n) | return new [Iterable] without last n elements |
|
| dropLast(n) | return new [Iterable] without last n elements |
|
||||||
| sum() | return sum of the collection applying `+` to its elements (3) |
|
|
||||||
| sumOf(predicate) | sum of the modified collection items (3) |
|
|
||||||
| sorted() | return [List] with collection items sorted naturally |
|
|
||||||
| sortedWith(comparator) | sort using a comparator that compares elements (1) |
|
|
||||||
| sortedBy(predicate) | sort by comparing results of the predicate function |
|
|
||||||
| joinToString(s,t) | convert iterable to string, see (2) |
|
| joinToString(s,t) | convert iterable to string, see (2) |
|
||||||
| reversed() | create a list containing items from this in reverse order |
|
|
||||||
|
|
||||||
(1)
|
(1)
|
||||||
: throws `NoSuchElementException` if there is no such element
|
: throws `NoSuchElementException` if there is no such element
|
||||||
|
|
||||||
(2)
|
(2)
|
||||||
: `joinToString(suffix=" ",transform=null)`: suffix is inserted between items if there are more than one, trasnfom is
|
: `joinToString(suffix=" ",transform=null)`: suffix is inserted between items if there are more than one, trasnfom is optional function applied to each item that must return result string for an item, otherwise `item.toString()` is used.
|
||||||
optional function applied to each item that must return result string for an item, otherwise `item.toString()` is used.
|
|
||||||
|
|
||||||
(3)
|
|
||||||
: sum of empty collection is `null`
|
|
||||||
|
|
||||||
fun Iterable.toList(): List
|
fun Iterable.toList(): List
|
||||||
fun Iterable.toSet(): Set
|
fun Iterable.toSet(): Set
|
||||||
@ -115,6 +87,7 @@ optional function applied to each item that must return result string for an ite
|
|||||||
fun Iterable.map(block: (Any?)->Void ): List
|
fun Iterable.map(block: (Any?)->Void ): List
|
||||||
fun Iterable.associateBy( keyMaker: (Any?)->Any): Map
|
fun Iterable.associateBy( keyMaker: (Any?)->Any): Map
|
||||||
|
|
||||||
|
|
||||||
## Abstract methods:
|
## Abstract methods:
|
||||||
|
|
||||||
fun iterator(): Iterator
|
fun iterator(): Iterator
|
||||||
@ -129,12 +102,7 @@ Creates a list by iterating to the end. So, the Iterator should be finite to be
|
|||||||
|
|
||||||
- [List], [Range], [Buffer](Buffer.md), [BitBuffer], [Buffer], [Set], [RingBuffer]
|
- [List], [Range], [Buffer](Buffer.md), [BitBuffer], [Buffer], [Set], [RingBuffer]
|
||||||
|
|
||||||
[Collection]: Collection.md
|
|
||||||
|
|
||||||
[List]: List.md
|
[List]: List.md
|
||||||
|
|
||||||
[Range]: Range.md
|
[Range]: Range.md
|
||||||
|
|
||||||
[Set]: Set.md
|
[Set]: Set.md
|
||||||
|
|
||||||
[RingBuffer]: RingBuffer.md
|
[RingBuffer]: RingBuffer.md
|
38
docs/List.md
38
docs/List.md
@ -92,29 +92,10 @@ Open end ranges remove head and tail elements:
|
|||||||
assert( [1, 2, 3] !== [1, 2, 3])
|
assert( [1, 2, 3] !== [1, 2, 3])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
## In-place sort
|
|
||||||
|
|
||||||
List could be sorted in place, just like [Collection] provide sorted copies, in a very like way:
|
|
||||||
|
|
||||||
val l1 = [6,3,1,9]
|
|
||||||
l1.sort()
|
|
||||||
assertEquals( [1,3,6,9], l1)
|
|
||||||
|
|
||||||
l1.sortBy { -it }
|
|
||||||
assertEquals( [1,3,6,9].reversed(), l1)
|
|
||||||
|
|
||||||
l1.sort() // 1 3 6 9
|
|
||||||
l1.sortBy { it % 4 }
|
|
||||||
// 1,3,6,9 gives, mod 4:
|
|
||||||
// 1 3 2 1
|
|
||||||
// we hope we got it also stable:
|
|
||||||
assertEquals( [1,9,6,3], l1)
|
|
||||||
>>> void
|
|
||||||
|
|
||||||
## Members
|
## Members
|
||||||
|
|
||||||
| name | meaning | type |
|
| name | meaning | type |
|
||||||
|-------------------------------|----------------------------------------------|-------------|
|
|-------------------------------|---------------------------------------|-------------|
|
||||||
| `size` | current size | Int |
|
| `size` | current size | Int |
|
||||||
| `add(elements...)` | add one or more elements to the end | Any |
|
| `add(elements...)` | add one or more elements to the end | Any |
|
||||||
| `insertAt(index,elements...)` | insert elements at position | Int, Any |
|
| `insertAt(index,elements...)` | insert elements at position | Int, Any |
|
||||||
@ -126,10 +107,7 @@ List could be sorted in place, just like [Collection] provide sorted copies, in
|
|||||||
| `contains(element)` | check the element is in the list (1) | |
|
| `contains(element)` | check the element is in the list (1) | |
|
||||||
| `[index]` | get or set element at index | Int |
|
| `[index]` | get or set element at index | Int |
|
||||||
| `[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) | List or Obj |
|
||||||
| `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 |
|
|
||||||
|
|
||||||
(1)
|
(1)
|
||||||
: optimized implementation that override `Array` one
|
: optimized implementation that override `Array` one
|
||||||
@ -138,16 +116,7 @@ List could be sorted in place, just like [Collection] provide sorted copies, in
|
|||||||
: `+=` append either a single element, or all elements if the List or other Iterable
|
: `+=` append either a single element, or all elements if the List or other Iterable
|
||||||
instance is appended. If you want to append an Iterable object itself, use `add` instead.
|
instance is appended. If you want to append an Iterable object itself, use `add` instead.
|
||||||
|
|
||||||
(3)
|
It inherits from [Iterable] too.
|
||||||
: predicate is called on each element, and the returned values are used to sort in natural
|
|
||||||
order, e.g. is same as `list.sortWith { a,b -> predicate(a) <=> predicate(b) }`
|
|
||||||
|
|
||||||
(4)
|
|
||||||
: comparator callable takes tho arguments and must return: negative value when first is less,
|
|
||||||
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 }
|
|
||||||
|
|
||||||
It inherits from [Iterable] too and thus all iterable methods are applicable to any list.
|
|
||||||
|
|
||||||
## Member inherited from Array
|
## Member inherited from Array
|
||||||
|
|
||||||
@ -165,5 +134,4 @@ It inherits from [Iterable] too and thus all iterable methods are applicable to
|
|||||||
|
|
||||||
|
|
||||||
[Range]: Range.md
|
[Range]: Range.md
|
||||||
|
|
||||||
[Iterable]: Iterable.md
|
[Iterable]: Iterable.md
|
@ -16,15 +16,9 @@ fun naiveCountHappyNumbers() {
|
|||||||
count
|
count
|
||||||
}
|
}
|
||||||
|
|
||||||
import lyng.time
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// After all optimizations it takes ~120ms.
|
// After all optimizations it takes ~120ms.
|
||||||
//
|
//
|
||||||
//for( r in 1..100 ) {
|
val found = naiveCountHappyNumbers()
|
||||||
// val start = Instant.now()
|
println("Found happy numbers: "+found)
|
||||||
val found = naiveCountHappyNumbers()
|
assert( found == 55252 )
|
||||||
// println("Found happy numbers: %d time %s"(found, Instant.now() - start))
|
|
||||||
assert( found == 55252 )
|
|
||||||
// delay(0.01)
|
|
||||||
//}
|
|
@ -765,8 +765,8 @@ thrown.
|
|||||||
Typical builtin types that are containers (e.g. support `contains`):
|
Typical builtin types that are containers (e.g. support `contains`):
|
||||||
|
|
||||||
| class | notes |
|
| class | notes |
|
||||||
|--------------|------------------------------------------------|
|
|------------|------------------------------------------------|
|
||||||
| [Collection] | contains an element (1) |
|
| Collection | contains an element (1) |
|
||||||
| Array | faster maybe that Collection's |
|
| Array | faster maybe that Collection's |
|
||||||
| List | faster than Array's |
|
| List | faster than Array's |
|
||||||
| String | character in string or substring in string (3) |
|
| String | character in string or substring in string (3) |
|
||||||
@ -1362,5 +1362,3 @@ See [math functions](math.md). Other general purpose functions are:
|
|||||||
[parallelism]: parallelism.md
|
[parallelism]: parallelism.md
|
||||||
|
|
||||||
[RingBuffer]: RingBuffer.md
|
[RingBuffer]: RingBuffer.md
|
||||||
|
|
||||||
[Collection]: Collection.md
|
|
@ -21,7 +21,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
|||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
group = "net.sergeych"
|
group = "net.sergeych"
|
||||||
version = "0.8.15-SNAPSHOT"
|
version = "0.8.14-SNAPSHOT"
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -225,7 +225,7 @@ class Compiler(
|
|||||||
// very special case chained calls: call()<NL>.call2 {}.call3()
|
// very special case chained calls: call()<NL>.call2 {}.call3()
|
||||||
Token.Type.NEWLINE -> {
|
Token.Type.NEWLINE -> {
|
||||||
val saved = cc.savePos()
|
val saved = cc.savePos()
|
||||||
if (cc.peekNextNonWhitespace().type == Token.Type.DOT) {
|
if( cc.peekNextNonWhitespace().type == Token.Type.DOT) {
|
||||||
// chained call continue from it
|
// chained call continue from it
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
@ -492,8 +492,7 @@ class Compiler(
|
|||||||
// if it is an open end range, then the end of line could be here that we do not want
|
// if it is an open end range, then the end of line could be here that we do not want
|
||||||
// to skip in parseExpression:
|
// to skip in parseExpression:
|
||||||
val current = cc.current()
|
val current = cc.current()
|
||||||
val right =
|
val right = if( current.type == Token.Type.NEWLINE || current.type == Token.Type.SINLGE_LINE_COMMENT)
|
||||||
if (current.type == Token.Type.NEWLINE || current.type == Token.Type.SINLGE_LINE_COMMENT)
|
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
parseExpression()
|
parseExpression()
|
||||||
@ -1384,13 +1383,7 @@ class Compiler(
|
|||||||
loopIterable(forContext, sourceObj, loopSO, body, elseStatement, label, canBreak)
|
loopIterable(forContext, sourceObj, loopSO, body, elseStatement, label, canBreak)
|
||||||
} else {
|
} else {
|
||||||
val size = runCatching { sourceObj.invokeInstanceMethod(forContext, "size").toInt() }
|
val size = runCatching { sourceObj.invokeInstanceMethod(forContext, "size").toInt() }
|
||||||
.getOrElse {
|
.getOrElse { throw ScriptError(tOp.pos, "object is not enumerable: no size", it) }
|
||||||
throw ScriptError(
|
|
||||||
tOp.pos,
|
|
||||||
"object is not enumerable: no size in $sourceObj",
|
|
||||||
it
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result: Obj = ObjVoid
|
var result: Obj = ObjVoid
|
||||||
var breakCaught = false
|
var breakCaught = false
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
package net.sergeych.lyng.obj
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection is an iterator with `size`
|
* Collection is an iterator with `size`]
|
||||||
*/
|
*/
|
||||||
val ObjCollection = ObjClass("Collection", ObjIterable).apply {
|
val ObjCollection = ObjClass("Collection", ObjIterable).apply {
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
@ -119,6 +119,12 @@ val ObjIterable by lazy {
|
|||||||
ObjList(result)
|
ObjList(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addFn("drop" ) {
|
||||||
|
// var n = requireOnlyArg<ObjInt>().value.toInt()
|
||||||
|
// if( n < 0 ) raiseIllegalArgument("drop($n): should be positive")
|
||||||
|
// val it = callMethod<>()
|
||||||
|
// }
|
||||||
|
|
||||||
addFn("isEmpty") {
|
addFn("isEmpty") {
|
||||||
ObjBool(
|
ObjBool(
|
||||||
thisObj.invokeInstanceMethod(this, "iterator")
|
thisObj.invokeInstanceMethod(this, "iterator")
|
||||||
@ -126,21 +132,5 @@ val ObjIterable by lazy {
|
|||||||
.not()
|
.not()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
addFn("sortedWith") {
|
|
||||||
val list = thisObj.callMethod<ObjList>(this, "toList")
|
|
||||||
val comparator = requireOnlyArg<Statement>()
|
|
||||||
list.quicksort { a, b ->
|
|
||||||
comparator.call(this, a, b).toInt()
|
|
||||||
}
|
|
||||||
list
|
|
||||||
}
|
|
||||||
|
|
||||||
addFn("reversed") {
|
|
||||||
val list = thisObj.callMethod<ObjList>(this, "toList")
|
|
||||||
list.list.reverse()
|
|
||||||
list
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,7 +18,6 @@
|
|||||||
package net.sergeych.lyng.obj
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
import net.sergeych.lyng.Scope
|
import net.sergeych.lyng.Scope
|
||||||
import net.sergeych.lyng.Statement
|
|
||||||
import net.sergeych.lyng.statement
|
import net.sergeych.lyng.statement
|
||||||
import net.sergeych.lynon.LynonDecoder
|
import net.sergeych.lynon.LynonDecoder
|
||||||
import net.sergeych.lynon.LynonEncoder
|
import net.sergeych.lynon.LynonEncoder
|
||||||
@ -128,33 +127,6 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
return list.map { it.toKotlin(scope) }
|
return list.map { it.toKotlin(scope) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun quicksort(compare: suspend (Obj, Obj) -> Int) = quicksort(compare, 0, list.size - 1)
|
|
||||||
|
|
||||||
suspend fun quicksort(compare: suspend (Obj, Obj) -> Int, left: Int, right: Int) {
|
|
||||||
if (left >= right) return
|
|
||||||
var i = left
|
|
||||||
var j = right
|
|
||||||
val pivot = list[left]
|
|
||||||
while (i < j) {
|
|
||||||
// Сдвигаем j влево, пока элемент меньше pivot
|
|
||||||
while (i < j && compare(list[j], pivot) >= 0) {
|
|
||||||
j--
|
|
||||||
}
|
|
||||||
// Сдвигаем i вправо, пока элемент больше pivot
|
|
||||||
while (i < j && compare(list[i], pivot) <= 0) {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if (i < j) {
|
|
||||||
list.swap(i, j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// После завершения i == j, ставим pivot на своё место
|
|
||||||
list.swap(left, i)
|
|
||||||
// Рекурсивно сортируем левую и правую части
|
|
||||||
quicksort(compare, left, i - 1)
|
|
||||||
quicksort(compare, i + 1, right)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
// check?
|
// check?
|
||||||
return list.hashCode()
|
return list.hashCode()
|
||||||
@ -263,23 +235,8 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
addFn("sortWith") {
|
|
||||||
val comparator = requireOnlyArg<Statement>()
|
|
||||||
thisAs<ObjList>().quicksort { a, b -> comparator.call(this, a, b).toInt() }
|
|
||||||
ObjVoid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Расширение MutableList для удобного обмена элементами
|
|
||||||
fun <T>MutableList<T>.swap(i: Int, j: Int) {
|
|
||||||
if (i in indices && j in indices) {
|
|
||||||
val temp = this[i]
|
|
||||||
this[i] = this[j]
|
|
||||||
this[j] = temp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,8 +77,9 @@ fun Iterable.dropLast(n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun Iterable.takeLast(n) {
|
fun Iterable.takeLast(n) {
|
||||||
|
val list = this
|
||||||
val buffer = RingBuffer(n)
|
val buffer = RingBuffer(n)
|
||||||
for( item in this ) buffer += item
|
for( item in list ) buffer += item
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,46 +104,10 @@ fun Iterable.all(predicate): Bool {
|
|||||||
!any { !predicate(it) }
|
!any { !predicate(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Iterable.sum() {
|
|
||||||
val i = iterator()
|
|
||||||
if( i.hasNext() ) {
|
|
||||||
var result = i.next()
|
|
||||||
while( i.hasNext() ) result += i.next()
|
|
||||||
result
|
|
||||||
}
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Iterable.sumOf(f) {
|
|
||||||
val i = iterator()
|
|
||||||
if( i.hasNext() ) {
|
|
||||||
var result = f(i.next())
|
|
||||||
while( i.hasNext() ) result += f(i.next())
|
|
||||||
result
|
|
||||||
}
|
|
||||||
else null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Iterable.sorted() {
|
|
||||||
sortedWith { a, b -> a <=> b }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Iterable.sortedBy(predicate) {
|
|
||||||
sortedWith { a, b -> predicate(a) <=> predicate(b) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List.toString() {
|
fun List.toString() {
|
||||||
"[" + joinToString(",") + "]"
|
"[" + joinToString(",") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List.sortBy(predicate) {
|
|
||||||
sortWith { a, b -> predicate(a) <=> predicate(b) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun List.sort() {
|
|
||||||
sortWith { a, b -> a <=> b }
|
|
||||||
}
|
|
||||||
|
|
||||||
class StackTraceEntry(
|
class StackTraceEntry(
|
||||||
val sourceName: String,
|
val sourceName: String,
|
||||||
val line: Int,
|
val line: Int,
|
||||||
@ -161,6 +126,5 @@ fun Exception.printStackTrace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
|
@ -3095,12 +3095,10 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOverridenListToString() = runTest {
|
fun testOverridenListToString() = runTest {
|
||||||
eval(
|
eval("""
|
||||||
"""
|
|
||||||
val x = [1,2,3]
|
val x = [1,2,3]
|
||||||
assertEquals( "[1,2,3]", x.toString() )
|
assertEquals( "[1,2,3]", x.toString() )
|
||||||
""".trimIndent()
|
""".trimIndent())
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -3125,93 +3123,9 @@ class ScriptTest {
|
|||||||
println(e.toString())
|
println(e.toString())
|
||||||
println("-------------------- dee")
|
println("-------------------- dee")
|
||||||
println(decoded.toString())
|
println(decoded.toString())
|
||||||
assertEquals( e.toString(), decoded.toString() )
|
// assertEquals( e.toString(), decoded.toString() )
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testThisInClosure() = runTest {
|
|
||||||
eval(
|
|
||||||
"""
|
|
||||||
fun Iterable.sum2by(f) {
|
|
||||||
var acc = null
|
|
||||||
for( x in this ) {
|
|
||||||
println(x)
|
|
||||||
println(f(x))
|
|
||||||
acc = acc?.let { acc + f(x) } ?: f(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class T(val coll, val factor) {
|
|
||||||
fun sum() {
|
|
||||||
// here we use ths::T and it must be available:
|
|
||||||
coll.sum2by { it * factor }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEquals(60, T([1,2,3], 10).sum())
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testThisInFlowClosure() = runTest {
|
|
||||||
eval(
|
|
||||||
"""
|
|
||||||
class T(val coll, val factor) {
|
|
||||||
fun seq() {
|
|
||||||
flow {
|
|
||||||
for( x in coll ) {
|
|
||||||
emit(x*factor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEquals([10,20,30], T([1,2,3], 10).seq().toList())
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSum() = runTest {
|
|
||||||
eval(
|
|
||||||
"""
|
|
||||||
assertEquals(1, [1].sum())
|
|
||||||
assertEquals(null, [].sum())
|
|
||||||
assertEquals(6, [1,2,3].sum())
|
|
||||||
assertEquals(30, [3].sumOf { it * 10 })
|
|
||||||
assertEquals(null, [].sumOf { it * 10 })
|
|
||||||
assertEquals(60, [1,2,3].sumOf { it * 10 })
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSort() = runTest {
|
|
||||||
eval("""
|
|
||||||
val coll = [5,4,1,7]
|
|
||||||
assertEquals( [1,4,5,7], coll.sortedWith { a,b -> a <=> b })
|
|
||||||
assertEquals( [1,4,5,7], coll.sorted())
|
|
||||||
assertEquals( [7,5,4,1], coll.sortedBy { -it })
|
|
||||||
assertEquals( [1,4,5,7], coll.sortedBy { -it }.reversed())
|
|
||||||
""".trimIndent()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testListSortInPlace() = runTest {
|
|
||||||
eval("""
|
|
||||||
val l1 = [6,3,1,9]
|
|
||||||
l1.sort()
|
|
||||||
assertEquals( [1,3,6,9], l1)
|
|
||||||
l1.sortBy { -it }
|
|
||||||
assertEquals( [1,3,6,9].reversed(), l1)
|
|
||||||
l1.sort()
|
|
||||||
l1.sortBy { it % 4 }
|
|
||||||
// 1,3,6,9
|
|
||||||
// 1 3 2 1
|
|
||||||
// we hope we got it also stable:
|
|
||||||
assertEquals( [1,9,6,3], l1)
|
|
||||||
""")
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user