开发者

Scala: 'implicit conversions are not applicable' in a simple for expression

I started out with Scala today, and I ran into an intriguing problem. I am running a for expression to iterate over the characters in a string, like such:

class Example {
  开发者_StackOverflow社区def forString(s: String) = {
    for (c <- s) {
      // ...
    }
  }
}

and it is consistently failing with the message:

error: type mismatch;
  found   : Int
  required: java.lang.Object
Note that implicit conversions are not applicable because they are ambiguous:
  ...
    for (c <- s) {
         ^
one error found

I tried changing the loop to several things, including using the string's length and using hardcoded numbers (just for testing), but to no avail. Searching the web didn't yield anything either...

Edit: This code is the smallest I could reduce it to, while still yielding the error:

class Example {
  def forString(s: String) = {
    for (c <- s) {
      println(String.format("%03i", c.toInt))
    }
  }
}

The error is the same as above, and happens at compile time. Running in the 'interpreter' yields the same.


Don't use the raw String.format method. Instead use the .format method on the implicitly converted RichString. It will box the primitives for you. i.e.

jem@Respect:~$ scala
Welcome to Scala version 2.8.0.final (Java HotSpot(TM) Client VM, Java 1.6.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> class Example {
     |   def forString(s: String) = {
     |     for (c <- s) {
     |       println("%03i".format(c.toInt))
     |     }
     |   }
     | }
defined class Example

scala> new Example().forString("9")
java.util.UnknownFormatConversionException: Conversion = 'i'

Closer, but not quite. You might want to try "%03d" as your format string.

scala> "%03d".format("9".toInt)
res3: String = 009


Scala 2.81 produces the following, clearer error:

scala> class Example {
     |   def forString(s: String) = {
     |     for (c <- s) {            
     |       println(String.format("%03i", c.toInt))
     |     }                                        
     |   }                                          
     | }                                            
<console>:8: error: type mismatch;                  
 found   : Int                                      
 required: java.lang.Object                         
Note: primitive types are not implicitly converted to AnyRef.
You can safely force boxing by casting x.asInstanceOf[AnyRef].
             println(String.format("%03i", c.toInt))          
                                  ^                           

Taking into account the other suggestion about String.format, here's the minimal fix for the above code:

scala> def forString(s: String) = {
     | for (c: Char <- s) {
     | println(String.format("%03d", c.toInt.asInstanceOf[AnyRef]))
     | }}
forString: (s: String)Unit

scala> forString("ciao")
099
105
097
111

In this case, using the implicit format is even better, but in case you need again to call a Java varargs method, that's a solution which works always.


I tried your code (with an extra println) and it works in 2.8.1:

class Example {
     | def forString(s:String) = {
     |   for (c <- s) {
     |    println(c)   
     |   }
     | }
     | }

It can be used with:

new Example().forString("hello")
h
e
l
l
o
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜