Can anybody help me with a begginer problem? I wrote a function to check Declaration, but I Cannot add element Symbol() to List env. I dont understand what the matter is.
def check_decl(env: List[Symbol])(decl: Declare): Unit = decl match{
case VarDec(varName, varType)=>{
lookupForInsert(env)(varName.toString()) match {
case Some(_) => throw Redeclared(Variable,varName.toString())
case None => {
varType match{
case ArrayType(lower, upper, element)=>{
if(lower > upper) throw SizeIsNotNegative(decl)
}
case IntType=>
case RealType=>
case BoolType=>
case StringType=>
}
}
}
}
In Scala you have immutable Lists by default, and you can't "add" something to it. All operations that would modify a list (or more similar, a stack) in Java will result in a new, modified list in Scala. Alternatively you have mutable classes like ListBuffer, which behave more like Java lists.
Related
I have a list like the following:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
I want to check whether SRC_999 exists in it.
I tried the following:
map_temp.foreach {
case(key, value) =>
if (key.contains("SRC_999")) {
print("yes exists")
}
}
This causes the following error
error: value contains is not a member of Any
case(key:Any, value) => if(key.contains("SRC_99"))
I have also tried this:
map_temp.foreach(a => if(a._1.contains("SRC_999")))
But this causes the following error:
error: value contains is not a member of Any
mapped.foreach(a => print(a._1.contains("SRC_999")))
How can I solve this?
How can I solve this?
By not having a List[Any].
By having a List[Any], you are explicitly telling Scala that the elements could be anything. That means Scala doesn't know anything about the elements. It doesn't even know whether they have a contains method or not. The elements could be integers, for example, which don't have a contains method.
The map_temp value is List[(List[String], String)], not List[Any]. You can check for the element you are looking for like this:
map_temp.exists(_._1.contains("SRC_999"))
This should do what you want:
val map_temp =
List(
(List("SRC_123","SRC_999"),"TRGT_123"),
(List("SRC_456"),"TRGT_456"),
(List("SRC_789"),"TRGT_789"),
(List("SRC_888"),"TRGT_888"),
)
def exists[A](input: List[(List[A], _)], what: A): Boolean =
input.exists(_._1.contains(what))
// should be found
assert(exists(map_temp, "SRC_999"))
assert(exists(map_temp, "SRC_888"))
// should not be found
assert(!exists(map_temp, "SRC_998"))
assert(!exists(map_temp, "TRGT_123"))
I don't think you actually have a List[Any] to begin with. It appears that you are experiencing a couple of type errors that could mislead you into believing so. Your map_temp is a List[(List[String], String)].
If that's not the case and you are getting map_temp from a method that for some reason returns a List[Any], if you're in control of that method you can change it to reflect the actual type. If you can't, even though it's not safe, you can attempt to cast it.
With few changes, you can also retrieve items:
def find[A, B](input: List[(List[A], B)], what: A): Option[B] =
input.find(_._1.contains(what)).map(_._2)
// should be found
assert(find(map_temp, "SRC_999") == Some("TRGT_123"))
assert(find(map_temp, "SRC_888") == Some("TRGT_888"))
// should not be found
assert(find(map_temp, "SRC_998") == None)
assert(find(map_temp, "TRGT_123") == None)
You can play around with this code here on Scastie.
I'm learning Scala and in a book that I'm reading (Functional Programming in Scala) I came across an example of a custom List implementation in Scala which goes like this:
sealed trait MyList[+A]
case object MyNil extends MyList[Nothing]
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A]
object MyList {
def apply[A](as: A*): MyList[A] =
if (as.isEmpty) MyNil
else Cons(as.head, apply(as. tail: _*))
}
I would like to extend MyList to add the following functionality:
add a tail method that returns all elements of a MyList instance without the first one, e.g. val x = MyList(1,2,3); x.tail == MyList(2,3).
Add a sum method that is only applicable when MyList contains Ints (or even better for all numeric types). So e.g. val x = MyList(1,2,3); x.sum == 6
The idea above 2 questions is to understand: (1) how to interact with the instance of my class and (2) how to use polymorphism in a situation like this. After some searching around, I'm not even sure how to begin with these problems, which is why I'm asking this question.
Any tips would be appreciated. Many thanks!
UPDATE:
A few updates:
First, I'd like to point out that the solution to the programming challenges in the Functional Programming course that I mentioned earlier can be found here, however, I'm looking for something a little different than what the author is asking for.
I've managed to find an answer to my first question "how can I use tail on my instance itself, e.g. MyList(1,2,3).tail?". To solve this, I had to modify the original trait in the following manner:
sealed trait MyList[+A] {
def tail: MyList[A] = MyList.tail(this)
}
I'm not sure if this is the best way of doing what I want to do, but it works. If anyone has better suggestions, please let me know.
The second part is harder. I wanted to add the following inside the same trait:
def sum[Int]: MyList[Int] = MyList.sum(this)
But IntelliJ is complaining about the type of this which is A and I need to apply this conditionally on this being of type Int.
Another alternative is to do the following:
def sum: Int = this match {
case x: MyList[Int] => MyList.sum(x)
}
But what if we want to create another implementation for String that will also return a String? This cannot be the right solution and I haven't found one yet. Please help :)
.tail
I note that your Cons class already has a public tail member. I'd be tempted to start there and just make it universal...
sealed trait MyList[+A] {
def tail: MyList[A]
}
...and add the MyNil implementation.
case object MyNil extends MyList[Nothing] {
def tail: MyList[Nothing] =
throw new java.lang.UnsupportedOperationException("tail of empty list")
}
This is how the standard library List handles the tail of an empty list. Another, perhaps gentler, option would be to return this so that the tail of an empty MyList is just the empty MyList.
Leaving class Cons and object MyList unchanged, we get the expected results.
MyList('s','h','o','w').tail //res0: MyList[Char] = Cons(h,Cons(o,Cons(w,MyNil)))
MyList(9).tail.tail //java.lang.Unsupported...
.sum
This is a bit trickier. We want each .sum invocation to compile only if the elements are of a sum-able type, such as Int. The Scala way to achieve this to require that the call site provide implicit "evidence" that the element type is acceptable.
sealed trait MyList[+A] {
def sum(implicit ev : A =:= Int) : Int //can sum only if A is Int
}
Alas, this won't compile because MyList is covariant on A, but being the type of a passed parameter puts A in a contra-variant position.
Error: covariant type A occurs in invariant position in type A =:= Int of value ev
Fortunately there's a fix for that: use a different type parameter, related to A but not restricted to its covariant relationship.
sealed trait MyList[+A] {
def sum[B >: A](implicit ev : B =:= Int) : Int = 0 //default behavior
}
case object MyNil extends MyList[Nothing] { ... //unchanged
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A] {
override def sum[B >: A](implicit ev :B =:= Int) : Int = head + tail.sum[B]
}
object MyList { ... //unchanged
MyList(23,31,12).sum //res0: Int = 66
MyList("as","is").sum //won't compile
Numeric[A]
Well that works for Int, but it would be a pain to have to do the same for every sum-able type. Fortunately the standard library offers the Numeric typeclass which provides some basic values (zero and one) and operations (plus(), minus(), times(), etc.) for all the numeric types under its umbrella (Short, Long, Float, etc.).
So, putting it all together:
sealed trait MyList[+A] {
val tail: MyList[A]
def sum[B >: A](implicit ev : Numeric[B]): B = ev.zero
}
case object MyNil extends MyList[Nothing] {
val tail: MyList[Nothing] = this
}
case class Cons[+A](head: A, tail: MyList[A]) extends MyList[A] {
override def sum[B >: A](implicit ev : Numeric[B]): B = ev.plus(head, tail.sum[B])
}
object MyList {
def apply[A](as: A*): MyList[A] =
if (as.isEmpty) MyNil else Cons(as.head, apply(as.tail: _*))
}
I have a class who's only task is to take a List<Object> and return a sorted List<Object>. For an example the sort method in the class works with a procedure which places the Objects randomly in the list.
Trying to do: to write the test for that sorting method (or class) which must fail if the sorting is in fact just random. That means I need to find the List<Object> order to test I assume.
Code to be tested
class RootLoggerFirstSorter {
List<LoggerConfig> sort(List<LoggerConfig> unSortedList) {
List<LoggerConfig> levelSortedList = new ArrayList<>(unSortedList);
Collections.sort(levelSortedList, new Comparator<LoggerConfig>() {
#Override
public int compare(LoggerConfig o1, LoggerConfig o2) {
if (o1.getLevel().intLevel() == o2.getLevel().intLevel()) {
return 0;
} else if (o1.getLevel().intLevel() < o2.getLevel().intLevel()) {
return 1;
} else {
return -1;
}
}}
);
LinkedList<LoggerConfig> sortedList = new LinkedList<LoggerConfig>();
for(Iterator<LoggerConfig> i = levelSortedList.iterator(); i.hasNext();) {
LoggerConfig cfg = i.next();
addNextLoggerConfig(cfg, sortedList);
}
return sortedList;
}
private void addNextLoggerConfig(LoggerConfig cfg, LinkedList<LoggerConfig> sortedList) {
if(cfg.getName() == null || cfg.getName().isEmpty()) {
sortedList.addFirst(cfg);
} else {
sortedList.addLast(cfg);
}
}
}
Tried
.....
expect(item1.getLevel()).andStubReturn(Level.DEBUG);
expect(item2.getLevel()).andStubReturn(Level.ERROR);
expect(item3.getLevel()).andStubReturn(Level.INFO);
.....
//Ignore the pre req for test setup
#Test
public void testSort() {
List<LoggerConfig> unsortedList = makeUnsortedList();
EasyMock.replay(item1,item2,item3);
List<LoggerConfig> sortedList = tested.sort(unsortedList);
assertThat("First item on the list is ERROR level: ", sortedList.get(0).getLevel(), is(Level.ERROR) );
assertTrue(sortedList.get(1).getLevel().equals(Level.INFO) || sortedList.get(1).getLevel().equals(Level.INFO));
assertTrue(sortedList.get(2).getLevel().equals(Level.DEBUG) || sortedList.get(2).getLevel().equals(Level.DEBUG));
}
But this test will always pass since if looked at the index 1 and 2 only, index 0 will always contain the LoggerConfig with an empty name [set up is done that way]). So I thought Should I just unit test the compare method instead? If yes, how?
Problem The issue is that I need to test the sort method with a particular Object property which is the level of the LoggerConfig object. So the test must check the List order.
Many different aspects here:
Of course you do not need to test the built-in Collections.sort() method.
In that sense: instead, you want to test two aspects A) that you are actually calling that sort method B) that your comparator works as expected.
A) is achieved by the code you put in your own answer. Or to be precise: you only need one test case where you sort check for an expected result; after providing a specific test input to your method.
B) is achieved by writing test code that simply checks that compareTo() returns the expected result for the different input
In the end, this is about properly dissecting your logic into classes. Of course you can declare that comparator as anonymous inner class; and just verify that the sort method returns the expected result.
But when you make the comparator, say an inner class somewhere, you could write unit tests for just the comparator functionality.
Finally: your test case does not mean the goal that you stated: must fail if the sorting is in fact just random. You see, if the result of sort() is random, that it could randomly give you a correct result. Meaning: you can't expect a single test to verify "possibly random behavior". You would have to run many tests with a lot of different data, and verify that all of them pass; to achieve a certain confidence that the sort() isnt pure random.
But as said: you are not sorting. You are calling the built-in sort method which does not need to be tested.
I assumed the List<ConfigLogger> followed something like item1["", ERROR], item2["com.fwk.foo", DEBUG], item3["com.fwk.core.baa", INFO]. So in that case I needed to check that if item3 is in the position 1 and item2 is in position 3 in the list the implementation does the sort correctly. So test I needed was as follows:
#Test
public void testSort() {
List<LoggerConfig> unsortedList = makeUnsortedList();
EasyMock.replay(item1,item2,item3);
List<LoggerConfig> sortedList = tested.sort(unsortedList);
assertFalse(unsortedList.equals(sortedList));
assertTrue(sortedList.get(0).getName().isEmpty());
LoggerConfig cfg1 = sortedList.get(1);
LoggerConfig cfg2 = sortedList.get(2);
assertThat(cfg1.getLevel(), is(Level.DEBUG));
assertThat(cfg2.getLevel(), is(Level.INFO));
}
So I am accessing the item from the list and comparing if they are same as expected.
Should I just unit test the compare method instead?
No, you should not. The test may fail if you try to refactor the sort method later. You are actually trying to assert that the sorting is done probably. The compare method is just an implementation detail. You may not use the compare method to sort the list in the future.
Of course you also don't need to test the built-in sort method because you are actually testing your custom sort method. Anything inside this sort method is implementation details including the list.sort method you called. You should pretend that you don't know about it when you are writing a test.
Other than that, your sort method also contain some logic that is not related to the built-in sort method.
As I am working a design model, I am torn between two different methods of indicating a parameter of type List must be nonEmpty. I began by using List[Int] with an accompanying require statement to verify the List is nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
I then needed to make the list optional. If the List is provided, it must be nonEmpty. I'm using using Option[List[Int]] with an accompanying require statement to verify, if the Option is nonEmpty, the list must also be nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
However, I need to use this non-empty List all over the system I am modeling. This means that my code has these same require statements duplicated everywhere. Is there a (non-ScalaZ) way to have a new type, say NeList, which is defined and behaves identically to List, with the only change being an exception is thrown when NeList attempts to be instantiated with no elements?
I tried to Google for this and couldn't find a set of search terms to hone on this area. I either got really simple List how-tos, or all sorts of references to ScalaZ's NEL (Non Empty List). So, if there is a link out there that would help with this, I would love to see it.
If you
def foo[A](x: ::[A]) = "List has length "+x.length
then you insist that the list be nonempty. But of course your lists are all typed as List, so you need a helper method to give you a nonempty list:
implicit class NonEmptyList[A](private val underlying: List[A]) {
def ifNonEmpty[B](f: ::[A] => B): Option[B] = {
underlying match {
case x: ::[A #unchecked] => Some(f(x))
case _ => None
}
}
}
Now you can safely apply the operation to get an Option out. (You could also run side-effecting functions in a foreach-like method.)
Now, this is rather non-idiomatic Scala. But it is safe at compile time (the #unchecked notwithstanding--Scala's compiler isn't quite smart enough to realize that the type parameter hasn't changed).
You could implement a non-empty list yourself with implicit conversions between List[A] and Nel[A]:
case class Nel[A](val head: A, val tail: List[A] = Nil)
implicit def list2Nel[A](list: List[A]): Nel[A] = {
require(!list.isEmpty)
Nel(list.head, list.tail)
}
implicit def nel2List[A](nel: Nel[A]): List[A] = nel.head :: nel.tail
Then you can define your functions where this is needed such that they take a Nel[A] as a parameter:
def f(l: Option[Nel[String]]) = { ... }
And call them with normal lists (assuming the implicit defs are in scope):
f(Some(List("hello", "world")) // works
f(Some(Nil)) // throws IllegalArgumentException
f(None) // works
EDIT: It should be noted that this does not provide compile time guarantees that the List[A] passed in will not be empty. If that's what you want, then get rid of the implicit def list2Nel and require clients of your function to pass in an Nel[A] explicitly, thus guaranteeing at compile time that the list is not empty.
Also, this is a very basic NonEmptyList implementation. A more complete solution is found in scalaz (granted it was specifically requested in the question that scalaz not be used): https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/NonEmptyList.scala
In scala source, I found:
case object Nil extends List[Nothing] {
...
}
I can't understand why it is declared as case object rather than object?
I found this question [ Difference between case object and object ] is useful, and I guess this reason is the key:
default implementations of serialization
because we often send list of data to another actor, so Nil must be serializable, right?
With the provided answers(thanks), I try to write some code to verify it:
trait MyList[+T]
object MyNil extends MyList[Nothing]
val list: MyList[String] = MyNil
list match {
case MyNil => println("### is nil")
case _ => println("### other list")
}
You can see MyNil is not case object, but I can still use it in pattern matching. Here is the output:
### is nil
Do I misunderstand something?
In general for immutable data, the question should never be "why is this a case object (or class)" but rather "Can I make this a case object?". With a few small exceptions (mostly due to inheritance), data elements in Scala should be immutable, and should be implemented via case classes/objects. Given that, implementing Nil and :: as a case object and case class (respectively) is just standard practice, for which there is no downside.
As mentioned in the comments of that linked question, one thing you get is a prettier .toString result
scala> MyNil.toString
res0: String = MyNil$#51aa572b
scala> case object MyNil2 extends MyList[Nothing]
defined module MyNil2
scala> MyNil2.toString
res2: String = MyNil2
scala> Nil.toString
res1: String = List()