Scala: «неявные преобразования неприменимы» в простом выражении for

Сегодня я начал работать со Scala и столкнулся с интригующей проблемой. Я запускаю выражение for для перебора символов в строке, например:

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

и он постоянно терпит неудачу с сообщением:

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

Я попытался изменить цикл на несколько вещей, включая использование длины строки и использование жестко закодированных чисел (только для тестирования), но безрезультатно. Поиск в сети тоже ничего не дал...

Редактировать: этот код является наименьшим, до которого я мог бы его сократить, но все равно выдает ошибку:

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

Ошибка такая же, как и выше, и происходит во время компиляции. Запуск в «интерпретаторе» дает то же самое.


person Félix Saparelli    schedule 30.03.2011    source источник
comment
Было бы полезно, если бы вы показали больше/весь код. Фрагмент кода, который вы показываете, кажется, в порядке.   -  person Fabian    schedule 30.03.2011
comment
Почтовый индекс, указывающий на проблему. Если пост слишком длинный, то удаляйте из него строки, пока не получите наименьший образец, отображающий проблему. Возможно, вы даже узнаете, в чем проблема.   -  person Daniel C. Sobral    schedule 30.03.2011


Ответы (3)


Не используйте необработанный метод String.format. Вместо этого используйте метод .format для неявно преобразованного RichString. Он упакует примитивы для вас. то есть

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'

Ближе, но не совсем. Возможно, вы захотите попробовать "%03d" в качестве строки формата.

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

Scala 2.81 выдает следующую более четкую ошибку:

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))          
                                  ^                           

Принимая во внимание другое предложение о String.format, вот минимальное исправление для приведенного выше кода:

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

В этом случае использование неявного формата даже лучше, но в случае, если вам снова нужно вызвать метод Java с переменными аргументами, это решение работает всегда.

person Blaisorblade    schedule 30.03.2011
comment
Я изо всех сил пытался выбрать, какой ответ выбрать ... но, наконец, я выбрал +1 здесь. - person Félix Saparelli; 31.03.2011
comment
Я согласен; этот ответ объясняет, как сделать этот код typecheck, но другой ответ объясняет, какой код вам лучше написать (как я уже сказал); так что они дополняют друг друга. В любом случае спасибо, буду признателен! - person Blaisorblade; 04.04.2011
comment
Более минимальный c: Integer. - person som-snytt; 27.07.2014

Я попробовал ваш код (с дополнительным println), и он работает в 2.8.1:

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

Его можно использовать с:

new Example().forString("hello")
h
e
l
l
o
person ssanj    schedule 30.03.2011