I wrote the following Scala code below to handle a String that I pass in, format the String, append it to a StringBuilder
and return the formatted String
with escaped unicode back to my caller for other processing.
我编写了下面的Scala代码来处理我传入的字符串、格式化字符串、将其附加到StringBuilder并将带转义unicode的格式化字符串返回给调用者进行其他处理。
The Scala compiler complains of the following on the lines where there is a String.format
call with the following error:
Scala编译器会在有字符串的行上抱怨如下内容。格式化调用,错误如下:
overloaded method value format with alternatives:
(x$1; java.util.Locale; x$2: String, X$3: Object*)
(x$1:String,x$2: Object*)
String cannot be applied to(*String, Int)
重载方法值格式与其他选项:(x$1;java.util.Locale;x$2: String,x$ 3: Object*) (x$1:String,x$2: Object*) String不能应用于(*String, Int)
class TestClass {
private def escapeUnicodeStuff(input: String): String = {
//type StringBuilder = scala.collection.mutable.StringBuilder
val sb = new StringBuilder()
val cPtArray = toCodePointArray(input) //this method call returns an Array[Int]
val len = cPtArray.length
for (i <- 0 until len) {
if (cPtArray(i) > 65535) {
val hi = (cPtArray(i) - 0x10000) / 0x400 + 0xD800
val lo = (cPtArray(i) - 0x10000) % 0x400 + 0xDC00
sb.append(String.format("\\u%04x\\u%04x", hi, lo)) //**complains here**
} else if (codePointArray(i) > 127) {
sb.append(String.format("\\u%04x", codePointArray(i))) //**complains here**
} else {
sb.append(String.format("%c", codePointArray(i))) //**complains here**
}
}
sb.toString
}
}
How do I address this problem? How can I clean up the code to accomplish my purpose of formatting a String? Thanks in advance to the Scala experts here
我如何解决这个问题?如何清理代码以实现格式化字符串的目的?感谢Scala专家
2 个解决方案
#1
7
The String.format
method in Java expects Objects
as its arguments. The Object
type in Java is equivalent to the AnyRef
type in Scala. The primitive types in Scala extend AnyVal
– not AnyRef
. Read more about the differences between AnyVal
, AnyRef
, and Any
in the docs or in this answer. The most obvious fix is to use the Integer
wrapper class from Java to get an Object
representation of your Ints
:
的字符串。Java中的format方法需要对象作为它的参数。Java中的对象类型等同于Scala中的AnyRef类型。Scala中的基本类型扩展了AnyVal——而不是AnyRef。请阅读更多关于AnyVal、AnyRef和文档中的任何一个或这个答案中的差异。最明显的修复方法是使用Java的Integer包装类来获得int的对象表示形式:
String.format("\\u%04x\\u%04x", new Integer(hi), new Integer(lo))
Using those wrapper classes is almost emblematic of unidiomatic Scala code, and should only be used for interoperability with Java when there is no better option. The more natural way to do this in Scala would be to either use the StringOps
equivalent method format
:
使用这些包装类几乎是unidiomatic Scala代码的象征,在没有更好的选择时,只能用于与Java的互操作性。在Scala中更自然的做法是使用StringOps等效的方法格式:
"\\u%04x\\u%04x".format(hi, lo)
You can also use the f
interpolator for a more concise syntax:
你也可以使用f插值器来实现更简洁的语法:
f"\\u$hi%04x\\u$lo%04x"
Also, using a for
loop like you have here is unidiomatic in Scala. You're better off using one of the functional list methods like map
, foldLeft
, or even foreach
together with a partial function using the match
syntax. For example, you might try something like:
此外,像这里一样使用for循环在Scala中是单变量的。最好使用函数列表方法之一,如map、foldLeft甚至foreach,或者使用match语法使用部分函数。例如,你可以试试以下方法:
toCodePointArray(input).foreach {
case x if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
sb.append(f"\\u$hi%04x\\u$lo%04x")
case x if > 127 => sb.append(f"\\u$x%04x")
case x => sb.append(f"$x%c")
}
Or, if you don't have to use StringBuilder
, which really only needs to be used in cases where you are appending many strings, you can replace your whole method body with foldLeft
:
或者,如果你不需要使用StringBuilder,它只需要在添加很多字符串的情况下使用,你可以用foldLeft替换整个方法体:
def escapeUnicodeStuff(input: String) = toCodePointArray(input).foldLeft("") {
case (acc, x) if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
acc + f"\\u$hi%04x\\u$lo%04x"
case (acc, x) if x > 127 => acc + f"\\u$x%04x"
case (acc, x) => acc + f"$x%c"
}
Or a even map
followed by a mkString
:
或者是一个偶数映射,后面跟着一个mkString:
def escapeUnicodeStuff(input: String) = toCodePointArray(input).map {
case x if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
f"\\u$hi%04x\\u$lo%04x"
case x if x > 127 => f"\\u$x%04x"
case x => f"$x%c"
}.mkString
#2
1
I couldn't figure out what exactly is causing that "overload *" but notice the code below:
我不知道到底是什么导致了“过载冲突”,但请注意下面的代码:
scala> "\\u%04x\\u%04x".format(10,20)
res12: String = \u000a\u0014
Using the one provided by StringOps works.
使用StringOps提供的方法。
#1
7
The String.format
method in Java expects Objects
as its arguments. The Object
type in Java is equivalent to the AnyRef
type in Scala. The primitive types in Scala extend AnyVal
– not AnyRef
. Read more about the differences between AnyVal
, AnyRef
, and Any
in the docs or in this answer. The most obvious fix is to use the Integer
wrapper class from Java to get an Object
representation of your Ints
:
的字符串。Java中的format方法需要对象作为它的参数。Java中的对象类型等同于Scala中的AnyRef类型。Scala中的基本类型扩展了AnyVal——而不是AnyRef。请阅读更多关于AnyVal、AnyRef和文档中的任何一个或这个答案中的差异。最明显的修复方法是使用Java的Integer包装类来获得int的对象表示形式:
String.format("\\u%04x\\u%04x", new Integer(hi), new Integer(lo))
Using those wrapper classes is almost emblematic of unidiomatic Scala code, and should only be used for interoperability with Java when there is no better option. The more natural way to do this in Scala would be to either use the StringOps
equivalent method format
:
使用这些包装类几乎是unidiomatic Scala代码的象征,在没有更好的选择时,只能用于与Java的互操作性。在Scala中更自然的做法是使用StringOps等效的方法格式:
"\\u%04x\\u%04x".format(hi, lo)
You can also use the f
interpolator for a more concise syntax:
你也可以使用f插值器来实现更简洁的语法:
f"\\u$hi%04x\\u$lo%04x"
Also, using a for
loop like you have here is unidiomatic in Scala. You're better off using one of the functional list methods like map
, foldLeft
, or even foreach
together with a partial function using the match
syntax. For example, you might try something like:
此外,像这里一样使用for循环在Scala中是单变量的。最好使用函数列表方法之一,如map、foldLeft甚至foreach,或者使用match语法使用部分函数。例如,你可以试试以下方法:
toCodePointArray(input).foreach {
case x if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
sb.append(f"\\u$hi%04x\\u$lo%04x")
case x if > 127 => sb.append(f"\\u$x%04x")
case x => sb.append(f"$x%c")
}
Or, if you don't have to use StringBuilder
, which really only needs to be used in cases where you are appending many strings, you can replace your whole method body with foldLeft
:
或者,如果你不需要使用StringBuilder,它只需要在添加很多字符串的情况下使用,你可以用foldLeft替换整个方法体:
def escapeUnicodeStuff(input: String) = toCodePointArray(input).foldLeft("") {
case (acc, x) if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
acc + f"\\u$hi%04x\\u$lo%04x"
case (acc, x) if x > 127 => acc + f"\\u$x%04x"
case (acc, x) => acc + f"$x%c"
}
Or a even map
followed by a mkString
:
或者是一个偶数映射,后面跟着一个mkString:
def escapeUnicodeStuff(input: String) = toCodePointArray(input).map {
case x if x > 65535 =>
val hi = (x - 0x10000) / 0x400 + 0xD800
val lo = (x - 0x10000) % 0x400 + 0xDC00
f"\\u$hi%04x\\u$lo%04x"
case x if x > 127 => f"\\u$x%04x"
case x => f"$x%c"
}.mkString
#2
1
I couldn't figure out what exactly is causing that "overload *" but notice the code below:
我不知道到底是什么导致了“过载冲突”,但请注意下面的代码:
scala> "\\u%04x\\u%04x".format(10,20)
res12: String = \u000a\u0014
Using the one provided by StringOps works.
使用StringOps提供的方法。