0

I've placed the following code into an object.Scala file within Eclipse, and simply want to know what the value for "x" is (it should be 3). The code won't compile if I place the value anywhere other than within the List object; at the same time, while within the List object, running the file yields no output.

package work

object Work extends App {
  // These 3 lines define a simplified List type
  sealed trait List[+A]
  case object Nil extends List[Nothing]
  case class Cons[+A](head: A, tail: List[A]) extends List[A]

  // This companion object contains basic operations for the List type
  object List {
    def sum(ints: List[Int]): Int = ints match {
      case Nil => 0
      case Cons(x,xs) => x + sum(xs)
    }

    def product(ds: List[Double]): Double = ds match {
      case Nil => 1.0
      case Cons(0.0, _) => 0.0
      case Cons(x,xs) => x * product(xs)
    }

    def apply[A](as: A*): List[A] =
      if (as.isEmpty) Nil
      else Cons(as.head, apply(as.tail: _*))

    // The next line is the value that I want to return. 
    val x = List(1,2,3,4,5) match {
      case Cons(x, Cons(2, Cons(4, _))) => x
      case Nil => 42
      case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y 
      case Cons(h, t) => h + sum(t)
      case _ => 101
     }

  }
}

I initially placed everything inside the object Work extends App in order for it to compile, as otherwise the compiler complains that I'm missing a Main method. But, to have "x" returned, I tried ditching the Work object and instead added a Main method to the expression I want to see evaluated, as follows:

def main(args: Array[String]) {
      val x = List(1,2,3,4,5) match {
        case Cons(x, Cons(2, Cons(4, _))) => x
        case Nil => 42
        case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y case Cons(h, t) => h + sum(t)
        case _ => 101
      }
}

However, I then get the following error:

List has a main method with parameter type Array[String], but work.List will not be a runnable program. Reason: companion is a trait, which means no static forwarder can be generated.

I'm not really sure what this means. I'm also pretty confused about how to properly implement a Main method. I tried to add a Main method directly under the List object, encapsulating all of List's definitions and val x, and it resulted in even more errors than above. I'm confused, and still searching the net for answers, but nothing seems to address my particular issue so far.

Any help would be greatly appreciated.

Below is my original post, containing more information, including the text for the exercise that I'm working on. To work on the exercise, I need to see how expressions evaluate. I normally work within a Scala Worksheet for precisely this reason, as I can see my results within seconds, but this particular exercise involves using a trait and companion object, and their addition has complicated things tremendously for me, as while I understand how they are used in the code, I don't know how to properly implement them.


Original Post


I put the following code into Eclipse IDE's Scala Worksheet, and then spent about two hours trying different ways to make it

  1. compile without errors, and
  2. display evaluated results on the righthand side.

I'm still struggling a lot with (2).

package fpinscala.datastructures
// The following three lines define a simplified List type and behavior
sealed trait List[+A] 
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]

// The companion object List defines basic List operations
object List { 
  def sum(ints: List[Int]): Int = ints match {
    case Nil => 0 
    case Cons(x,xs) => x + sum(xs) 
  }

  def product(ds: List[Double]): Double = ds match {
    case Nil => 1.0
    case Cons(0.0, _) => 0.0
    case Cons(x,xs) => x * product(xs)
  }

  def apply[A](as: A*): List[A] = 
    if (as.isEmpty) Nil
    else Cons(as.head, apply(as.tail: _*))
}

When I run the code above, it outputs a standard error saying that a main argument is missing. Though I'm not very clear about how the def main(args: Array[String) {} or object some_object extends App {} actually work, I do know that they allow the code to actually compile and run. At the same time, the Scala Worksheet never required that I have a Main method in the past, though in the past I also wasn't using classes or traits in the same file. I know I must be missing something.

I've tried

  • extending the List object with App
    • or adding a def main argument underneath it
  • creating an object called "Classes" for the sealed trait and adding the main argument to it
    • or extending it with App
  • creating a larger object "Worksheet" that I then added all of the following to under a def main argument
    • or extending "Worksheet" with App
  • in another Eclipse IDE file, creating a New Scala Trait, adding the trait and class code in it, and then trying to import it into the worksheet, realizing that the companion object List needs to exist in the same file
  • putting all of the above code into a different file, trying to import that file into worksheet, and trying to make any of the list operations work (the problem here is I don't actually know which type of Scala file in the Eclipse IDE the code below would belong to, object, class, or trait)

Some of these have compiled, others have not, but none of them so far have resulted in the worksheet actually producing evaluated results on the righthand side.

Here's the exercise requiring the code above that I've been trying to work on, if only I could actually see how my code evaluated:

Let’s try implementing a few different functions for modifying lists in different ways. You can place this, and other functions that we write, inside the List companion object.

3.2 Implement the function tail for removing the first element of a List. Note that the function takes constant time. What are different choices you could make in your implementation if the List is Nil? We’ll return to this question in the next chapter.

from Functional Programming in Scala.

Thanks so much for your time.

Nicholas Montaño
  • 935
  • 10
  • 24

1 Answers1

2

I am not sure why you mention that placing the val x outside the List object prevents you from compiling.

The following compiles and produces the expected output = 3

object Work extends App {
  // These 3 lines define a simplified List type
  sealed trait List[+A]
  case object Nil extends List[Nothing]
  case class Cons[+A](head: A, tail: List[A]) extends List[A]

  // This companion object contains basic operations for the List type
  object List {
    def sum(ints: List[Int]): Int = ints match {
      case Nil => 0
      case Cons(x,xs) => x + sum(xs)
    }

    def product(ds: List[Double]): Double = ds match {
      case Nil => 1.0
      case Cons(0.0, _) => 0.0
      case Cons(x,xs) => x * product(xs)
    }

    def apply[A](as: A*): List[A] =
      if (as.isEmpty) Nil
      else Cons(as.head, apply(as.tail: _*))
  }

  // The next line is the value that I want to return.
  val x = List(1,2,3,4,5) match {
    case Cons(x, Cons(2, Cons(4, _))) => x
    case Nil => 42
    case Cons(x, Cons(y, Cons(3, Cons(4, _)))) => x + y
    case Cons(h, t) => h + List.sum(t)
    case _ => 101
  }

  println(x)
}
AlexBrand
  • 11,971
  • 20
  • 87
  • 132
  • I'm not sure why either. I think I was trying so many different iterations that when I placed val x outside of the List object, something else was interfering. In any case, your code ran after I realized I was running the wrong file within Eclipse; thank you very much for your help! – Nicholas Montaño May 10 '15 at 20:02
  • Ah, I realize why. It was because that I—being new to understanding how objects and classes work—placed val x outside of the List object while simultaneously getting rid of the Work object, which led Scala to complain that it expected a class or object definition where val x was. I wasn't sure at the time how to actually solve that, but with your code showing me what properly compiling code looks like, I have a better understanding, and now have figured out another way to have my code compile as well as return a value. – Nicholas Montaño May 10 '15 at 20:14