Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to resolve ambiguous method reference in scala

Tags:

scala

slf4j

Here is the specific issue I am encountering. I am using SLF4J Logger (The type of the variable logger below)

//After adding to a map
logger debug ("Adding {} = {}", key, value)

Here is what mouse hover in eclipse (and the compiler) tell me.

ambiguous reference to overloaded definition, both method debug in trait Logger of type (x$1: String, x$2: Object*)Unit and method debug in trait Logger of type (x$1: String, x$2: Any, x$3: Any)Unit match argument types (String,String,String)

I understand why they are ambiguous. I am certainly not arguing with the compiler :). I want to simply know how seasoned programmers solve this issue.

Here are the alternatives I can use

  1. Create and array , and ride the Object* definition

    logger debug ("Adding {} = {}", Array(key, value):_*)

  2. Cast to Any

    logger debug ("Adding {} = {}", key.asInstanceOf[Any], value.asInstanceOf[Any])

Neither approach is particularly appealing. Does the community have a better approach or suggestions for me?

Many thanks!

like image 729
Prashant Avatar asked Sep 02 '15 21:09

Prashant


2 Answers

I would use

logger.debug("Adding {} = {}", key, value: Any)

Alternatively following can be used:

logger.debug("Adding {} = {}", Array(key, value):_*)

Please pay attention to :_*. Should you omit these symbols and it will call Object* method providing only 1 argument, which will be an array.

like image 184
Oleg Rudenko Avatar answered Nov 02 '22 05:11

Oleg Rudenko


First off a nod of credit to @Shadowlands, @ArneClaassen and @OlgeRudenko. As mentioned in the comments, this does seem to be known issue. That stopped me from trying to "solve" it. The next thing to do was to find a good work around that did not break Scala idioms.

With these constraints in mind I chose to go with String Interpolation as suggested above. I also switched to scala-logging. Quoting from their GitHub/README,

Scala Logging is a convenient and performant logging library wrapping SLF4J. It's convenient, because you can simply call log methods without checking whether the respective log level is enabled:

logger.debug(s"Some $expensive message!")

It's performant, because thanks to Scala macros the check-enabled-idiom is applied, just like writing this more involved code:

if (logger.isDebugEnabled) logger.debug(s"Some $expensive message!")

Thanks all! As far as I am concerned, this is resolved. If the commentators can post their answers, I will be happy to acknowledge them.

As always, feels good to be standing on the shoulders of friendly giants!

PS: I just verified that there is no execution cost to String interpolation if you are using scala-logging. My verification method was crude but effective.

    log.debug{ 
        {
          throw new IllegalAccessException("This should not have been called with debug off!")
        }
        s"Added Header ${name}:${headerValue}"
      }

Sure enough, when I set my log to DEBUG, the exception is thrown, as expected , but vanishes when I set it to a level higher. And yes, I have already removed the IllegalAccessException part :).

like image 24
Prashant Avatar answered Nov 02 '22 05:11

Prashant