fix #26 lists redesigned for ranges, less chaotic and serpentic
This commit is contained in:
parent
19eae213ec
commit
8a4363bd84
65
docs/List.md
65
docs/List.md
@ -20,11 +20,11 @@ indexing is zero-based, as in C/C++/Java/Kotlin, etc.
|
|||||||
list[1]
|
list[1]
|
||||||
>>> 20
|
>>> 20
|
||||||
|
|
||||||
Using negative indexes has a special meaning: _offset from the end of the list_:
|
There is a shortcut for the last:
|
||||||
|
|
||||||
val list = [10, 20, 30]
|
val list = [10, 20, 30]
|
||||||
list[-1]
|
[list.last, list.lastIndex]
|
||||||
>>> 30
|
>>> [30, 2]
|
||||||
|
|
||||||
__Important__ negative indexes works wherever indexes are used, e.g. in insertion and removal methods too.
|
__Important__ negative indexes works wherever indexes are used, e.g. in insertion and removal methods too.
|
||||||
|
|
||||||
@ -38,7 +38,8 @@ You can concatenate lists or iterable objects:
|
|||||||
|
|
||||||
## Appending
|
## Appending
|
||||||
|
|
||||||
To append to lists, use `+=` with elements, lists and any [Iterable] instances, but beware it will concatenate [Iterable] objects instead of appending them. To append [Iterable] instance itself, use `list.add`:
|
To append to lists, use `+=` with elements, lists and any [Iterable] instances, but beware it will
|
||||||
|
concatenate [Iterable] objects instead of appending them. To append [Iterable] instance itself, use `list.add`:
|
||||||
|
|
||||||
var list = [1, 2]
|
var list = [1, 2]
|
||||||
val other = [3, 4]
|
val other = [3, 4]
|
||||||
@ -57,7 +58,28 @@ To append to lists, use `+=` with elements, lists and any [Iterable] instances,
|
|||||||
|
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
|
## Removing elements
|
||||||
|
|
||||||
|
List is mutable, so it is possible to remove its contents. To remove a single element
|
||||||
|
by index use:
|
||||||
|
|
||||||
|
assertEquals( [1,2,3].removeAt(1), [1,3] )
|
||||||
|
assertEquals( [1,2,3].removeAt(0), [2,3] )
|
||||||
|
assertEquals( [1,2,3].removeLast(), [1,2] )
|
||||||
|
>>> void
|
||||||
|
|
||||||
|
There is a way to remove a range (see [Range] for more on ranges):
|
||||||
|
|
||||||
|
assertEquals( [1, 4], [1,2,3,4].removeRange(1..2))
|
||||||
|
assertEquals( [1, 4], [1,2,3,4].removeRange(1..<3))
|
||||||
|
>>> void
|
||||||
|
|
||||||
|
Open end ranges remove head and tail elements:
|
||||||
|
|
||||||
|
assertEquals( [3, 4, 5], [1,2,3,4,5].removeRange(..1))
|
||||||
|
assertEquals( [3, 4, 5], [1,2,3,4,5].removeRange(..<2))
|
||||||
|
assertEquals( [1, 2], [1,2,3,4,5].removeRange( (2..) ))
|
||||||
|
>>> void
|
||||||
|
|
||||||
## Comparisons
|
## Comparisons
|
||||||
|
|
||||||
@ -73,18 +95,43 @@ To append to lists, use `+=` with elements, lists and any [Iterable] instances,
|
|||||||
## 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 |
|
||||||
| `addAt(index,elements...)` | insert elements at position | Int, Any |
|
| `insertAt(index,elements...)` | insert elements at position | Int, Any |
|
||||||
| `removeAt(index)` | remove element at position | Int |
|
| `removeAt(index)` | remove element at position | Int |
|
||||||
| `removeRangeInclusive(start,end)` | remove range, inclusive (1) | Int, Int |
|
| `remove(from,toNonInclusive)` | remove range from (incl) to (nonincl) | Int, Int |
|
||||||
| | | |
|
| `remove(Range)` | remove range | Range |
|
||||||
|
| `removeLast()` | remove last element | |
|
||||||
|
| `removeLast(n)` | remove n last elements | Int |
|
||||||
|
| `contains(element)` | check the element is in the list (1) | |
|
||||||
|
| `[index]` | get or set element at index | Int |
|
||||||
|
| `[Range]` | get slice of the array (copy) | Range |
|
||||||
|
| `+=` | append element(s) | List or Obj |
|
||||||
|
|
||||||
(1)
|
(1)
|
||||||
: end-inclisiveness allows to use negative indexes to, for exampe, remove several last elements, like `list.removeRangeInclusive(-2, -1)` will remove two last elements.
|
: optimized implementation that override `Array` one
|
||||||
|
|
||||||
|
(2)
|
||||||
|
: `+=` 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.
|
||||||
|
|
||||||
|
## Member inherited from Array
|
||||||
|
|
||||||
|
| name | meaning | type |
|
||||||
|
|------------------|--------------------------------|-------|
|
||||||
|
| `last` | last element (throws if empty) | |
|
||||||
|
| `lastOrNull` | last element or null | |
|
||||||
|
| `lastIndex` | | Int |
|
||||||
|
| `indices` | range of indexes | Range |
|
||||||
|
| `contains(item)` | test that item is in the list | |
|
||||||
|
|
||||||
|
(1)
|
||||||
|
: end-inclisiveness allows to use negative indexes to, for exampe, remove several last elements, like
|
||||||
|
`list.removeRangeInclusive(-2, -1)` will remove two last elements.
|
||||||
|
|
||||||
# Notes
|
# Notes
|
||||||
|
|
||||||
Could be rewritten using array as a class but List as the interface
|
Could be rewritten using array as a class but List as the interface
|
||||||
|
|
||||||
|
[Range]: Range.md
|
@ -514,62 +514,73 @@ To add elements to the list:
|
|||||||
assert( x == [1, 2, 3, "the", "end"])
|
assert( x == [1, 2, 3, "the", "end"])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
Self-modifying concatenation by `+=` also works:
|
Self-modifying concatenation by `+=` also works (also with single elements):
|
||||||
|
|
||||||
val x = [1, 2]
|
val x = [1, 2]
|
||||||
x += [3, 4]
|
x += [3, 4]
|
||||||
assert( x == [1, 2, 3, 4])
|
x += 5
|
||||||
|
assert( x == [1, 2, 3, 4, 5])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
You can insert elements at any position using `addAt`:
|
You can insert elements at any position using `insertAt`:
|
||||||
|
|
||||||
val x = [1,2,3]
|
val x = [1,2,3]
|
||||||
x.addAt(1, "foo", "bar")
|
x.insertAt(1, "foo", "bar")
|
||||||
assert( x == [1, "foo", "bar", 2, 3])
|
assert( x == [1, "foo", "bar", 2, 3])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
Using splat arguments can simplify inserting list in list:
|
Using splat arguments can simplify inserting list in list:
|
||||||
|
|
||||||
val x = [1, 2, 3]
|
val x = [1, 2, 3]
|
||||||
x.addAt( 1, ...[0,100,0])
|
x.insertAt( 1, ...[0,100,0])
|
||||||
x
|
x
|
||||||
>>> [1, 0, 100, 0, 2, 3]
|
>>> [1, 0, 100, 0, 2, 3]
|
||||||
|
|
||||||
Using negative indexes can insert elements as offset from the end, for example:
|
|
||||||
|
|
||||||
val x = [1,2,3]
|
|
||||||
x.addAt(-1, 10)
|
|
||||||
x
|
|
||||||
>>> [1, 2, 10, 3]
|
|
||||||
|
|
||||||
Note that to add to the end you still need to use `add` or positive index of the after-last element:
|
Note that to add to the end you still need to use `add` or positive index of the after-last element:
|
||||||
|
|
||||||
val x = [1,2,3]
|
val x = [1,2,3]
|
||||||
x.addAt(3, 10)
|
x.insertAt(3, 10)
|
||||||
x
|
x
|
||||||
>>> [1, 2, 3, 10]
|
>>> [1, 2, 3, 10]
|
||||||
|
|
||||||
|
but it is much simpler, and we recommend to use '+='
|
||||||
|
|
||||||
|
val x = [1,2,3]
|
||||||
|
x += 10
|
||||||
|
>>> [1, 2, 3, 10]
|
||||||
|
|
||||||
## Removing list items
|
## Removing list items
|
||||||
|
|
||||||
val x = [1, 2, 3, 4, 5]
|
val x = [1, 2, 3, 4, 5]
|
||||||
x.removeAt(2)
|
x.removeAt(2)
|
||||||
assert( x == [1, 2, 4, 5])
|
assert( x == [1, 2, 4, 5])
|
||||||
// or remove range (start inclusive, end exclusive):
|
// or remove range (start inclusive, end exclusive):
|
||||||
x.removeRangeInclusive(1,2)
|
x.removeRange(1..2)
|
||||||
assert( x == [1, 5])
|
assert( x == [1, 5])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
Again, you can use negative indexes. For example, removing last elements like:
|
There is a shortcut to remove the last elements:
|
||||||
|
|
||||||
val x = [1, 2, 3, 4, 5]
|
val x = [1, 2, 3, 4, 5]
|
||||||
|
|
||||||
// remove last:
|
// remove last:
|
||||||
x.removeAt(-1)
|
x.removeLast()
|
||||||
assert( x == [1, 2, 3, 4])
|
assert( x == [1, 2, 3, 4])
|
||||||
|
|
||||||
// remove 2 last:
|
// remove 2 last:
|
||||||
x.removeRangeInclusive(-2,-1)
|
x.removeLast(2)
|
||||||
assert( x == [1, 2])
|
assertEquals( [1, 2], x)
|
||||||
|
>>> void
|
||||||
|
|
||||||
|
You can get ranges to extract a portion from a list:
|
||||||
|
|
||||||
|
val list = [1, 2, 3, 4, 5]
|
||||||
|
assertEquals( [1,2,3], list[..2])
|
||||||
|
assertEquals( [1,2,], list[..<2])
|
||||||
|
assertEquals( [4,5], list[3..])
|
||||||
|
assertEquals( [2,3], list[1..2])
|
||||||
|
assertEquals( [2,3], list[1..<3])
|
||||||
>>> void
|
>>> void
|
||||||
|
|
||||||
# Flow control operators
|
# Flow control operators
|
||||||
|
@ -365,7 +365,7 @@ class Compiler(
|
|||||||
} ?: parseLambdaExpression(cc)
|
} ?: parseLambdaExpression(cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
Token.Type.RBRACKET -> {
|
Token.Type.RBRACKET, Token.Type.RPAREN -> {
|
||||||
cc.previous()
|
cc.previous()
|
||||||
return operand
|
return operand
|
||||||
}
|
}
|
||||||
|
@ -161,13 +161,26 @@ val ObjArray by lazy {
|
|||||||
|
|
||||||
addFn("contains", isOpen = true) {
|
addFn("contains", isOpen = true) {
|
||||||
val obj = args.firstAndOnly()
|
val obj = args.firstAndOnly()
|
||||||
for( i in 0..< thisObj.invokeInstanceMethod(this, "size").toInt()) {
|
for (i in 0..<thisObj.invokeInstanceMethod(this, "size").toInt()) {
|
||||||
if( thisObj.getAt(this, ObjInt(i.toLong())).compareTo(this, obj) == 0 ) return@addFn ObjTrue
|
if (thisObj.getAt(this, ObjInt(i.toLong())).compareTo(this, obj) == 0) return@addFn ObjTrue
|
||||||
}
|
}
|
||||||
ObjFalse
|
ObjFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
addFn("isample") { "ok".toObj() }
|
addFn("last") {
|
||||||
|
thisObj.invokeInstanceMethod(
|
||||||
|
this,
|
||||||
|
"getAt",
|
||||||
|
(thisObj.invokeInstanceMethod(this, "size").toInt() - 1).toObj()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
addFn("lastIndex") { (thisObj.invokeInstanceMethod(this, "size").toInt() - 1).toObj() }
|
||||||
|
|
||||||
|
addFn("indices") {
|
||||||
|
ObjRange(0.toObj(), thisObj.invokeInstanceMethod(this, "size"), false)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,20 +11,48 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
list.joinToString(separator = ", ") { it.inspect() }
|
list.joinToString(separator = ", ") { it.inspect() }
|
||||||
}]"
|
}]"
|
||||||
|
|
||||||
fun normalize(context: Context, index: Int, allowsEndInclusive: Boolean = false): Int {
|
override suspend fun getAt(context: Context, index: Obj): Obj {
|
||||||
val i = if (index < 0) list.size + index else index
|
return when (index) {
|
||||||
if (allowsEndInclusive && i == list.size) return i
|
is ObjInt -> {
|
||||||
if (i !in list.indices) context.raiseError("index $index out of bounds for size ${list.size}")
|
list[index.toInt()]
|
||||||
return i
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAt(context: Context, index: Obj): Obj {
|
is ObjRange -> {
|
||||||
val i = normalize(context, index.toInt())
|
when {
|
||||||
return list[i]
|
index.start is ObjInt && index.end is ObjInt -> {
|
||||||
|
if (index.isEndInclusive)
|
||||||
|
ObjList(list.subList(index.start.toInt(), index.end.toInt() + 1).toMutableList())
|
||||||
|
else
|
||||||
|
ObjList(list.subList(index.start.toInt(), index.end.toInt()).toMutableList())
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenStart && !index.isOpenEnd -> {
|
||||||
|
if (index.isEndInclusive)
|
||||||
|
ObjList(list.subList(0, index.end!!.toInt() + 1).toMutableList())
|
||||||
|
else
|
||||||
|
ObjList(list.subList(0, index.end!!.toInt()).toMutableList())
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenEnd && !index.isOpenStart -> {
|
||||||
|
ObjList(list.subList(index.start!!.toInt(), list.size).toMutableList())
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenStart && index.isOpenEnd -> {
|
||||||
|
ObjList(list.toMutableList())
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
throw RuntimeException("Can't apply range for index: $index")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> context.raiseArgumentError("Illegal index object for a list: ${index.inspect()}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun putAt(context: Context, index: Int, newValue: Obj) {
|
override suspend fun putAt(context: Context, index: Int, newValue: Obj) {
|
||||||
val i = normalize(context, index)
|
val i = index
|
||||||
list[i] = newValue
|
list[i] = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,33 +139,74 @@ class ObjList(val list: MutableList<Obj> = mutableListOf()) : Obj() {
|
|||||||
ObjVoid
|
ObjVoid
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
createField("addAt",
|
addFn("insertAt") {
|
||||||
statement {
|
|
||||||
if (args.size < 2) raiseError("addAt takes 2+ arguments")
|
if (args.size < 2) raiseError("addAt takes 2+ arguments")
|
||||||
val l = thisAs<ObjList>()
|
val l = thisAs<ObjList>()
|
||||||
var index = l.normalize(
|
var index = requiredArg<ObjInt>(0).value.toInt()
|
||||||
this, requiredArg<ObjInt>(0).value.toInt(),
|
|
||||||
allowsEndInclusive = true
|
|
||||||
)
|
|
||||||
for (i in 1..<args.size) l.list.add(index++, args[i])
|
for (i in 1..<args.size) l.list.add(index++, args[i])
|
||||||
ObjVoid
|
ObjVoid
|
||||||
}
|
}
|
||||||
)
|
|
||||||
addFn("removeAt") {
|
addFn("removeAt") {
|
||||||
val self = thisAs<ObjList>()
|
val self = thisAs<ObjList>()
|
||||||
val start = self.normalize(this, requiredArg<ObjInt>(0).value.toInt())
|
val start = requiredArg<ObjInt>(0).value.toInt()
|
||||||
if (args.size == 2) {
|
if (args.size == 2) {
|
||||||
val end = requireOnlyArg<ObjInt>().value.toInt()
|
val end = requireOnlyArg<ObjInt>().value.toInt()
|
||||||
self.list.subList(start, self.normalize(this, end)).clear()
|
self.list.subList(start, end).clear()
|
||||||
} else
|
} else
|
||||||
self.list.removeAt(start)
|
self.list.removeAt(start)
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
addFn("removeRangeInclusive") {
|
|
||||||
|
addFn("removeLast") {
|
||||||
val self = thisAs<ObjList>()
|
val self = thisAs<ObjList>()
|
||||||
val start = self.normalize(this, requiredArg<ObjInt>(0).value.toInt())
|
if (args.isNotEmpty()) {
|
||||||
val end = self.normalize(this, requiredArg<ObjInt>(1).value.toInt()) + 1
|
val count = requireOnlyArg<ObjInt>().value.toInt()
|
||||||
|
val size = self.list.size
|
||||||
|
if (count >= size) self.list.clear()
|
||||||
|
else self.list.subList(size - count, size).clear()
|
||||||
|
} else self.list.removeLast()
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
addFn("removeRange") {
|
||||||
|
val self = thisAs<ObjList>()
|
||||||
|
val list = self.list
|
||||||
|
val range = requiredArg<Obj>(0)
|
||||||
|
if (range is ObjRange) {
|
||||||
|
val index = range
|
||||||
|
when {
|
||||||
|
index.start is ObjInt && index.end is ObjInt -> {
|
||||||
|
if (index.isEndInclusive)
|
||||||
|
list.subList(index.start.toInt(), index.end.toInt() + 1)
|
||||||
|
else
|
||||||
|
list.subList(index.start.toInt(), index.end.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenStart && !index.isOpenEnd -> {
|
||||||
|
if (index.isEndInclusive)
|
||||||
|
list.subList(0, index.end!!.toInt() + 1)
|
||||||
|
else
|
||||||
|
list.subList(0, index.end!!.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenEnd && !index.isOpenStart -> {
|
||||||
|
list.subList(index.start!!.toInt(), list.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
index.isOpenStart && index.isOpenEnd -> {
|
||||||
|
list
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
throw RuntimeException("Can't apply range for index: $index")
|
||||||
|
}
|
||||||
|
}.clear()
|
||||||
|
} else {
|
||||||
|
val start = range.toInt()
|
||||||
|
val end = requiredArg<ObjInt>(1).value.toInt() + 1
|
||||||
self.list.subList(start, end).clear()
|
self.list.subList(start, end).clear()
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@ package net.sergeych.lyng
|
|||||||
|
|
||||||
class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Obj() {
|
class ObjRange(val start: Obj?, val end: Obj?, val isEndInclusive: Boolean) : Obj() {
|
||||||
|
|
||||||
|
val isOpenStart by lazy { start == null || start.isNull }
|
||||||
|
val isOpenEnd by lazy { end == null || end.isNull }
|
||||||
|
|
||||||
override val objClass: ObjClass = type
|
override val objClass: ObjClass = type
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
@ -1137,7 +1137,8 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOpenStartRanges() = runTest {
|
fun testOpenStartRanges() = runTest {
|
||||||
eval("""
|
eval(
|
||||||
|
"""
|
||||||
var r = ..5
|
var r = ..5
|
||||||
assert( r::class == Range)
|
assert( r::class == Range)
|
||||||
assert( r.start == null)
|
assert( r.start == null)
|
||||||
@ -1155,17 +1156,20 @@ class ScriptTest {
|
|||||||
assert( (-2..3) in r)
|
assert( (-2..3) in r)
|
||||||
assert( (-2..12) !in r)
|
assert( (-2..12) !in r)
|
||||||
|
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testOpenEndRanges() = runTest {
|
fun testOpenEndRanges() = runTest {
|
||||||
eval("""
|
eval(
|
||||||
|
"""
|
||||||
var r = 5..
|
var r = 5..
|
||||||
assert( r::class == Range)
|
assert( r::class == Range)
|
||||||
assert( r.end == null)
|
assert( r.end == null)
|
||||||
assert( r.start == 5)
|
assert( r.start == 5)
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1226,7 +1230,7 @@ class ScriptTest {
|
|||||||
val list = (1..1024).toList()
|
val list = (1..1024).toList()
|
||||||
assert(list.size == 1024)
|
assert(list.size == 1024)
|
||||||
assert(list[0] == 1)
|
assert(list[0] == 1)
|
||||||
assert(list[-1] == 1024)
|
assert(list.last == 1024)
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
@ -2149,7 +2153,8 @@ class ScriptTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNull1() = runTest {
|
fun testNull1() = runTest {
|
||||||
eval("""
|
eval(
|
||||||
|
"""
|
||||||
var s = null
|
var s = null
|
||||||
assertThrows { s.length }
|
assertThrows { s.length }
|
||||||
assertThrows { s.size() }
|
assertThrows { s.size() }
|
||||||
@ -2164,25 +2169,41 @@ class ScriptTest {
|
|||||||
s = "xx"
|
s = "xx"
|
||||||
assert(s.lower().size == 2)
|
assert(s.lower().size == 2)
|
||||||
assert(s.length == 2)
|
assert(s.length == 2)
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSprintf() = runTest {
|
fun testSprintf() = runTest {
|
||||||
eval("""
|
eval(
|
||||||
|
"""
|
||||||
assertEquals( "123.45", "%3.2f"(123.451678) )
|
assertEquals( "123.45", "%3.2f"(123.451678) )
|
||||||
assertEquals( "123.45: hello", "%3.2f: %s"(123.451678, "hello") )
|
assertEquals( "123.45: hello", "%3.2f: %s"(123.451678, "hello") )
|
||||||
assertEquals( "123.45: true", "%3.2f: %s"(123.451678, true) )
|
assertEquals( "123.45: true", "%3.2f: %s"(123.451678, true) )
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSubstringRangeFailure() = runTest {
|
fun testSubstringRangeFailure() = runTest {
|
||||||
eval("""
|
eval(
|
||||||
|
"""
|
||||||
assertEquals("pult", "catapult"[4..])
|
assertEquals("pult", "catapult"[4..])
|
||||||
assertEquals("cat", "catapult"[..2])
|
assertEquals("cat", "catapult"[..2])
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun passingOpenEndedRangeAsParam() = runTest {
|
||||||
|
eval(
|
||||||
|
"""
|
||||||
|
fun test(r) {
|
||||||
|
assert( r is Range )
|
||||||
|
}
|
||||||
|
test( 1.. )
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user