Wasn't aware of this channel, so reposting my ques...
# functional
s
Wasn't aware of this channel, so reposting my question here
Copy code
I have just started looking at Kotlin, I have been using F# on .NET for a while now and I am liking Kotlin. I am missing pipe operator in Kotlin though, is there any plan to bring the pipe operator to Kotlin?
r
I’m not aware of any efforts to bring that and to be fair that style of composition is not widely used in Kotlin. Arrow used to have pipe but we removed in 0.13 because it didn’t get much use. https://github.com/arrow-kt/arrow-core/blob/0.11.0/arrow-syntax/src/main/kotlin/arrow/syntax/function/pipe.kt
e
Kotlin has two features that mike piping much less needed: 1. Kotlin has extensions, which usually let you "pipe" things directly in a natural
.call
style, e.g.
collection.filter {...}.map{...}
(no need for a pipe here) 2. Kotlin has
.let
scope function that covers the case for non-extension functions, e.g.
collection.first().let { println(it) }
w
Roman's answer is 💯 but for the sake of understanding, @Sandeep Chandra are you imagining something like
Copy code
infix fun <A, B> A.`|`(nextOp: (A) -> B): B {
    return nextOp(this)
}

fun test(): Int {
    return " " `|` String::length `|` " "::repeat `|` String::length
}
which cleans up to
Copy code
fun test(): Int {
    return " ".let(String::length).let(" "::repeat).let(String::length)
}
and then
Copy code
fun test(): Int {
    return " ".length.let(" "::repeat).length
}
in ideomatic kotlin?
s
Have a look at the following snippet
Copy code
let square x = x * x
[1..100]
|> List.map square
here I have declared a function called
square
and a list of numbers from 1..100 and then I call the List.map passing in
square
function. The pipe operator passes list of numbers to List.map, the map function takes 2 arguments. With pipe operator the value
piped
is passed as last argument to the function.
r
@Sandeep Chandra if you mean tacit, point free style in Kotlin that would look like:
Copy code
fun square(x: Int) = x * x
val result = (1..100).map(::square)
It gets more complex as your functions are polymorphic and callable references have more than one type arg in my experience but similar style can be used with them. https://kotlinlang.org/spec/expressions.html#callable-references
If you want to see the limits of more complex use cases try to pass
fold
or similar with more than one type argument as callable reference value to another function. In most cases you’d have to ascribe the types manually of the calling function so it takes exactly the shape it expects.
But the pipe operator does in essence what it did in arrow, take a function result and pass it to the next one. Kotlin does not abstract over function arity so for this to work with any name maybe
|>
as a library you’d still need to declare N variations of the operator for as high of a function arity you want to support.
m
It is for functional programming without object orientation.
e
Kotlin has extension functions for that. They have nothing to do with object-orientation and are great for writing functional code.
👍 1