Как мне неявно преобразовать кортежи в вектор в Scala

StackOverflow https://stackoverflow.com/questions/707162

  •  22-08-2019
  •  | 
  •  

Вопрос

Я хочу иметь возможность неявно преобразовывать кортежи чисел (целые числа и double) в векторный объект.

Предполагая векторный класс с методом +

case class Vector(x: Double, y:Double){
  def + (v:Vector)= new Vector(x+v.x,y+v.y)
} 

Моя цель состоит в том, чтобы заставить следующий код работать.

val vec = (1,2)+(.5,.3) // vec == Vector(1.5,2.3)

Я могу заставить это работать для Int со следующим

implicit def int2vec(t:Tuple2[Int,Int])=new Vector(t._1,t._2)
val vec = (1,2)+(3,4) // vec == Vector(4.0,6.0)

Но это не удается, когда я добавляю преобразование для double

implicit def int2vec(t:Tuple2[Int,Int])=new Vector(t._1,t._2)
implicit def double2vec(t:Tuple2[Double,Double])=new Vector(t._1,t._2)
val a = (1,2)
val b = (.5,.3)
val c = (1,1)+b // vec = Vector(1.5,1.3)
val d = (1,2)+(.3,.5) // compile error: wrong number of arguments
val e = (1,2)+((.3,.5)) // compile error: type mismatch

Пытаюсь просто удвоить количество сахара по рецепту Андри

implicit def double2vec(t:Tuple2[Double,Double])=new Vector(t._1,t._2)
val a = (.5,.3)
val b = (1,1)+a // type mismatch found:(Double,Double) required:String 

Что мне нужно сделать, чтобы это заработало?

Это было полезно?

Решение

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

В частности, я предлагаю вам дать следующее определение:

val V = Vector

И тогда все ваши примеры будут работать так, как вы ожидали, без каких-либо подтекстов, магии или загадочных сообщений об ошибках, и за счет использования всего одного символа на вектор.

val a = V(1,2)+V(.5,.3)
val b = V(1,2)+V(3,4)
val c = V(1,2)
val d = V(.5,.3)
val e = V(1,1)+b
val f = V(1,2)+V(.3,.5)
val g = V(.5,.3)
val h = V(1,1)+a

Это не совсем тот синтаксис, который вам нужен, но поверьте мне, это избавит вас от лишних хлопот в долгосрочной перспективе.

Другие советы

Эти неявные преобразования неоднозначны, и поэтому Scala не будет использовать ни одно из них.Это причина, по которой последние строки не будут оцениваться.

Одним из способов исправить это было бы оставить int2vec полностью отсутствует, хотя это означает, что все целые числа сначала будут неявно преобразованы в двойные.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top