2010-02-15 69 views
3

我想在斯卡拉做一些示例程序,以获得更熟悉的语言,为此,我试图重新实现一些Haskell中内置的方法,这些方法大多数我当然也可以在Scala中实现,但这些只是为了我的练习。我想我可以发布一些代码片段(不是所有的代码片断)来获得更好的做事方式并验证我对scala的理解。所以请让我知道,如果这不是做这些事情的地方。斯卡拉执行哈斯克尔最后一个方法

这是我的scala实现获取任何列表的最后一个元素。这是正确的做事方式,通过使用Any我失去了包含在列表中的对象的类型?这是如何在scala中实现这种事情?

def getLast(xs: List[Any]): Any = xs match { 
    case List()   => null 
    case x :: List() => x 
    case _ :: ys  => getLast(ys) 
    } 
+1

他们是功能,而不是方法:D – 2010-02-16 01:42:15

+1

@trinithis他们是方法。在Scala中,函数是来自'Function'的类后代的实例。 – 2010-02-16 08:24:56

+0

它的措辞是指Haskell拥有方法,而不是Scala。 – 2010-02-17 03:13:58

回答

6

参数化的函数的类型,并使用 “零”,而不是列表()像这样:

def getLast[T](xs: List[T]): T = xs match { 
    case Nil   => null.asInstanceOf[T] 
    case x :: Nil => x 
    case _ :: ys  => getLast(ys) 
    } 

此外,考虑将它返回一个选项类型:

def getLast[T](xs: List[T]): Option[T] = xs match { 
    case Nil   => None 
    case x :: Nil => Some(x) 
    case _ :: ys  => getLast(ys) 
    } 

用法:

val listOfInts = List(1,2,3) 
    assert(getLast(listOfInts).isInstanceOf[Int]) 

    val listOfStrings = List("one","two","three") 
    assert(getLast(listOfStrings).isInstanceOf[String]) 
+0

@Mitch Blevins,谢谢你的输入。第一个代码块不会将关于空转换的投诉编译为“T”。第二个代码块工作良好,但问题是返回类型现在包裹在一些,我做错了,而调用这些测试方法..这里是我的测试方法.. @Test def getLastElement(){ assertEquals(Utils1to10.getLast (List [Int]()),None) assertEquals(Utils1to10.getLast(List [Int](1)),Some(1)) assertEquals(Utils1to10.getLast(List [Int] ),Some(3)) } 我无法格式化上面的代码......我该怎么做:-( – 2010-02-15 19:46:06

+0

你不能格式化内部注释,“null.asInstanceOf [T]”应该编译。 – 2010-02-15 20:25:18

+0

@joa Ebert,谢谢你,但即使我们正在参数化返回值,我总是会得到'Some(x)'当List'类型为'Int'时如何获得像'Int'这样的实际Type对象。 ? – 2010-02-15 20:44:13

5

首先,避免null,尤其是null.asInstanceOf[T]。观察与原语的危险:

scala> null.asInstanceOf[Int] 
res19: Int = 0 

scala> null.asInstanceOf[Boolean] 
res20: Boolean = false 

所以签名要么是List[T] => T,从而last在一个空迭代器抛出一个异常:

def last[T](ts: List[T]): T = ts match {  
    case Nil => throw new NoSuchElementException 
    case t :: Nil => t       
    case t :: ts => last(ts)      
} 

或改为:List[T] => Option[T]

def lastOption[T](ts: List[T]): Option[T] = ts match { 
    case Nil => None         
    case t :: Nil => Some(t)       
    case t :: ts => lastOption(ts)      
} 

def lastOption1[T](ts: List[T]): Option[T] = ts.reverse.headOption 

def lastOptionInScala28[T](ts: List[T]): Option[T] = ts.lastOption // :)