【问题标题】:define a function with tuples用元组定义一个函数
【发布时间】:2011-09-24 18:09:06
【问题描述】:

如何定义一个接受所有元组(1 到 22)作为参数的函数,我的想法如下:

def foo (v=Tuple) =...

foo((1,2))
foo((1,2,3))

编辑:

回答评论:我实际上是在尝试创建一个张量类,它是一组值和一组索引。索引可以是协变的和/或逆变的(参见Wikipedia1Wikipedia2)。我想要一个像Tensor((1,2),(3,4),values) 这样的特殊语法,它将创建一个带有values 的张量、两个长度为(2,3) 的协变索引和两个长度为(3,4) 的逆变索引。所以使用这种语法我也可以写Tensor((1,2,3),3,values)(带有隐式 Int=>Tuple1)。

我同意Tuples 不适合这个,最好使用Lists。但是语法不是那么好...

【问题讨论】:

标签: scala


【解决方案1】:

这真的是isn't what tuples are for(参见cmets 和答案here)。元组用于执行诸如从方法返回多个值之类的操作,而在 Java 中,您必须创建一个轻量级类。如果你有任意数量的元素,你应该使用一个集合。

【讨论】:

  • 经过澄清,我不确定这个答案是否真的适用。他并没有尝试将集合方法应用于元组——他只是想为调用者提供一个方便的 API。
【解决方案2】:

包括元组在内的所有案例类都扩展了scala.Product,但不幸的是,没有专门针对元组的标记特征,因此有人可以将普通案例类偷偷带入您的方法中。当然,没有办法以统一的方式处理所有 arities 并且仍然是类型安全的,但是您可以使用 productElement(n: Int) 提取第 n 个值,或使用 productIterator 迭代所有值。

但是...这里是异端,但是您是否考虑过超载? :)

【讨论】:

    【解决方案3】:

    没有专门针对元组的特征,但您可以使用类型类方法as demonstrated in this answer

    如果您的目标确实是拥有一个 List 但允许调用者传入元组(为了方便),您可以修改该解决方案,以便类型类生成一个 List 而不是 Product。

    简而言之,这个想法是您提供从调用者可以传递的类型到您实际要使用的类型的隐式转换:

    def foo(x: IndexList) = x.indices
    
    sealed case class IndexList(indices: List[Int])
    
    object IndexList {
       implicit def val2indices(i: Int) = IndexList(List(i))
       implicit def tuple2toIndices(t: (Int, Int)): IndexList = 
          product2indices(t)
       // etc
       implicit def list2indices(l: List[Int]) = IndexList(l)
    
       private def product2indices(p: Product) = 
          IndexList(p.productIterator.toList.asInstanceOf[List[Int]])
    }
    

    然后,您可以使用已提供转换的任何类型调用您的方法:

    foo(1)
    foo((2,3))
    foo(List(1,2,3))
    

    【讨论】:

      【解决方案4】:

      看看这个。它实际上比我预期的要好;)

      scala> def f[T <: Product](x: T) = x
      f: [T <: Product](x: T)T
      
      scala> f(1)
      <console>:9: error: inferred type arguments [Int] do not conform to method f's type parameter bounds [T <: Product]
      
      scala> f(1, "2") // you don't even need the extra parenthesis
      res0: (Int, java.lang.String) = (2,3)
      
      scala> f(1, "2", BigInt("3"))
      res1: (Int, java.lang.String, scala.math.BigInt) = (1,2,3)
      

      【讨论】:

        【解决方案5】:

        您可能想要使用的是 HList,而不是元组。 HList(异构列表)基本上是一个任意长度的类型化元组。

        在 scala 中有几个 HList 的例子(它们不是标准库的一部分)

        【讨论】:

          【解决方案6】:

          为您的用户提供方便的 API 的另一种方法(implicit conversion 除外)是使用带有可变参数的多个参数列表:

          def tensor(cov: Int*)(contrav: Int*)(values: Int*) = // ...
          

          你的例子会写出来

          tensor(1,2)(3,4)(values)
          tensor(1,2,3)(3)(values)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-23
            • 2017-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多