worldterminator
worldterminator

Reputation: 3076

How to pass a function with implicit as parameter

I want to pass a function fun1 as a parameter to fun2. However fun1 needs an implicit parameter. Is is possible to define that implicit value inside fun2?

The code is like this:

import org.json4s._
import org.json4s.jackson.JsonMethods._

  def fun1(json:JValue)(implicit formats: Formats) = {

        //do something
  }


  def fun2(f: (JValue) => RatEvent,line:String ) = {

        implicit val formats = DefaultFormats  //has been defined in import
        val json = parse(line)  //covert string to jvalue
        val result = f(json)
  }

Here I pass fun1 to fun2, compiler complains that it cannot find implicit value for fun1.

  fun2(fun1,"asdfasdf")    //error here,   fun1 is lack of an implicit value

I want to solve the problem by changing the shape of fun2 i.e.

def fun2(f: (JValue)(implicit Formats) => RatEvent,line:String ) //doesn't compile

But I don't know how to write it correctly.

Supplement:

Declare an implicit Format may seems a good solution. But I have to define it in fun2. I have made problem simple. The real funs looks like:

  def fun2(f: (JValue) => RatEvent,lines:RDD[String] )(implicit sc:SparkContext) = {

        for (
          line <- lines
        ){
        implicit val formats = DefaultFormats  //has been defined in import
        val json = parse(line)  //covert string to jvalue
        val result = f(json)
        ......
        }
  }

formats has to be defined inside of lines's map function (I used for instead).

Upvotes: 6

Views: 1374

Answers (1)

Seth Tisue
Seth Tisue

Reputation: 30508

A Scala function value's apply method only has one parameter list and does not take any implicit parameters. You can't do anything about that.

You could change the shape of fun2 to take the extra parameter as a normal parameter:

class J; class F; class R

def fun1(j: J)(implicit f: F): R =
  new R
def fun2(fn: (J, F) => R) {
  fn(new J, new F)
}

fun2(fun1(_)(_))

But yuck; the call site isn't as nice as the fun2(fun1) you wanted.

If you have an implicit F in scope at the call site, then you can change the shape of fun2 as follows:

class J; class F; class R

def fun1(j: J)(implicit f: F): R =
  new R

def fun2(fn: J => R)(implicit f: F) {
  fn(new J)
}

implicit val f = new F
fun2(fun1)

Yay, clean call site!

Does this meet your requirements? In your question, you only have a Formats in implicit scope inside the body of fun2, but I can't tell if that's a necessary condition of your question, or just something accidental about the way you condensed your code to fit in a question.

Upvotes: 2

Related Questions