How can I disable a specific Implicit in Scala that prevents code from being compiled due to overloaded methods?

I'm trying to answer this question myself: Scala Play 2.4.x wide character handling via anorm (MySQL) in Java Mail

and I came across this possible solution: https://objectpartners.com/2013/04/24/html-encoding-utf-8-characters/

So, I decided to rewrite the sample in Scala:

  def htmlEncode(input: String) = htmlEncode_sb(input).toString

  def htmlEncode_sb(input: String, stringBuilder: StringBuilder = new StringBuilder()) = {
    for ((c, i) <- input.zipWithIndex) {
      if (CharUtils.isAscii(c)) {
        // Encode common HTML equivalent characters
        stringBuilder.append(StringEscapeUtils.escapeHtml4(c.toString()))
      } else {
        // Why isn't this done in escapeHtml4()?
        stringBuilder.append(String.format("&#x%x;": String, Character.codePointAt(input, i)))
      }
    }
    stringBuilder
  }
}

      

FYI: I usually rewrite most things that work with Strings into a wrapped call to StringBuilder in case I am already creating something with another StringBuilder, in which case I can just pass this StringBuilder as a parameter if it doesn't work like normal string by calling the first function.

You might think that everything is ok and dandy, however the Scala compiler has this to say:

[info] Compiling 1 Scala source to /SomeOne/SomePath/SomeProject/target/scala-2.11/classes...
[error] /SomeOne/SomePath/SomeProject/TKEmailAgent.scala:278: overloaded method value format with alternatives:
[error]   (x$1: java.util.Locale,x$2: String,x$3: Object*)String <and>
[error]   (x$1: String,x$2: Object*)String
[error]  cannot be applied to (String, Int)
[error]         stringBuilder.append(String.format("&#x%x;": String, Character.codePointAt(input, i)))
[error]                                     ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed

      

Note that I even tried to "declare" the first parameter, which must be a string:

stringBuilder.append(String.format("&#x%x;": String, Character.codePointAt(input, i)))

      

and yet the compiler didn't figure out that the overloaded method with java.util.Locale would do the trick.

I moved the code into a less cluttered class, thinking it might have been an import, but it wasn't.

So the question is, how to disable the implicit ones that are not selected?

OR

How to satisfy the compiler need to know what you really want here?

+3


source to share


4 answers


Apparently this compiles:

    stringBuilder.append(String.format("&#x%x;": String, Character.codePointAt(input, i).toString))

      



However, I believe it can lead to a primarily victory in the purpose of assigning a format if toString gets hold of things first.

So my original questions are still standing ...

0


source


And this might actually work:

  def htmlEncode(input: String) = htmlEncode_sb(input).toString

  def htmlEncode_sb(input: String, stringBuilder: StringBuilder = new StringBuilder()) = {
    for ((c, i) <- input.zipWithIndex) {
      if (CharUtils.isAscii(c)) {
        // Encode common HTML equivalent characters
        stringBuilder.append(StringEscapeUtils.escapeHtml4(c.toString()))
      } else {
        // Why isn't this done in escapeHtml4()?
        stringBuilder.append(String.format("""&#x%s;""": String, Character.codePointAt(input, i).toString))
      }
    }
    stringBuilder
  }
}

      

It turns out that CodePointAt returns Int and when we toString it (which looks OK in this context), String.format needs to be configured to handle string substitution.



I think I'll rewrite this with the Scala String style and see what happens

 s"""&#x${Character.codePointAt(input, i)};"""

      

0


source


It seems to work!

  def htmlEncode(input: String) = htmlEncode_sb(input).toString

  def htmlEncode_sb(input: String, stringBuilder: StringBuilder = new StringBuilder()) = {
    stringBuilder.synchronized {
      for ((c, i) <- input.zipWithIndex) {
        if (CharUtils.isAscii(c)) {
          // Encode common HTML equivalent characters
          stringBuilder.append(StringEscapeUtils.escapeHtml4(c.toString()))
        } else {
          // Why isn't this done in escapeHtml4()?
          stringBuilder.append(s"""&#${Character.codePointAt(input, i)};""")
        }
      }
      stringBuilder
    }
  }

      

However, it doesn't answer my original no-show question.

0


source


Your problem has nothing to do with implicits * and anything to do with the fact that Scala is Int

not Object

. The error message tells you the truth: it String.format

has two overloads, and the parameter list doesn't match either of them.

Try using Int.box(Character.codePointAt(input, i))

to make your parameter to Object

.

* Ok, it has little to do with implicits as it Int

can be implicitly converted to Integer

, but that won't apply to converting Int

to Object

.

0


source







All Articles