Taking this example right from the User Guide of Scalacheck:
scala> import org.scalacheck.Prop.{forAll, BooleanOperators}
scala> val propTrivial = forAll { n: Int =>
| (n == 0) ==> (n == 0)
| }
scala> propTrivial.check
! Gave up after only 4 passed tests. 500 tests were discarded.
I'd like to see the actual value that caused the test to fail. I have a similar test case in my project that produces a similar (useless) message.
I tried adding the verbosity option to sbt:
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "5")
and also tried calling the property like
testOptions in Test += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "5")
But neither works. I cannot get any more output.
In this case, no value caused the test to fail, but ScalaCheck gave up because it could not find enough values to try. This is why it says 500 tests were discarded - it's not a useless error message, it's just saying that the generated values did not match your n == 0 precondition.
If you try with a test that does fail, it will tell you the failing test:
scala> forAll { n: Int => n > 0 }
res0: org.scalacheck.Prop = Prop
scala> res0.check
! Falsified after 2 passed tests.
> ARG_0: -2147483648
Related
In the book "Scala for the impatient", it says on page 16
In Scala, a { } block contains a sequence of expressions, and the
result is also an expression. The value of the block is the value of
the last expression.
OK, then let's create a block and let the last value of the block be assigned:
scala> val evens = for (elem <- 1 to 10 if elem%2==0) {
| elem
| }
val evens: Unit = ()
I would have expected that evens is at least the last value of the sequence (i.e. 10). But why not?
You need to yield the value, then it's a for expression:
val evens = for (elem <- 1 to 10 if elem % 2 == 0) yield elem
Without that it's just a statement (does not return anything) and is translated to foreach.
P.S.: Of course this will return a collection of all the elements that fulfill the predicate and not the last one.
When in doubt just run it through the typechecker to peek under the hood
scala -Xprint:typer -e 'val evens = for (elem <- 1 to 10 if elem%2==0) { elem }'
reveals
val evens: Unit =
scala.Predef
.intWrapper(1)
.to(10)
.withFilter(((elem: Int) => elem.%(2).==(0)))
.foreach[Int](((elem: Int) => elem))
where we see foreach to be the last step in the chain, and its signature is
def foreach[U](f: A => U): Unit
where we see it returns Unit. You can even do this straight from within the REPL by executing the following command
scala> :settings -Xprint:typer
and now you will get real-time desugaring of Scala expressions at the same time they are interpreted. You can even take it a step further and get at the JVM bytecode itself
scala> :javap -
For-comprehensions are some of the most prevalent syntactic sugar in Scala so I would suggest to drill them as much as possible by perhaps trying to write them at the same time in both their suggared and desugared from until it clicks: https://docs.scala-lang.org/tutorials/FAQ/yield.html
Unit is the exception to the rule stated in your book. Unit basically says "ignore whatever type the block would have returned because I only intended to execute the block for the side effects." Otherwise, in order to get it to typecheck, you'd have to add a unit value to the end of any block that was supposed to return Unit:
val evens = for (elem <- 1 to 10 if elem%2==0) {
elem
()
}
This throwing away of type information is one reason people tend to avoid imperative for loops and similar in Scala.
I am in the process of implementing a simple in-memory, Redis-like KeyValue store and experiencing a compilation failure on the if statement within the for comprehension following piece of code:
/*
Returns the specified elements of the list stored at key. The offsets start and
stop are zero-based indexes, with 0 being the first element of the list to n. */
def lrange(k: keyT, maxIdx:Int, minIdx:Int): List[valT] = {
val l = lookup(k)
//assert(maxIdx >= minIdx && maxIdx <= (l length) && minIdx >= 0, "invalid min or max argument. list size ")
for {
(x: valT, i: Int) <- l zipWithIndex //tried without explicit typing
if i <= maxIdx && i >= minIdx //tried indenting if
} yield x
}
The editor (IntelliJ) shows no errors, but I receive the following build error when attempting to build and run tests.
[INFO] --- scala-maven-plugin:3.3.2:compile (default) # DS4300Project3 ---
[INFO] .../Spring2019/DS4300/scala/DS4300Project3/src/main/scala:-1: info: compiling
[INFO] Compiling 3 source files to .../Spring2019/DS4300/scala/DS4300Project3/target/classes at 1550678144065
[ERROR] .../Spring2019/DS4300/scala/DS4300Project3/src/main/scala/com/rejevichb/homework3/KeyValStore.scala:70: error: illegal start of simple expression
[ERROR] if (i <= maxIdx) && (i >= minIdx) //tried indenting if
[ERROR] ^
[ERROR] one error found
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
Specifically:
KeyValStore.scala:70: error: illegal start of simple expression
Any guidance or insight into what is going wrong here is appreciated, as the solution is not clear to me.
This is exactly the reason why you should use postfix operators with caution.
for {
i <- "a" zipWithIndex
if true
} yield i
is parsed as
for { i <- ("a" zipWithIndex if true) } yield i
because the compiler attempts to interpret zipWithIndex as a binary infix operator, but then runs into if true, which is indeed not a simple expression.
Workarounds:
just don't use postfix ops, use a period:
for {
i <- "a".zipWithIndex
if true
} yield i
add a semicolon to force zipWithIndex to be interpreted as postfix op:
for {
i <- "a" zipWithIndex;
if true
} yield i
and then enjoy your feature warning:
warning: postfix operator zipWithIndex should be enabled
by making the implicit value scala.language.postfixOps visible.
I tried following two versions of code to understand how yield in scala works. I am unable to understand why I am getting two different results
In this version, I call yield and the expression is simply multiply by 2. I get a Vector of 1st 10 multiples of 2. It makes sense to me
scala> val r = for (j <- 1 to 10) yield {
| (j*2).toString //multiply by 2
| }
r: scala.collection.immutable.IndexedSeq[String] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20) // got multiples of 2. This looks ok
Interestingly in this version, all I have done is store the multiplication by 2 in a val. But now I get an empty vector! Why is this?
scala> val r = for (j <- 1 to 10) yield {
| val prod = (j*2).toString //multiply by 2 but store in a val
| }
r: scala.collection.immutable.IndexedSeq[Unit] = Vector((), (), (), (), (), (), (), (), (), ()) //this is empty
I thought that maybe the val prod = (j*2).toString results in a Unit result but when I try following independent expression on scala interpreter, I can see that prod is a String
scala> val prod = 2.toString()
prod: String = 2
In Scala every expression return something. But assignments are designed to return Unit for performance reasons (see What is the motivation for Scala assignment evaluating to Unit rather than the value assigned?).
In your snippet, in last example REPL says prod: String = 2, meaning that prod has some value, that's done for your convenience. But try { val prod = 2.toString() }:
scala> { val prod = 2.toString() }
scala> println(res0)
()
() is the only possible value of Unit type.
(I'm not sure why res0 was not shown after first like, because resN-like values in REPL collect all non-assigned explicitly results)
I'm wondering if there is something that can give me results similar to Groovy's nice power assert statement.
> assert ["1", '2']*.size() == [2, 3]
Result: Assertion failed:
assert ["1", '2']*.size() == [2, 3]
| |
[1, 1] false
AFAIK there is no support for such thing neither in language, nor in
scalatest, which I'm currently using.
But maybe someone can suggest some side library doing that? It's a pet project, so experimental and not well-supported libs are fine.
EDIT: I know about matchers (scalatest ones, or even plain-java hamcrest matchers). I find them verbose to write and that their output lacks details.
The example above shows intermediate computation steps, facilitating detection of errors. It shows you what's wrong with tested code with more details.
I expect, that introducing such behaviour will require having information about expression AST at runtime. But I suppose, that this information can be "baked" compile time with usage of macroses.
I.e. if we have expression assert a + b == c scala (or some macro extension I'm looking for) can rewrite it to something like:
if (!(a + b == c)) {
// detailed message is
// compute a
// compute b
// compute a + b
// compute c
// compute a + b == c
// Make it pretty.
throw new AssertionFailedException(prettyDetailedMessage)
}
So I'm looking if it's already implemented, and if yes - where.
In ScalaTest, you can use DiagrammedAssertions.
See http://www.scalatest.org/release_notes/2.2.0#diagrammedAssertions
This is based on Expecty which is a macro-based implementation of Spock's power assertions. See https://github.com/pniederw/expecty
Specs2 matchers do a good job with error messages:
class Specs2Specification extends Specification {
"specs2 assertion" should {
"fail" in {
List("1", "2").map(_.length) must_=== List(2, 3)
}
}
}
run output:
[info] Specs2Specification
[info]
[info] specs2 assertion should
[error] x fail
[error] List(1, 1) is not equal to List(2, 3)
[info]
[error] Added (2)
[error] 1
[error] 1
[info]
[error] Missing (2)
[error] 2
[error] 3
or
List("1", "2").map(_.length) must contain(exactly(2, 3)).inOrder
which produces
[error] x fail
[error] the values 2, 3 are not in order
There are lots of them and you can create custom ones.
Your groovy code snippet is literally translated to the following scala code (given that you're already using scalatest):
assert((List("1", "2") map (_.length)) === List(2, 3))
It produces the following error message:
*** FAILED ***
List(1, 1) did not equal List(1, 3)
I'm getting an error message of "error: type arguments [Any] do not conform to trait Cloneable's type parameter bounds [+A <: AnyRef]," which I can't make heads or tails of.
Specifically,
var M = mutable.Map[Int, mutable.Set[Int]]()
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
else {M(i) += j}
}
(I'm actually trying something more complicated, but this is the error generating code tweaked and simplified to a minimum)
And the last line of the above code generates the error message. If I strip it down further
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
}
it works!
How do I make the above code work?
Digal diagnosed the problem (failure to unify the types of the if-else branches) and it looks like a compiler bug. Here's a further simplified case that will give an error in the REPL, after a lengthy compilation time,
if (true) {
null: collection.mutable.Map[Int, Int]
} else {
null: collection.mutable.Set[Int]
}
In the meantime, you can get your code to compile with an explicit type sprinkled somewhere in the if-else statement,
for(i <- 1 to 100; j <- 1 to 100) {
if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
else {M(i) += j}: Unit
}
I filed an issue here: https://issues.scala-lang.org/browse/SI-4938
I've reduced your example even further:
scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1};
<console>:9: error: type arguments [Any] do not conform to trait Cloneable's type parameter bounds [+A <: AnyRef]
val res17 =
^
The problem seem to occur when compiler tries to find common return type for both branches:
The first one is
scala> M += 1 -> mutable.Set[Int](1)
res19: scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] = ...
And the "else" part is
scala> M(1) += 1
res18: scala.collection.mutable.Set[Int] = Set(1)
If I add a return value to the end of this expression, REPL eats it without errors:
scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1}; println("hello")
hello
Because the expression's return type is Unit.