Hey everybody, Thanks for having me. Can somebody ...
# announcements
j
Hey everybody, Thanks for having me. Can somebody tell me how to resolve this ambiguity without
it.
?
Copy code
kotlin
        val a = "1 2\n3 4".lines().map{CharSequence::split("\\s+".toRegex())}
Copy code
log
Matrix.kt: (10, 59): This syntax is reserved for future use; to call a reference, enclose it in parentheses: (foo::bar)(args)
e: /home/a/github/exercism/kotlin/matrix/src/main/kotlin/Matrix.kt: (10, 54): Overload resolution ambiguity:
public fun CharSequence.split(regex: Pattern, limit: Int = ...): List<String> defined in kotlin.text
public fun CharSequence.split(vararg delimiters: String, ignoreCase: Boolean = ..., limit: Int = ...): List<String> defined in kotlin.text
public fun CharSequence.split(vararg delimiters: Char, ignoreCase: Boolean = ..., limit: Int = ...): List<String> defined in kotlin.text
@InlineOnly public inline fun CharSequence.split(regex: Regex, limit: Int = ...): List<String> defined in kotlin.text
n
is it a method reference or a method call? you can't do both
j
well, I have tried different things
Copy code
val a = "1 2\n3 4".lines().map(CharSequence::split("\\s+".toRegex()))
isn't working either.
And I saw
Copy code
fun scoreWord(word: String): Int {
        if(word.isEmpty()) return 0

        return word
            .map(Character::toUpperCase)
            .map { scores.getOrDefault(it, 0) }
            .reduce(Int::plus)
    }
n
I mean `Class::method(`is never going to work
j
Sorry, I am new to this. isn't
Character::toUpperCase
Class::method
?
n
yes, but there's no attempted method invocation there -- that
(
I added isn't a typo
btw
.map(Character::toUpperCase)
is exactly equivalent to
.map { it.toUpperCase() }
or, more verbosely,
.map { c: Character -> c.toUpperCase() }
I don't think there's any way around doing this:
Copy code
val spaces = "\\s+".toRegex()
val a = "blah".lines().map { it.split(spaces) }
j
right, right, I was looking to the equivalent thing to
map{it.split("\\s+".toRegex())}
.
And you are saying it doesn't work because split takes 1 parameter, right?
n
if split returned a
(Character -> T)
instead of a String, you could probably say
map(it.split("\s"))
but yeah,
split
accepts one parameter, and that parameter isn't the string being split; it's the pattern you want to split on, which is crucial
q
You could maybe do something like this?
Copy code
val spaces = "\\s+".toRegex()
val spliter = { s: String -> s.split(spaces) }
val a = "blah".lines().map(splitter)
But if the actual use case is not more complicated than what you've shown it's not really buying you anything.
j
ok, I don't think I understand if
.map(Character::toUpperCase)
gets translated to
.map { c: Character -> c.toUpperCase() }
, why
.map(CharSequence::split("\\s+".toRegex())
is not translated to
.map{cs:CharSequence -> cs.split("\\s+".toRegex())}
. I just mark it as one parameter extra. Does not work. Thank you for the replies.
n
it's just invalid syntax. you can't combine a method reference with a method invocation.
@Quincy yeah, that would work. might also promote the
splitter
thing into an actual method; that might be more efficient
q
@Ol' Dawg a reference like
Character::toUppercase
is a way of referring to a specific function defined elsewhere which satisfies the type
(Character) -> Character
r
Disclaimer: please really don't do this, I'm just messing with stuff https://pl.kotl.in/IF5TTwTJm this actually works the obvious question is why do
mySplit
? ... well original split has like 4 overloads and compiler complains it can't chose. Afaik, doing this is stretching the limits of Kotlin's type system anyways, to real question: Map can only handle if you pass it reference to function taking 1 argument - because it has 1 value (the
it
) and can just chunk it there. But split needs at least 2 arguments -
a.split(b)
both
a
and
b
are arguments, and
map
only has 1 value. And no, you can't just pass 1 argument to reference and expect a new function to be created (sadly)
n
I'm not really sure what partial buys you here
r
nothing 😛 Just wanted to try if that would work even I'm all for just specifying it - you won't get clearer than that if he hates to use
it
then easy solution: name it
n
Copy code
"blah".lines().map { it.split("\\s+".toRegex()) }
Already works and is perfectly readable, the problem is that you'd be executing the toRegex over and over
Which is a problem shared by the solution you posted
The ugliest part of the kotlin solution is that you have to create this
spaces
variable but it's not clear how you'd hope to avoid that in general.
r
the
partial
solution mess wouldn't actually call
toRegex
over and over - it passes the function just once to map, with already "inlined" argument but without managing to resolve that overload ambiguity, it's not really viable solution
n
Ah you're totally right, my bad
Probably not recommended either but a way to make it work as a one liner, without any extra machinery:
Copy code
val a = "1 2\n3 4"
        .lines()
        .map("\\s+".toRegex().let{ {line -> line.split(it)} })
w
It seems
Regex
already has a
split
. Can check if the output is desirable, but could try this:
Copy code
val a = "1 2\n3 4".lines().map("\\s+".toRegex()::split)
The docs says:
Splits the input CharSequence around matches of this regular expression.
So I believe it should work as expected.
2