4

I am newbie to scala and just trying out stuff, below is what I am trying

scala> var col  = List[String]()
col: List[String] = List()

scala> List("a", "b", "c").foreach(x => x :: col)

scala> println(col)
List()

Actually, I was expecting col to contain a,b,c, what am I missing?

2
  • Prepending elements to a list does not modify the list. Commented Feb 9, 2017 at 20:51
  • I see, so how do I modify the list in this case? Commented Feb 9, 2017 at 20:53

2 Answers 2

7

You need an assignment in the foreach

scala> var col  = List[String]()
col: List[String] = List()

scala> List("a", "b", "c").foreach(x => {col = x :: col})

scala> col
res0: List[String] = List(c, b, a)

The operation x :: col simply returns a new list consisting of the element x prepended to col, the original col is not changed. You would need to reassign col to this newly generated list.

Note however that this would not typically be considered idiomatic Scala since you are using side-effects.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks @evan058, now that empty list in my example make sense to me!
@samadhi000 No problem. Just as an FYI, upvotes are the currency of thanks on SO. You can upvote multiple answers which you find useful (but you can only accept one, which you did for my post).
I would like to but looks like I don't have even privilege
Ooh, my bad. I didn't think that applied to your own questions.
6

The :: method on list does not add anything to the list, it creates a new list with the value prepended to it, you are discarding this new list instead of reassigning it to col. x => col = x :: col will add each element of your list to col. Note that col will then be List("c","b","a"), the order is reversed because you are pre-pending the elements to col.

Note that foreach returns nothing and is designed for side-effecting operations. If you simply want to transform a collection or load elements into another collection there are better methods to use.

For your specific operation, the most appropriate method is foldRight which iterates elements in reverse order, right-to-left. We want to iterate in reverse here because when you prepend elements to a list one at a time the order gets reversed.

val col = List("a", "b", "c").foldRight(List[String]())((x, acc) => x :: acc) will produce a List("a", "b", "c"). This has the advantage that we no longer need to use var to declare a mutable variable, and in fact we don' to need to declare our list ahead of time at all.

note, we could have used some special syntax to save some typing

val col = List("a", "b", "c").foldRight(List[String]())(_ :: _)

The underscores give us a shorter syntax to write function literals, I'll leave up to you to decide if it's more clear or not.

2 Comments

Thanks @puhlen for detailed explanation!
I would really like to up vote, but unfortunately I don't have an option to do so

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.