2010-02-15 67 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 // :)