This describes the problem pretty well:
scala> var l2 = List(1,2,3)
l2: List[Int] = List(1, 2, 3)
scala> l2(2) = 55
<console>:10: error: value update is not a member of List[Int]
l2(2) = 55
^
scala.List is immutable, meaning you cannot update it in place. If you want to create a copy of your List which contains the updated mapping, you can do the following:
val updated = l2.updated( 2, 55 )
There are mutable ordered sequence types as well, in scala.collection.mutable, such as Buffer types which seem more like what you want. If you try the following you should have more success:
scala> import scala.collection._
import scala.collection._
scala> val b = mutable.Buffer(1,2,3)
b: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)
scala> b(2) = 55
scala> b
res1: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 55)
Edit: Just to note that some other answers have mentioned that you should use a "mutable List type" - this is true, but "List" in Scala just refers to the single-linked list, whereas in Java it's generally used for any ordered, random-access collection. There is also a DoubleLinkedList, which is more like a Java LinkedList, and a MutableList, which is a type used for the internals of some other types.
Generally speaking what you probably want in Scala is a Buffer for this job; especially since the default implementation is an ArrayBuffer, which is pretty close to being the same as ArrayList, most peoples' default, in Java.
If you ever want to find out what the closest "mapping" of a Java collections interface to the Scala world is, though, the easiest thing to do is probably just check what JavaConversions does. In this case you can see the mapping is to Buffer:
scala.collection.mutable.Buffer <=> java.util.List
The List you are creating is immutable.
scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> l.getClass
res3: java.lang.Class[_] = class scala.collection.immutable.$colon$colon
Use a mutable List instead and you should be fine.
But you can wrap the assignment in an implicit if you don't like updated
implicit class RichList[A](l: List[A]) {
def update(which: Int, what: A): List[A] = {
l.updated(which, what)
}
}
val l = List(1, 2, 3)
val l2 = l(2) = 55
List(1, 2, 55)
Your problem is that Lists in scala are immutable, you need to use a mutable list instead.
Import scala.collection.mutable.Queue and use that instead. Queue is a MutableList, so it should do what you want.
Lists are immutable in scala. But if you want to replace an element in a List you can use "updated" method like this
val num:List[Int]=List(1,5,4,7,8,2,10)
num=num.updated(0,22)
Since Lists are immutable,this creates a copy of the first List called num(as we assigned the new list to 'num') by replacing 0th element to 22.So the genaral updated method is
listname.updated(index,value)
Related
How can I convert a list with (say) 3 elements into a tuple of size 3?
For example, let's say I have val x = List(1, 2, 3) and I want to convert this into (1, 2, 3). How can I do this?
You can do it using scala extractors and pattern matching (link):
val x = List(1, 2, 3)
val t = x match {
case List(a, b, c) => (a, b, c)
}
Which returns a tuple
t: (Int, Int, Int) = (1,2,3)
Also, you can use a wildcard operator if not sure about a size of the List
val t = x match {
case List(a, b, c, _*) => (a, b, c)
}
You can't do this in a typesafe way. Why? Because in general we can't know the length of a list until runtime. But the "length" of a tuple must be encoded in its type, and hence known at compile time. For example, (1,'a',true) has the type (Int, Char, Boolean), which is sugar for Tuple3[Int, Char, Boolean]. The reason tuples have this restriction is that they need to be able to handle a non-homogeneous types.
an example using shapeless :
import shapeless._
import syntax.std.traversable._
val x = List(1, 2, 3)
val xHList = x.toHList[Int::Int::Int::HNil]
val t = xHList.get.tupled
Note: the compiler need some type informations to convert the List in the HList that the reason why you need to pass type informations to the toHList method
Shapeless 2.0 changed some syntax. Here's the updated solution using shapeless.
import shapeless._
import HList._
import syntax.std.traversable._
val x = List(1, 2, 3)
val y = x.toHList[Int::Int::Int::HNil]
val z = y.get.tupled
The main issue being that the type for .toHList has to be specified ahead of time. More generally, since tuples are limited in their arity, the design of your software might be better served by a different solution.
Still, if you are creating a list statically, consider a solution like this one, also using shapeless. Here, we create an HList directly and the type is available at compile time. Remember that an HList has features from both List and Tuple types. i.e. it can have elements with different types like a Tuple and can be mapped over among other operations like standard collections. HLists take a little while to get used to though so tread slowly if you are new.
scala> import shapeless._
import shapeless._
scala> import HList._
import HList._
scala> val hlist = "z" :: 6 :: "b" :: true :: HNil
hlist: shapeless.::[String,shapeless.::[Int,shapeless.::[String,shapeless.::[Boolean,shapeless.HNil]]]] = z :: 6 :: b :: true :: HNil
scala> val tup = hlist.tupled
tup: (String, Int, String, Boolean) = (z,6,b,true)
scala> tup
res0: (String, Int, String, Boolean) = (z,6,b,true)
Despite the simplicity and being not for lists of any length, it is type-safe and the answer in most cases:
val list = List('a','b')
val tuple = list(0) -> list(1)
val list = List('a','b','c')
val tuple = (list(0), list(1), list(2))
Another possibility, when you don't want to name the list nor to repeat it (I hope someone can show a way to avoid the Seq/head parts):
val tuple = Seq(List('a','b')).map(tup => tup(0) -> tup(1)).head
val tuple = Seq(List('a','b','c')).map(tup => (tup(0), tup(1), tup(2))).head
FWIW, I wanted a tuple to initalise a number of fields and wanted to use the syntactic sugar of tuple assignment.
EG:
val (c1, c2, c3) = listToTuple(myList)
It turns out that there is syntactic sugar for assigning the contents of a list too...
val c1 :: c2 :: c3 :: Nil = myList
So no need for tuples if you've got the same problem.
If you are very sure that your list.size<23 use it:
def listToTuple[A <: Object](list:List[A]):Product = {
val class = Class.forName("scala.Tuple" + list.size)
class.getConstructors.apply(0).newInstance(list:_*).asInstanceOf[Product]
}
listToTuple: [A <: java.lang.Object](list: List[A])Product
scala> listToTuple(List("Scala", "Smart"))
res15: Product = (Scala,Smart)
You can't do this in a type-safe way. In Scala, lists are arbitrary-length sequences of elements of some type. As far as the type system knows, x could be a list of arbitrary length.
In contrast, the arity of a tuple must be known at compile time. It would violate the safety guarantees of the type system to allow assigning x to a tuple type.
In fact, for technical reasons, Scala tuples were limited to 22 elements, but the limit no longer exists in 2.11 The case class limit has been lifted in 2.11 https://github.com/scala/scala/pull/2305
It would be possible to manually code a function that converts lists of up to 22 elements, and throws an exception for larger lists. Scala's template support, an upcoming feature, would make this more concise. But this would be an ugly hack.
This can also be done in shapeless with less boilerplate using Sized:
scala> import shapeless._
scala> import shapeless.syntax.sized._
scala> val x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> x.sized(3).map(_.tupled)
res1: Option[(Int, Int, Int)] = Some((1,2,3))
It's type-safe: you get None, if the tuple size is incorrect, but the tuple size must be a literal or final val (to be convertible to shapeless.Nat).
Using Pattern Matching:
val intTuple = List(1,2,3) match {case List(a, b, c) => (a, b, c)}
2015 post.
For the Tom Crockett's answer to be more clarifying, here is a real example.
At first, I got confused about it. Because I come from Python, where you can just do tuple(list(1,2,3)).
Is it short of Scala language ? (the answer is -- it's not about Scala or Python, it's about static-type and dynamic-type.)
That's causes me trying to find the crux why Scala can't do this .
The following code example implements a toTuple method, which has type-safe toTupleN and type-unsafe toTuple.
The toTuple method get the type-length information at run-time, i.e no type-length information at compile-time, so the return type is Product which is very like the Python's tuple indeed (no type at each position, and no length of types).
That way is proned to runtime error like type-mismatch or IndexOutOfBoundException. (so Python's convenient list-to-tuple is not free lunch. )
Contrarily , it is the length information user provided that makes toTupleN compile-time safe.
implicit class EnrichedWithToTuple[A](elements: Seq[A]) {
def toTuple: Product = elements.length match {
case 2 => toTuple2
case 3 => toTuple3
}
def toTuple2 = elements match {case Seq(a, b) => (a, b) }
def toTuple3 = elements match {case Seq(a, b, c) => (a, b, c) }
}
val product = List(1, 2, 3).toTuple
product.productElement(5) //runtime IndexOutOfBoundException, Bad !
val tuple = List(1, 2, 3).toTuple3
tuple._5 //compiler error, Good!
you can do this either
via pattern-matching (what you do not want) or
by iterating through the list and applying each element one by one.
val xs: Seq[Any] = List(1:Int, 2.0:Double, "3":String)
val t: (Int,Double,String) = xs.foldLeft((Tuple3[Int,Double,String] _).curried:Any)({
case (f,x) => f.asInstanceOf[Any=>Any](x)
}).asInstanceOf[(Int,Double,String)]
In scala 3, you can do something like this:
def totuple[A](as: List[A]): Tuple = as match
case Nil => EmptyTuple
case h :: t => h *: totuple(t)
but as has been said already, without giving the compiler any more hard-coded type information, you aren't going to know the length of the tuple or the types of its elements, so this is likely hardly any better than the original list.
as far as you have the type:
val x: List[Int] = List(1, 2, 3)
def doSomething(a:Int *)
doSomething(x:_*)
is there an alternative 'List' syntax in Scala?
Is it possible to define one aditional class/type/operator* called '[' and ']'?
I know 'square brackets' are used to indicate Type, but they are perfect to the repetitive task of declaring lists.
A ';' or '?' would be good also, as a last resource.
Thanks
obs.:
after much search the only alternative I found was to use 'cons':
val list = 1 :: 2 :: 3 :: Nil
but it doesn't reduce any key typing at all.
I am still learning those things in Scala
EDIT:
Just to clarify: Performance is not a priority in my case. And yes, shift is not welcome. :P
Motivation behind the scenes: I like Haskell style, but cannot use it directly with Java.
EDIT 2:
Final solution based on both Rex Kerr solutions
implementing object Types:
package a
object Types {
type \[z] = List[z]
implicit def make_lists[A](z: A) = new ListMaker(z)
class ListMaker[A](a0: A) {
private[this] val buffer = List.newBuilder[A]
buffer += a0
def \(z: A) = {
buffer += z;
this
}
def \\ = buffer.result
}
}
using object Types:
package a
import a.Types._
object Whatever {
def listInListOut (l: \[Int]) = {
1\2\\
}
}
[ and ] are reserved symbols in Scala which are used for type annotations. You can't use them for lists. ; is reserved for end of line. You could use ? in many cases, but it would be awkward.
I recommend that you learn to use the :: notation (and get used to typing the : symbol fast twice in succession) because it really makes the list operations visually clear, plus it is a great syntactic reminder that lists are weird because you put things on the head of the list.
However, if you cannot tolerate this, your best option is probably to define a one-letter list symbol. For example,
List(1,2,3,4)
is a list of the numbers from 1 to 4. What if you could just type L instead of List? It turns out that you can, since this is not a fancy constructor or static method, but a singleton companion object to the class List. So you just
val L = List
L(1,2,3,4)
and you are just one character worse off than your suggestion of brackets.
Define
def l[A](a:A*) = List(a:_*)
Then you can do
l(1,2,3)
which is only one character more than [1,2,3]
I can't help pointing out another way to go here for lists where all the elements are the same type, if you really hate the shift key and don't care if other people can understand your code:
class ListMaker[A](a0: A) {
private[this] val buffer = List.newBuilder[A]
buffer += a0
def \(a: A) = { buffer += a; this }
def \\ = buffer.result
}
implicit def make_lists[A](a: A) = new ListMaker(a)
Now you can list to your heart's content, without ever touching the shift key!
scala> val a = 1\2\3\4\5\\
a: List[Int] = List(1, 2, 3, 4, 5)
scala> val b = 'a'\'b'\\
b: List[Char] = List(a, b)
scala> val c = false\true\false\false\false\false\true\\
c: List[Boolean] = List(false, true, false, false, false, false, true)
This uses exactly as many characters as brackets would. (It doesn't nest well, however.)
Welcome to Scala version 2.10.0.r24777-b20110419020105 (Java HotSpot(TM) Client VM, Java 1.6.0
Type in expressions to have them evaluated.
Type :help for more information.
scala> class LM[A](x: A) {
| def \(y: A) = List(x,y)
| }
defined class LM
scala> implicit def a2l[A](x: A): LM[A] = new LM(x)
a2l: [A](x: A)LM[A]
scala> class LX[A](xs: List[A]) {
| def \(y: A) = xs:::List(y)
| }
defined class LX
scala> implicit def l2lx[A](xs: List[A]): LX[A] = new LX(xs)
l2lx: [A](xs: List[A])LX[A]
scala> 1\2
res0: List[Int] = List(1, 2)
scala> 1\2\3
res1: List[Int] = List(1, 2, 3)
scala>
Not exactly an alternative syntax, but it is by far the most portable solution:
In Intellij IDEA it is possible to create "Live Templates";
press Ctrl+Alt+s; search for "template"; go to "Live Templates" section;
just add one new item named "l" inside Scala entry, add a random description and the following code:
List($END$)
Press Enter, go to the editor, press L followed by Tab.
It is the end of your typing pains.
Do the same for Arrays.
scala> last(List(1, 1, 2, 3, 5, 8))
res0: Int = 8
for having a result above, I wrote this code:
val yum = args(0).toInt
val thrill:
def last(a: List[Int]): List[Int] = {
println(last(List(args(0).toInt).last)
}
What is the problem with this code?
You can use last, which returns the last element or throws a NoSuchElementException, if the list is empty.
scala> List(1, 2, 3).last
res0: Int = 3
If you do not know if the list is empty or not, you may consider using lastOption, which returns an Option.
scala> List().lastOption
res1: Option[Nothing] = None
scala> List(1, 2, 3).lastOption
res2: Option[Int] = Some(3)
Your question is about List, but using last on a infinite collection (e.g. Stream.from(0)) can be dangerous and may result in an infinite loop.
Another version without using last (for whatever reason you might need it).
def last(L:List[Int]) = L(L.size-1)
You should better do:
val a = List(1,2,3) //your list
val last = a.reverse.head
Cleaner and less error-prone :)
Albiet this is a very old question, it might come handy that the performance impact of head and last operations seems to be laid out here http://docs.scala-lang.org/overviews/collections/performance-characteristics.html.
The recursive function last should following 2 properties. Your last function doesn't have any of them.
Requirement #1. An exit condition that does not call recursive
function further.
Requirement #2. A recursive call that reduces the elements that we began with.
Here are the problems I see with other solutions.
Using built in function last might not be an option in interview
questions.
Reversing and head takes additional operations, which the interviewer might ask to reduce.
What if this is a custom linked list without the size member?
I will change it to as below.
def last(a: List[Int]): Int = a match {
//The below condition defines an end condition where further recursive calls will not be made. requirement #1
case x::Nil => x
//The below condition reduces the data - requirement#2 for a recursive function.
case x:: xs => last(xs)
}
last(List(1,2,3))
Result
res0: Int = 3
In these types of questions the useful take and takeRight are often overlooked. Similar to last, one avoids the slow initial reversing of a list, but unlike last, can take the last (or first) n items as opposed to just a single one:
scala> val myList = List(1,2,3)
myList: List[Int] = List(1, 2, 3)
scala> myList.takeRight(2)
res0: List[Int] = List(2, 3)
scala> myList.takeRight(1)
res1: List[Int] = List(3)
If I create a Set in Scala using Set(1, 2, 3) I get an immutable.Set.
scala> val s = Set(1, 2, 3)
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
Q1: What kind of Set is this actually? Is it some hash-set? What is the complexity of look-ups for instance?
Q2: Where can I read up on this "set-creating" method? I thought that it was the apply method but the docs says "This method allows sets to be interpreted as predicates. It returns true, iff this set contains element elem."
Similarly, if I create a List using List(1, 2, 3), I get
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.getClass
res13: java.lang.Class[_] = class scala.$colon$colon
Q3: Again, what do I get? In this case I can't even immediately tell if it's mutable or not, since it's not even part of the scala.collection-package. Why does this live in the scala package?
Q4: Where in the API can I read about this "list-creating" method?
Q1: In this specific case you get a Set3 which is an immutable set of exactly three arguments. Presumably it uses if-else if-else to check inclusion. If you create a set of more than 4 elements, you get an immutable hash set.
Q2: You need to look at the apply method of the object Set, not the class. The apply method of the Set class is what is called when you do someSet(something).
Q3: scala.:: is a non-empty immutable singly linked list (if you do List() without arguments, you get Nil which is an immutable empty list). It lives in the scala package because it is considered so basic that it belongs in the base package.
Q4: See Q2.
Just to add to sepp2k's excellent answer to Q3, where he says
It lives in the scala package because
it is considered so basic that it
belongs in the base package.
This applies to Scala 2.7
In Scala 2.8, the collections classes have been reorganized, and now the :: class lives in scala.collection.immutable, and the name scala.:: is a type alias for scala.collection.immutable.::.
Welcome to Scala version 2.8.0.RC5 (OpenJDK 64-Bit Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val l = List(1, 2, 3)
l: List[Int] = List(1, 2, 3)
scala> l.getClass
res0: java.lang.Class[_] = class scala.collection.immutable.$colon$colon
scala> scala.::
res1: collection.immutable.::.type = scala.collection.immutable.$colon$colon$#6ce5d622
if you call getClass method on the
scala> val list = List(1,2,3,45)
list: List[Int] = List(1, 2, 3, 45)
scala> val seq = Seq(1,2,3,4,5)
seq: Seq[Int] = List(1, 2, 3, 4, 5)
scala> list.getClass
res13: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon
scala> seq.getClass
res14: Class[_ <: Seq[Int]] = class scala.collection.immutable.$colon$colon
That’s because scala.collection.immutable.List is an abstract class, and it comes with two implementations: the scala.Nil class and scala.::. In Scala, :: is a valid identifier, and you could use it to name a class. Nil represents an empty list, and scala.:: represents any nonempty list.
I would like a List, Seq, or even an Iterable that is a read-only view of a part of a List, in my specific case, the view will always start at the first element.
List.slice, is O(n) as is filter. Is there anyway of doing better than this - I don't need any operations like +, - etc. Just apply, map, flatMap, etc to provide for list comprehension syntax on the sub list.
Is the answer to write my own class whose iterators keep a count to know where the end is?
How about Stream? Stream is Scala's way to laziness. Because of Stream's laziness, Stream.take(), which is what you need in this case, is O(1). The only caveat is that if you want to get back a List after doing a list comprehension on a Stream, you need to convert it back to a List. List.projection gets you a Stream which has most of the opeations of a List.
scala> val l = List(1, 2, 3, 4, 5)
l: List[Int] = List(1, 2, 3, 4, 5)
scala> val s = l.projection.take(3)
s: Stream[Int] = Stream(1, ?)
scala> s.map(_ * 2).toList
res0: List[Int] = List(2, 4, 6)
scala> (for (i <- s) yield i * 2).toList
res1: List[Int] = List(2, 4, 6)
List.slice and List.filter both return Lists -- which are by definition immutable.The + and - methods return a different List, they do not change the original List. Also, it is hard to do better than O(N). A List is not random access, it is a linked list. So imagine if the sublist that you want is the last element of the List. The only way to access that element is to iterate over the entire List.
Well, you can't get better than O(n) for drop on a List. As for the rest:
def constantSlice[T](l: List[T], start: Int, end: Int): Iterator[T] =
l.drop(start).elements.take(end - start)
Both elements and take (on Iterator) are O(1).
Of course, an Iterator is not an Iterable, as it is not reusable. On Scala 2.8 a preference is given to returning Iterable instead of Iterator. If you need reuse on Scala 2.7, then Stream is probably the way to go.