Scala помещает приоритет на неявное преобразование по “естественным” операциям … Почему? Действительно ли это - ошибка? Или я делаю что-то не так?

Этот простой тест, конечно, работает как ожидалось:

scala> var b = 2
b: Int = 2

scala> b += 1   

scala> b
res3: Int = 3

Теперь я приношу это в объем:

class A(var x: Int) { def +=(y:Int) { this.x += y } }
implicit def int2A(i:Int) : A = new A(i)             

Я определяю новый класс и + = операция на нем и удобное неявное преобразование в течение тех времен, когда я хочу добавить Интервал к Международному значению A.

Я никогда не ожидал, что это будет влиять на способ, которым ведут себя мои регулярные Международные операции, когда "A" класс нисколько не является частью выражения.

Но это делает:

scala> var b:Int = 0
b: Int = 0

scala> b += 1

scala> b  
res29: Int = 0

scala> b += 2

scala> b
res31: Int = 0

Что, кажется, происходит, вот то, что b:Int неявно преобразовывается в "A", который не связывается ни с какой переменной, и затем + = вызывается на него, отбрасывая результаты.

Scala, кажется, дает высокому приоритету неявное преобразование по естественному + = поведение (волшебство компилятора, не фактический метод), который уже определяется к Ints. Здравый смысл, а также фон C++ говорит мне, что implicits должен только быть вызван как последнее прибежище, когда компиляция иначе перестала бы работать. Это приводит к нескольким вопросам...

  • Почему? Действительно ли это - ошибка? Это дизайном?
  • Существует ли обходное решение (кроме не использования "+ =" для моего DSL's "+ =" операция)?

Спасибо

9
задан Alex R 22 April 2010 в 21:00
поделиться

5 ответов

Даже несмотря на объяснение Истсана, похоже, что это ошибка, и он должен попробовать преобразование b = b + 1 перед попыткой неявного преобразования для + = .

Задайте этот вопрос списку рассылки пользователей scala по электронной почте (скрыто) или посетив n4.nabble.com/Scala-User-f1934582.html. Если это ошибка, ее заметят и исправят.

1
ответ дан 4 December 2019 в 08:51
поделиться

Как отмечали другие, Int не может иметь + = "метод", потому что Int неизменяем. Вместо этого происходит то, что x + = 1 рассматривается как краткая форма для x = x + 1, но только если нет метода с именем + =, который определен для типа. Таким образом, разрешение метода имеет приоритет.

Учитывая, что Scala позволяет вам определять методы + =, а также позволяет делать + = для переменных, можем ли мы изменить их приоритет? Т.е. сначала попробуйте расширенный + =, и только если это не поможет, найдите метод с именем + =?

Теоретически да, но я утверждаю, что это было бы хуже, чем текущая схема. Практически нет. В библиотеке коллекций Scala есть много типов, которые определяют как метод + для неразрушающего сложения , так и метод + = для деструктивного сложения. Если бы мы поменяли приоритет, вызов типа

  myHashTable += elem

расширился бы до

  myHashTable = myHashTable + elem

. Таким образом, он построил бы новую хеш-таблицу и присвоил ее обратно переменной, вместо простого обновления элемента. Не очень разумный поступок ...

13
ответ дан 4 December 2019 в 08:51
поделиться

Кажется, что Scala дает высокий приоритет неявному преобразованию над естественным + = , которое уже определено для Инт с.

О какой версии Scala вы говорите? Я не знаю ни одной версии, в которой есть метод + = в Int . Конечно, ни одна из все еще поддерживаемых версий не поддерживает, это должна быть какая-то действительно древняя версия, которая у вас есть.

И поскольку нет + = в Int , но вы вызываете метод + = в Int , Scala пытается удовлетворить это ограничение типа с помощью неявного преобразования.

1
ответ дан 4 December 2019 в 08:51
поделиться

Из «Программирование на Scala», глава 17:

Когда вы пишете a + = b, а a не поддерживает метод с именем + =, Scala будет пытаться интерпретировать его как = а + б.

Класс Int не содержит метода + = . Однако класс A предоставляет метод + = . Это могло вызвать неявное преобразование из Int в A .

6
ответ дан 4 December 2019 в 08:51
поделиться

Я не думаю, что это ошибка. На самом деле Int имеет только метод "+", но не имеет " + = "метод. b + = 1 преобразуется в b = b + 1 во время компиляции, если не существует другого неявного метода, имеющего метод" + = ".

3
ответ дан 4 December 2019 в 08:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: