4

和有什么区别

def drop1[A](l: List[A]) = l.tail

def drop1(l: List[Int]) = l.tail

假设用法看起来像

drop1(List(1,2,3))

?

什么时候应该使用其中一种,为什么?虽然我可以理解第二个示例,但我并不真正理解第一个示例的目的。

4

4 回答 4

7

真的很简单。您的第一个示例是指泛型的概念。

泛型有一个简单的目标,使某些方法通用,例如不依赖于类型。

让我们看看这个简单的例子。假设我想drop1List.

我可以为每种类型写一个:(缓慢,重复):

def drop1(l: List[Int]): List[Int] = l.tail // this only works for Int

def drop1(l: List[String]): List[String] = l.tail // this only works for String 

您可以看到如何为每种类型编写上述内容。为了克服这个问题,你有泛型:

def drop1[A](l: List[A]): List[A] = l.tail // this works for any given type.

这实质上是说:无论列表中包含的类型是什么,都给我尾巴。而不是为几乎无限数量的类型编写数千个变体drop1,我只需要编写一个。

现在在 Scala 中,您的实现最好通过以下方式完成:

implicit class ListOps[A](val l: List[A]) extends AnyVal {
   def drop1: List[A] = l match {
     case head :: tail => tail
     case Nil => Nil
   }
}
// you can now have
List(1, 2, 3).drop1

重命名众所周知的库方法通常也是一个坏主意。一个tail操作是不安全的,一个drop是安全的。您所造成的只是混乱,因为有一个默认drop方法。

List(1, 2, 3) drop 1
于 2014-01-14T14:11:11.837 回答
3

简而言之——一些操作不依赖于特定类型并且可以被抽象。数苹果和数橙子本质上是相同的操作。如果您要重用算法,那么将某些类型抽象出来而不是编写会更聪明

def countOranges(xs: List[Orange]) = { some code } 
def countApples(xs: List[Apple]) = { the very same code }
于 2014-01-14T14:26:00.500 回答
0

我有点晚了,如果您对 Java 中的泛型有一个想法,那么可以在这里进行类比:-

Java --> 泛型类的对象可以在方法参数中传递。

class Test<T> {
    // An object of type T is declared
    T obj;
    Test(T obj) {  this.obj = obj;  }  // constructor
    // some other methods in class 
}

Test<String> testobj = new Test<String>();

public void function(testobj){ 
// do something with testobj 
}

Scala --> 通用参数函数在 Scala 中的工作方式相同。这里,[A] 定义了 scala 中的泛型 Type

def drop1[A](l: List[A]) = l.tail

上述功能的用法:-

scala>drop1(List(1,2,3))   // output List(2, 3)
scala>drop1(List(1.0,2.0,3.0)) // output List(2.0, 3.0)
scala>drop1(List('a','b','c'))  // output List(b, c)

说明:- 只需传递任何类型的列表,它就像一个魅力。语法如下:-

def function[Type](param:Type):Type = {do something}
于 2018-06-26T17:16:10.077 回答
0
//snippet to explain scala parametric polymorphism

object MethodParametricPolymorphism {
  //parametric polymorphism is similar/same as of java generics
  def countOranges(oranges : List[Orange]) = oranges.size;
  def countApples(apples : List[Apple]) = apples.size
  //if algo is same then paramatric polymorphism can be used
  def count[A](items : List[A]) = items.size

  val oranges : List[Orange] =  List( new Orange(1.1))
  val apples : List[Apple] =  List( new Apple(2.1), new Apple(2.2))

  countOranges(oranges);
  countApples(apples);
  //using polymorphic typed method
  count(oranges);
  count(apples);

  case class Orange ( weight: Double)
  case class Apple ( weight: Double)
 }
于 2018-09-26T14:53:20.417 回答