【问题标题】:Is there there any difference or reason to prefer one of these function signatures?是否有任何区别或理由更喜欢这些函数签名之一?
【发布时间】:2013-08-13 02:02:12
【问题描述】:

我不认为有任何区别,也没有理由偏爱其中一个,但想检查一下...

def length(l: List[Any])
def length[T](l: List[T])

【问题讨论】:

    标签: scala types type-signature


    【解决方案1】:

    你也可以这样写:

    def length(l: List[_])
    

    现在,关于您的问题,List[Any] 确实会接受任何List,但如果您尝试过Set[Any],它将无法正常工作!例如,尝试将 Set[Int] 传递给它:

    scala> def length(s: Set[Any]) = s.size
    length: (s: Set[Any])Int
    
    scala> val set = Set(1, 2, 3)
    set: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
    
    scala> length(set)
    <console>:10: error: type mismatch;
     found   : scala.collection.immutable.Set[Int]
     required: Set[Any]
    Note: Int <: Any, but trait Set is invariant in type A.
    You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
                  length(set)
                         ^
    

    List 是协变的,这使得这成为可能,但并非每个参数化类都是协变的。不过,您的参数化版本或上述版本都可以使用。

    我想不出任何理由偏爱其中一个,但我宁愿在不需要时不参数化某些东西。如果不出意外,它会对编译速度产生轻微的积极影响。

    【讨论】:

      【解决方案2】:

      如果您只想要任何List 的长度,对您来说没有区别。
      但是,如果您想要对该列表中的元素进行操作,则有。

      val l = List(1, 2, 3, 4)
      def secondElementAny(l: List[Any]) = l.tail.head
      def secondElementGen[A](l : List[A]) = l.tail.head
      

      给出这两个函数和列表,我们将期望从List 获得2

      val secondAny = secondElementAny(l)
      val secondGen = secondElementGen(l)
      

      如果我们将这些值打印到控制台,我们可以发现没有区别,但是如果我们尝试将它们转换为 Float,例如,我们会得到一个错误。 secondAny.toFloat 会告诉我们, secondAny 是 Any 的类型,我们不能在 Any 上使用函数 toFloat
      相比之下,secondGen.toFloat 会给我们一个Float 值。

      这样做的原因是,编译器将完整的签名近似如下。

      def secondElementAny(l: List[Any]): Any = l.tail.head
      def secondElementGen[A](l: List[A]): A = l.tail.head
      

      你可以看到第一个函数的返回类型是Any,所以我们总是会得到一个Any,而第二个函数的返回类型取决于List的类型。我们将获得该类型的元素。这是类型安全的。

      【讨论】:

        【解决方案3】:

        有区别:

        def head_1(l: List[Any]) = {
          l.head
        }
        
        def head_2[T](l: List[T]) = {
          l.head
        }
        
        // Doesn't compile, head_1 returns Any
        // head_1(List(1,2,3)) > 1
        
        head_2(List(1,2,3)) > 1                   //> res0: Boolean = false
        

        【讨论】:

        • 不过,通过提供这些特定的方法主体,您已经改变了问题中的签名。
        • @ChristopherMartin 它确实回答了我的问题,因为它给出了在某些情况下更喜欢其中一个的理由(即代码无法编译!)
        • head_1 会编译。它返回一个正确的 Any,但它可以编译。
        • @TGrottker &gt; 1 无法编译为 Any 没有方法 &gt;
        猜你喜欢
        • 2011-05-06
        • 2011-03-18
        • 2011-06-18
        • 2012-07-06
        • 1970-01-01
        • 2015-07-06
        • 1970-01-01
        • 2011-11-03
        • 1970-01-01
        相关资源
        最近更新 更多