From 397dcaae92ae862ac5dc9af7f4f01bc53c908659 Mon Sep 17 00:00:00 2001 From: sergeych Date: Sun, 8 Jun 2025 16:58:09 +0400 Subject: [PATCH] splat any Iterable --- docs/declaring_arguments.md | 26 ++++++++++++++++++- .../kotlin/net/sergeych/lyng/Arguments.kt | 14 ++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/docs/declaring_arguments.md b/docs/declaring_arguments.md index 911b44c..b12ecfe 100644 --- a/docs/declaring_arguments.md +++ b/docs/declaring_arguments.md @@ -70,7 +70,31 @@ destructuring arrays when calling functions and lambdas: fun getFirstAndLast(first, args..., last) { [ first, last ] } - getFirstAndLast( ...(1..10).toList() ) + getFirstAndLast( ...(1..10) ) // see "splats" section below >>> [1, 10] +# Splats + +Ellipsis allows to convert argument lists to lists. The inversa algorithm that converts [List], +or whatever implementing [Iterable], is called _splats_. Here is how we use it: + + fun testSplat(data...) { + println(data) + } + val array = [1,2,3] + testSplat("start", ...array, "end") + >>> ["start", 1, 2, 3, "end"] + >>> void + +There could be any number of splats at any positions. You can splat any other [Iterable] type: + + fun testSplat(data...) { + println(data) + } + val range = 1..3 + testSplat("start", ...range, "end") + >>> ["start", 1, 2, 3, "end"] + >>> void + + [tutorial]: tutorial.md diff --git a/library/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt b/library/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt index ee79626..6f804f5 100644 --- a/library/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt +++ b/library/src/commonMain/kotlin/net/sergeych/lyng/Arguments.kt @@ -8,8 +8,18 @@ suspend fun Collection.toArguments(context: Context): Arguments for (x in this) { val value = x.value.execute(context) if (x.isSplat) { - (value as? ObjList) ?: context.raiseClassCastError("expected list of objects for splat argument") - for (subitem in value.list) list.add(Arguments.Info(subitem, x.pos)) + when { + value is ObjList -> { + for (subitem in value.list) list.add(Arguments.Info(subitem, x.pos)) + } + + value.isInstanceOf(ObjIterable) -> { + val i = (value.invokeInstanceMethod(context, "toList") as ObjList).list + i.forEach { list.add(Arguments.Info(it, x.pos)) } + } + + else -> context.raiseClassCastError("expected list of objects for splat argument") + } } else list.add(Arguments.Info(value, x.pos)) }