为什么 Scala 中没有用于单元素元组的 Tuple1 Literal? [英] Why is there no Tuple1 Literal for single element tuples in Scala?

查看:15
本文介绍了为什么 Scala 中没有用于单元素元组的 Tuple1 Literal?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 具有用于单个元素元组的 (1,).在 Scala 中,(1,2) 适用于 Tuple2(1,2) 但我们必须使用 Tuple1(1) 来获取单个元素元组.这似乎是一个小问题,但是对于传递单个元素的用户来说,设计期望产品的 API 是一件痛苦的事情,因为他们必须编写 Tuple1(1).

Python has (1,) for a single element tuple. In Scala, (1,2) works for Tuple2(1,2) but we must use Tuple1(1) to get a single element tuple. This may seem like a small issue but designing APIs that expect a Product is a pain to deal for users that are passing single elements since they have to write Tuple1(1).

也许这是一个小问题,但 Scala 的一个主要卖点是输入更多,输入更少.但在这种情况下,它似乎是更多的打字.

Maybe this is a small issue, but a major selling point of Scala is more typing with less typing. But in this case it seems it's more typing with more typing.

请告诉我:1)我错过了这个,它以另一种形式存在,或者2) 它将被添加到该语言的未来版本中(并且他们将接受补丁).

Please tell me: 1) I've missed this and it exists in another form, or 2) It will be added to a future version of the language (and they'll accept patches).

推荐答案

可以定义隐式转换:

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

仅当参数的静态类型不符合方法参数的类型时,才会应用隐式转换.假设您的方法采用 Product 参数

The implicit conversion will only apply if the argument's static type does not already conform to the method parameter's type. Assuming your method takes a Product argument

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

转换将应用于非产品值,但应用于Tuple2.警告:所有案例类都扩展了 Product 特征,因此转换也不适用于它们.相反,产品元素将是案例类的构造函数参数.

the conversion will apply to a non-product value but will not apply to a Tuple2, for example. Warning: all case classes extend the Product trait, so the conversion will not apply to them either. Instead, the product elements will be the constructor parameters of the case class.

ProductTupleX 类的最小上限,但如果要将隐式 Tuple1 转换应用于所有非元组,则可以使用类型类:

Product is the least upper bound of the TupleX classes, but you can use a type class if you want to apply the implicit Tuple1 conversion to all non-tuples:

// 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 中使用此类型类:

You can use this type class in your API as follows:

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

如果您的方法返回产品,您可以看到转换是如何应用的:

If you have your method return the product, you can see how the conversions are being applied:

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)

这篇关于为什么 Scala 中没有用于单元素元组的 Tuple1 Literal?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆