https://kotlinlang.org logo
#getting-started
Title
# getting-started
v

Vitali Plagov

03/29/2022, 12:50 PM
How can I do the same with Kotlin? I want to create a predicate based on the function:
Copy code
// java
var words = List.of("one", "two", "three");
Function<Integer, Predicate<String>> lengthFun = (minLength) -> (str) -> str.length() > minLength;
Predicate<String> isLongerThan2 = lengthFun.apply(2);
Predicate<String> isLongerThan3 = lengthFun.apply(3);

var longerThan2 = words.stream().filter(isLongerThan2).collect(Collectors.toList());
var longerThan3 = words.stream().filter(isLongerThan3).collect(Collectors.toList());
I know that these predicates are pretty straightforward and can be inlined straight into the
filter { }
function. But I’m more interested in a general approach of how to do it.
h

hfhbd

03/29/2022, 12:58 PM
If you want to keep a
Predicate
, I would use this, because a Predicate is just a function: (String) -> Boolean:
Copy code
val words = listOf("one", "two", "three")
val lengthFun = fun String.(minLength: Int): Boolean = length > minLength
val isLongerThan2 = fun String.() = lengthFun(2)
val isLongerThan3 = fun String.() = lengthFun(3)

val longerThan2 = words.filter(isLongerThan2)
val longerThan3 = words.filter(isLongerThan3)
You could also use the lambda expression:
Copy code
val lengthFun = { str: String, minLength: Int -> str.length > minLength }
val isLongerThan2 = { str: String -> lengthFun(str, 2) }
val isLongerThan3 = { str: String -> lengthFun(str ,3) }
r

Rob Elliot

03/29/2022, 1:01 PM
This is the direct translation into Kotlin:
Copy code
val words = listOf("one", "two", "three")
val lengthFun: (Int) -> ((String) -> Boolean) = { minLength -> { str -> str.length > minLength } }
val isLongerThan2: (String) -> Boolean = lengthFun(2)
val isLongerThan3: (String) -> Boolean = lengthFun(3)

val longerThan2: List<String> = words.filter(isLongerThan2)
val longerThan3: List<String> = words.filter(isLongerThan3)
👍 1
Or if you wanted to be a bit more functional about it:
Copy code
fun <A, B, R> ((A, B) -> R).curry(a: A): (B) -> R = { b: B -> this(a, b) }

val words = listOf("one", "two", "three")
val lengthFun: (Int, String) -> Boolean = { minLength, str -> str.length > minLength }
val isLongerThan2: (String) -> Boolean = lengthFun.curry(2)
val isLongerThan3: (String) -> Boolean = lengthFun.curry(3)

val longerThan2: List<String> = words.filter(isLongerThan2)
val longerThan3: List<String> = words.filter(isLongerThan3)
v

Vitali Plagov

03/29/2022, 1:25 PM
@hfhbd if I understand correctly, these two:
String.(minLength: Int)
and
String.()
are extension functions of String type?
h

hfhbd

03/29/2022, 1:28 PM
Yes
v

Vitali Plagov

03/29/2022, 1:39 PM
@Rob Elliot thanks! your first code block is very similar to Java. That’s clear. Can’t understand though why can’t I pass in the predicate to the
filter { }
function and just to the
filter()
one
r

Rob Elliot

03/29/2022, 1:53 PM
xs.filter { x -> ... }
is syntax sugar for
xs.filter({ x -> ... })
- you are passing a function literal
{ x -> ... }
as the argument to
filter
, you just don't have to put the argument parentheses around it (in fact it's good style not to ). So when you call
words.filter { isLongerThan2 }
it will not compile, because
{ isLongerThan2 }
is a function literal for a function of type
() -> (String) -> Boolean
, and
filter
needs
(String) -> Boolean
. You could use
words.filter { isLongerThan2(it) }
- a function literal with a single parameter automatically gets a parameter called
it
if you do not provide a parameter list. But that's exactly the same as
words.filter(isLongerThan2)
(though perhaps a little simpler to read).
A minor variant on @hfhbd’s solution reads quite nicely as English when done like that, because it maintains subject-verb-object order:
Copy code
val words = listOf("one", "two", "three")
fun String.isLongerThan(minLength: Int): Boolean = length > minLength

val longerThan2 = words.filter { it.isLongerThan(2) }
val longerThan3 = words.filter { it.isLongerThan(3) }
👍 1
v

Vitali Plagov

03/29/2022, 1:59 PM
Thanks guys! That answered my question!
3 Views