1

This code prints "Hello 1". parseInput have two generic types, the first arg is a simple object of the first generic type A, the second arg is a function which suppose to change the generic type A to generic B. As you can see it works fine in the following.

fun toGreeting(input : Int) : String {
    return "hello " + input
}

fun <A, B> parseInput(raw : A, toB : (raw : A) -> B) : B {
    return toB(raw)
}

fun main(args: Array<String>) {
    val greeting = parseInput(1, ::toGreeting)
    println(greeting)
}

The question is how can I give a default lambda value for the second named argument in the parseInput. So I can call this function by just providing the first argument, and having it to use the default lambda function.

val greeting = parseInput(1)
println(greeting)
s-hunter
  • 24,172
  • 16
  • 88
  • 130
  • What do you want to specify as the default value? The default value can only be a function from Any to Any, and there are not too many useful functions which fit this signature. – yole Mar 20 '18 at 18:01
  • 1
    It seems like you can't even have an `(Any) -> Any` function as the default here. Since there's generics involved, a generic `(A) -> B` function is required, which then forces the caller to specify the generic types, as there's no way to infer `B`. As for the implementation of this default function, you can either cast something to `B` inside it (which _probably_ won't succeed), or have it return `Nothing` (which is not what you want here). – zsmb13 Mar 20 '18 at 18:06
  • @yole, a void, Unit would be good for default value. – s-hunter Mar 20 '18 at 18:28
  • 1
    So you want `greeting` in your second example to be equal to `Unit`? How is that useful? – yole Mar 20 '18 at 18:31
  • @yole, right it's not useful, but I wanted it to be not useful if it isn't provided when calling the function. My goal is to make the second function optional, which is why I want a default lambda function to return Unit – s-hunter Mar 20 '18 at 18:34
  • What if you made the second parameter nullable, assigned `null` to it as a default, and then returned `toB?.invoke(raw)` ? – zsmb13 Mar 20 '18 at 18:44
  • @zsmb13 Error:(16, 19) Type inference failed: Not enough information to infer parameter B in fun parseInput(raw: A, toB: ((raw: A) -> B)? = ...): B? Please specify it explicitly. – s-hunter Mar 20 '18 at 18:54

1 Answers1

1

Your requirements are contradictory. You want to be able to specify a function that returns a value of type B for any B (which is actually impossible by itself; the only possible such function is a function that always throws an exception), and you also want the compiler to be able to infer what B is when you haven't given the compiler any information from which it can be determined. In your example:

 val greeting = parseInput(1)  
 println(greeting)

...there is zero information from which the compiler could determine what type the greeting variable needs to have. There is no logic that would substitute Unit or any other specific type in this case; instead, as you correctly remark in your comment, this code fails to compile.

If you want greeting to be Unit in this case, you can achieve this by simply overloading the function:

fun <A> parseInput(raw: A) {
}

This function will return Unit, giving you the exact behavior you're looking for.

yole
  • 92,896
  • 20
  • 260
  • 197