Reputation: 113
I am stumped on something pretty basic in Scala. I'm working my way through the book "Atomic Scala." I'm not a complete beginner to programming, but what experience I do have is pretty surface-level. No actual development experience, just tinkering around with string manipulation and things at that level.
In the book, one of the exercises (in a section on Parameterized Types) is to define a method which takes a vector as input and gives a list as output, where the list's elements are the same as the vector's elements. The given vector could be of any length.
I don't know of a way to do this without a for loop and without thinking of the list as (at least at first) mutable.
Here's what I tried:
def explicit(v:Vector[Double]):List[Double] = {
var l = List()
for (i <- v) {
l = l :+ i
}
l
}
but it appears there's something wrong with that fourth line. It kicks out an error message.
I have a feeling there's some cool thing you can do without a for loop where you just say right off the bat "val l = List(~~~insert something cool here with rockets or something~~~) but either the book hasn't covered this yet or I just haven't figured it out.
As you can see, I'm at a very basic level here, so please do your best to explain it like I'm five. ;)
Edited to add: I looked ahead a little bit, and it looks like a couple of chapters later I'll be learning about the "map" method, which if I'm skimming accurately, would provide a solution to this problem. But that's later in the book. Any idea how it can be done without map?
Upvotes: 1
Views: 5119
Reputation: 15086
Looks more like an exercise in recursion and/or type parameters:
def parameterized[T](v: Vector[T]): List[T] = v match {
case head +: tail => head :: parameterized(tail)
case _ => Nil
}
Or with tail recursion:
def parameterized[T](v: Vector[T]): List[T] = {
def toList[T](v: Vector[T], l: List[T]): List[T] = v match {
case init :+ last => toList(init, last :: l)
case _ => l
}
toList(v, Nil)
}
Upvotes: 1
Reputation: 7476
List
in Scala is immutable, "modifying" a List
actually yield a new instance of List
.
map
is a very useful function on List
but will not help you, it does not change the container, only the contained values.
I don't really understand the point of your exercise, turning a Vector
into a List
is as simple as calling toList
on the Vector
.
scala> val v= Vector(1,2,3)
v: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)
scala> v.toList
res0: List[Int] = List(1, 2, 3)
Edit after 1st comment: yeah, it wouldn't make sense to give an exercise to simply call toList
:) Hard to really know what's expected, what is the main topic of the chapter/section?
Another way is: List(Vector(1,2,3):_*)
. @Rex Kerr answer is good too.
Upvotes: 7
Reputation: 167931
First, your existing code doesn't work because var l = List()
creates an empty list with Nothing
type. That kinda makes sense, because there's nothing in it, but when you want to put something in, it's not going to work very well. Do it like so:
var l = List[Double]()
This still isn't a very good way to do it, though, because each time you add to the end of a list you have to rebuild the whole preceding part! Adding to the head doesn't require any rebuilding, though, so you really need to add your elements in reverse order if you can. For a Vector
, it turns out that the best way to go in reverse order in a context like this is reverseIterator
. So
for (i <- v.reverseIterator) l = i :: l
And this still isn't the best way to do things unless it's just as an exercise because Vector
has a toList
method, which does the obvious thing.
Upvotes: 0