Kotlin: higher order function with recursion - recursion

I have to create a higher order function which returns a lambda to learn functional programming with Kotlin.
This is the class
class Product (val productName : String, val price : Double, val rating : Int) {
override fun toString () = "$productName, $price, $rating"
}
this is my function
fun productFactory (productName: String , rating : Int) : (Double) -> Product {
val x : (Double) -> Product = productFactory(productName, rating)
return x
}
this is how I call the function
val cheese = productFactory("Gouda", 5)
val product = cheese(4.99)
Although it seems to work with the needed constructors, it causes a StackOverflowError and I don't know, where the problem is. Can anybody help me?

Your function productFactory is recursively calling itself with no way to exit the recursion, so it will always cause a stack overflow.
The function it returns should certainly not be itself because the behavior is different.
You can define the returned function as a lambda:
fun productFactory (productName: String , rating : Int) : (Double) -> Product {
return { price -> Product(productName, price, rating) }
}
or use function syntax and return the function using the :: operator:
fun productFactory (productName: String , rating : Int) : (Double) -> Product {
fun produce(price: Double) = Product(productName, price, rating)
return ::produce
}

Related

Can I convert a Kotlin KFunction1 to a KFunction0 by applying the argument?

I have a reference to a functionthat needs a parameter.
fun foo(x: Int) = 2 * x
val f: KFunction1<Int, Int> = ::foo
Is there any way to write applyArgument where
val f2: KFunction0<Int> = f1.applyArgument(42)
assertEquals("foo", f2.name)
assertEquals(84, f2())
I don't want to use a callable reference, as I need access to the name property.
hope it helps you:
fun foo(x: Int) = 2 * x
val f1 = ::foo
val f0 = { -> f1(42) }
f0() //84
KFunctions are intented to represent functions that are explicitly decleared in Kotlin code, but f2 is not declared anywhere in the code. In addition KFunction has lot of reflection properties and functions which are not relevant to the applied function f2. Therefore even if it is possible it is not recommended.
If you want to do it anyway you can simply write an applyArgument function in this way:
fun <T, R> KFunction1<T, R>.applyArgument(value: T): KFunction0<R> {
return object : KFunction<R> by this, KFunction0<R> {
override fun invoke(): R {
return this#applyArgument(value)
}
}
}
But, if what you need is to preserve the name, I would do it in a safe way. One way could be:
data class Named<out T>(val name: String, val value: T)
fun <T, R> Named<T>.map(transform: (T) -> R): Named<R> = Named(name, transform(value))
val <F : KFunction<*>> F.named: Named<F>
get() = Named(name, this)
Then use it:
fun foo(x: Int) = 2 * x
val f: Named<(Int) -> Int> = ::foo.named
val f2: Named<() -> Int> = f.map { fValue -> { fValue(42) } }
assertEquals("foo", f2.name)
assertEquals(84, f2.value())
Partial application is possible.
You may just declare a function for partial application and use it for the :: reference.
Hence, the name would not be the original function. Another approach - create your own classes/interfaces
data class MyFunction1<T, R>(val name: String, val f: (T) -> R) {
operator fun invoke(t: T) = f(t)
}
data class MyFunction0<R>(val name: String, val f: () -> R) {
operator fun invoke() = f()
}
Now define the curring:
fun MyFunction1<T, R>.curry(t: T) = MyFunction0(name){ f(t) }
(it can be a member function too)

Generic function works, but generic class doesn't?

I would like a class that is a generic for KProperty1, I can do this for a function, but not a class:
import kotlin.reflect.KProperty1
data class Dog(val name: String, val age: Int)
fun <P: KProperty1<*, *>> reflectionHelper(input: P) = input.name
fun <P: KProperty1<*, *>> getReflectionHelper(clazz: P) = ReflectionHelper<P>()
class ReflectionHelper<P: KProperty1<*, *>> {
}
fun main(args : Array<String>) {
println(reflectionHelper(Dog::age)) // Works
val helper1 = getReflectionHelper(Dog::age) // Also Works
val helper2 = ReflectionHelper<Dog::age>() // Error: Type inference failed
}
Dog::age is a value (of type KProperty1<Dog, String>), not a type. In between < and > you need to put a type, or you need to omit them entirely and the type will be inferred (that's what happens in the first two lines).
So the equivalent to your funs would be
class ReflectionHelper<P: KProperty1<*, *>>(input: P) { ... }
val helper2 = ReflectionHelper(Dog::age)
If you don't need input: P as a parameter, you'll have to specify P explicitly both for fun and for class.

Kotlin's reduce() function with different types

I was looking through array extension functions and found reduce() one
inline fun <S, T: S> Array<out T>.reduce(operation: (acc: S, T) -> S): S {
if (isEmpty())
throw UnsupportedOperationException("Empty array can't be reduced.")
var accumulator: S = this[0]
for (index in 1..lastIndex) {
accumulator = operation(accumulator, this[index])
}
return accumulator
}
here the accumulator variable of type S assigned with first element from the array with type T.
Can't wrap my head around the real use case of reduce() function with two data types. Here synthetic example which actually doesn't make any sense.
open class A(var width: Int = 0)
class B(width: Int) : A(width)
val array = arrayOf(A(7), A(4), A(1), A(4), A(3))
val res = array.reduce { acc, s -> B(acc.width + s.width) }
Seems most real life use cases with this function use this signature:
inline fun <T> Array<out T>.reduce(operation: (acc: T, T) -> T): T
Can you help with providing some examples, where reduce() function can be useful with different types.
Here is an example:
interface Expr {
val value: Int
}
class Single(override val value: Int): Expr
class Sum(val a: Expr, val b: Expr): Expr {
override val value: Int
get() = a.value + b.value
}
fun main(args: Array<String>) {
val arr = arrayOf(Single(1), Single(2), Single(3));
val result = arr.reduce<Expr, Single> { a, b -> Sum(a, b) }
println(result.value)
}

How to use map in a function

The function in map is pretty easy. I want to double every element in a list which can be done:
map(fn x => x * 2);
But what if I want to name this function double?
fun double = map(fn x => x * 2);
Calling this function I get
- double [1,2,3];
val it = fn : int list -> int list
How can I name this function double?
The result of map (fn x => x * 2) is a function, which can be bound to an identifier:
- val double = map (fn x => x * 2);
val double = fn : int list -> int list
- double [1,2,3];
val it = [2,4,6] : int list
The fun form is just syntactic sugar. For example:
fun name param = ...
will be desugared to:
val rec name = fn param => ...
The rec part is a keyword that lets you implement recursive function definitions.

How can go-lang curry?

In functional programming likes Haskell, I can define function
add a b = a+b
Then add 3 will return a function that take one parameter and will return 3 + something
How can I do this in GO?
When I define a function that take more than one (say n) parameters, can I only give it one parameter and get another function that take n-1 parameters?
Update:
Sorry for the imprecise words in my original question.
I think my question should be asked as two qeustions:
Is there partial application in GO?
How GO do function curry?
Thanks TheOnly92 and Alex for solving my second question. However, I am also curious about the first question.
To extend on the previous answer, which allows you to take an arbitrary number of arguments:
package main
import (
"fmt"
)
func mkAdd(a int) func(...int) int {
return func(b... int) int {
for _, i := range b {
a += i
}
return a
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5,3), add3(6))
}
Perhaps something like
package main
import (
"fmt"
)
func mkAdd(a int) func(int) int {
return func(b int) int {
return a + b
}
}
func main() {
add2 := mkAdd(2)
add3 := mkAdd(3)
fmt.Println(add2(5), add3(6))
}
You can take it a step further by defining a function type and then adding a method to it.
package main
import "fmt"
type Add func(int, int) int
func (f Add) Apply(i int) func(int) int {
return func(j int) int {
return f(i, j)
}
}
func main() {
var add Add = func(i, j int) int { return i + j }
add3 := add.Apply(3)
fmt.Println("add 3 to 2:", add3(2))
}
You can even try with variadic functions:
package main
import "fmt"
type Multiply func(...int) int
func (f Multiply) Apply(i int) func(...int) int {
return func(values ...int) int {
values = append([]int{i}, values...)
return f(values...)
}
}
func main() {
var multiply Multiply = func(values ...int) int {
var total int = 1
for _, value := range values {
total *= value
}
return total
}
var times2 Multiply = multiply.Apply(2)
fmt.Println("times 2:", times2(3, 4), "(expect 24)")
// ... and you can even cascade (if assigned the Multiply type)
times6 := times2.Apply(3)
fmt.Println("times 6:", times6(2, 3, 5, 10), "(expect 1800)")
}
Hope this helps!

Resources