views:

195

answers:

2

I am trying to do some examples programs in scala to get more familiar with the language, For that I am trying to re-implement some of the built in methods in Haskell, Most of these methods I am sure are also implemented in Scala too, But these are just for my practice. I think I can post some of code snippets (not all of them) to get a better way of doing things and to validate my understanding of scala. So please let me know if this is not the place to do these things.

Here is my scala implementation to get the last element of any list. Is this the right way of doing things, By using Any am I loosing the type of the object containing in the list? Is this how this kind of things implemented in scala?

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

Parameterize the type of your function and use "Nil" instead of List() like so:

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

Also, consider making it return an Option type:

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

Usage:

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

  val listOfStrings = List("one","two","three")
  assert(getLast(listOfStrings).isInstanceOf[String])
Mitch Blevins
@Mitch Blevins, Thanks for your input. The first code block is not compiling with the complaint about null converting as `T`. Second code block works good but the problem is the return types are now wrapped in some, Am doing something wrong while calling these test methods.. Here is my test method.. @Test def getLastElement(){ assertEquals (Utils1to10.getLast(List[Int]()), None) assertEquals (Utils1to10.getLast(List[Int](1)), Some(1)) assertEquals (Utils1to10.getLast(List[Int](1,2,3)), Some(3)) }I am unable to format the code above here... how can I do it:-(
Teja Kantamneni
You can not format inside comments. "null.asInstanceOf[T]" should compile.
Joa Ebert
@joa Ebert, Thanks man. But Even when we are parametrizing the return value, I am always getting `Some(x)` how to get the actual Type object like `Int` when the `List` is of type `Int`?
Teja Kantamneni
Edited the first (null-returning) function to cast to T (asInstanceOf[T]). Edited to show usage.
Mitch Blevins
A bit of pedanticry, but the name of this method should be `last`, following the Haskell convention, rather than `getLast`. Using the `get` and `set` prefixes is generally discouraged in Scala.
Daniel Spiewak
+4  A: 

Firstly, avoid the null, and especially null.asInstanceOf[T]. Observe the danger with primitives:

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

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

So the signature should either be List[T] => T, whereby last on an empty iterator throws an exception:

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

Or instead: 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  // :)
retronym