Почему в Scala не существует Tuple1 Literal для одноэлементных кортежей? - PullRequest
12 голосов
/ 24 июня 2011

Python имеет (1,) для одного элемента кортежа. В Scala (1,2) работает для Tuple2(1,2), но мы должны использовать Tuple1(1), чтобы получить кортеж из одного элемента. Это может показаться небольшой проблемой, но при разработке API-интерфейсов, ожидающих, что продукт будет проблематичным для пользователей, передающих отдельные элементы, поскольку им приходится писать Tuple1 (1).

Возможно, это небольшая проблема, но главное преимущество Scala - больше печатать с меньшим количеством печатания. Но в этом случае кажется, что больше печатать с большим количеством печатать.

Пожалуйста, скажите мне: 1) Я пропустил это, и оно существует в другой форме, или 2) Он будет добавлен в будущую версию языка (и они будут принимать исправления).

Ответы [ 3 ]

4 голосов
/ 25 июня 2011

Вы можете определить неявное преобразование:

implicit def value2tuple[T](x: T): Tuple1[T] = Tuple1(x)

Неявное преобразование будет применяться, только если статический тип аргумента еще не соответствует типу параметра метода.Предполагая, что ваш метод принимает Product аргумент

def m(v: Product) = // ...

, преобразование будет применяться к значению, не являющемуся продуктом, но не применяется к Tuple2,например.Предупреждение: все классы дел расширяют черту Product, поэтому преобразование также не будет применяться к ним .Вместо этого элементы product будут параметрами конструктора класса case.

Product является наименьшей верхней границей классов TupleX, но вы можете использовать класс типов, если хотите применить неявное преобразование Tuple1 ко всем не кортежам:

// given a Tupleable[T], you can call apply to convert T to a Product
sealed abstract class Tupleable[T] extends (T => Product)
sealed class ValueTupler[T] extends Tupleable[T] { 
   def apply(x: T) = Tuple1(x) 
}
sealed class TupleTupler[T <: Product] extends Tupleable[T] { 
   def apply(x: T) = x 
}

// implicit conversions
trait LowPriorityTuple {
   // this provides a Tupleable[T] for any type T, but is the 
   // lowest priority conversion
   implicit def anyIsTupleable[T]: Tupleable[T] = new ValueTupler
}
object Tupleable extends LowPriorityTuple {
   implicit def tuple2isTuple[T1, T2]: Tupleable[Tuple2[T1,T2]] = new TupleTupler
   implicit def tuple3isTuple[T1, T2, T3]: Tupleable[Tuple3[T1,T2,T3]] = new TupleTupler
   // ... etc ...
}

Вы можете использовать этот класс типов в своем API следующим образом:

def m[T: Tupleable](v: T) = { 
   val p = implicitly[Tupleable[T]](v) 
   // ... do something with p
}

Если ваш метод возвращает продукт, вы можете увидеть, как применяются преобразования:

scala> def m[T: Tupleable](v: T) = implicitly[Tupleable[T]](v)
m: [T](v: T)(implicit evidence$1: Tupleable[T])Product

scala> m("asdf") // as Tuple1
res12: Product = (asdf,)

scala> m(Person("a", "n")) // also as Tuple1, *not* as (String, String)
res13: Product = (Person(a,n),)

scala> m((1,2)) // as Tuple2
res14: Product = (1,2)
3 голосов
/ 24 июня 2011

Конечно, вы можете добавить неявное преобразование в свой API:

implicit def value2tuple[A](x: A) = Tuple1(x)

Мне кажется странным, что Tuple1.toString включает в себя запятую:

scala> Tuple1(1)
res0: (Int,) = (1,)
2 голосов
/ 24 июня 2011

Python не является статически типизированным, поэтому кортежи там действуют скорее как коллекции фиксированного размера. Это не относится к Scala, где каждый элемент кортежа имеет отдельный тип. Кортежи в Scala не используются так же, как в Python.

...