1

I am having trouble for setting a default value for a function parameter when the types are generics.

My function signature looks like:

  def doStuff[ K, T ]( result: Future[ Seq[ T ] ] )
                     ( transform: T => Option[ K ] ): Future[ Either[ String, Option[ K ] ] ] = {
  }

And I am aware that I cat set a default value to a function parameter like:

  def doStuff(a: Int)
             (f: Int => Option[Int] = k => Option(k)): Future[ Either[ String, Option[ Int ] ] ] = {
  }

However I can't combine these generic types with a default function value

  def doStuff[ K, T ]( result: Future[ Seq[ T ] ] )
                     ( transform: T => Option[ K ] = k => Option(k)): Future[ Either[ String, Option[ K ] ] ] = {
  }

with an obvious error message: Option[T] does not conform expected Option[K]

my last resort is to pass class tag in for K and T and change the default parameter from k => Option(k) to

def doStuff[ K: ClassTag, T ]( result: Future[ Seq[ T ] ] )
                               ( transform: T => Option[ K ] = {
                                 case m: K => Option( m )
                                 case _ => None
                               } ): Future[ Either[ String, Option[ K ] ] ] = {
  }

but this approach will force me to pass in my generic parameters on function call.

Can anyone see any other approach?

7
  • 1
    Is there a relationship between T and K? Commented Feb 3, 2017 at 12:48
  • for the default case K is Option[T] but otherwise no, there is no relationship at all, they can and will be totally different case classes Commented Feb 3, 2017 at 12:50
  • @kali is it necessary to have doStuff with two parameter lists? can it be with one? Commented Feb 3, 2017 at 15:00
  • If you can't think of a sensible default value, why do you want to assign one? Commented Feb 3, 2017 at 16:22
  • Or is your goal also to have K default to T when no second parameter is supplied? Commented Feb 3, 2017 at 16:39

1 Answer 1

1

I haven't achieved it with the signature you provided with two parameter lists. But I wonder if you can use it with one parameter list:

def toOption[R](x: R): Option[R] = Option(x)

def doStuff[K, T](result: Future[Seq[T]], transform: T => Option[K] = toOption[K] _): Future[Either[String, Option[K]]] = {
  result.map(r => Right[String, Option[K]](transform(r.head)))
}

// Then, if you need a function of the second parameter, you can use partially applied function:
val rf: (Int => Option[Int]) => Future[Either[String, Option[Int]]] = doStuff[Int, Int](Future(List(1, 2)), _)

// Or call with default argument:
val r: Future[Either[String, Option[Int]]] = doStuff[Int, Int](Future(List(1, 2)))

// These lines should print the same
println(rf(toOption))
println(r)
Sign up to request clarification or add additional context in comments.

1 Comment

Hi, Thanks for the answer. If I am calling the function "with" the generic parameters (doStuff[Int, Int](.....)) then I'd rather use the "last resort" approach I mentioned in my question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.