I'm trying to use scala compiler Y warnings, but I don't think I'm doing it right. In the example below, nums is unused, hence I'd expect -Ywarn-value-discard to print a warning for that.
There are two if conditions, one nested inside the other. The child if's condition is exact opposite of parents', hence anything inside it is dead code. But -Ywarn-dead-code doesn't warn against that.
Could anyone please suggest what I might be doing wrong? Any pointers would be appreciated.
object DeadCodeWarn{
def main( args: Array[ String ] ) {
val nums = 1 to 100
//There should be a warning for squares
//as its a non-unit expression thats not
//used in any computation. Y-warn-value-discard
val squares = nums.map( x => x * x )
if( nums.length == 100 ){
println( "should be printed" )
if( nums.length !=100 )
{
//-Ywarn-dead-code
println( "Dead code, so should be warned against" )
}
}
}
}
$scalac -Xlint -Ywarn-all DeadCodeWarn.scala succeeds silently.
-Ywarn-value-discard
The value isn't discarded, it's assigned to the val!
The problem is that the val is unused
With code:
package foo
case class Foo(x: Int) {
def foo: Int = {
val y = 2;
x
}
}
I get with scalac 2.11.5 and -Ywarn-unused:
[warn] /.../foo.scala:5: local val in method foo is never used
[warn] val y = 2;
-Ywarn-dead-code
It's easy to write the counter-example(s) where the common logic doesn't work:
// Evil mutable class
class Arrayish {
private var x: Int = 100
def length(): Int = {
val res = x
x += 1
res
}
}
def test(nums: Arrayish): Unit =
if (nums.length == 100) {
println( "should be printed" )
if (nums.length != 100) {
println("Dead code, so should be warned against")
}
}
Dead code is run:
scala> test(new Arrayish())
should be printed
Dead code, so should be warned against
Or
class NonEqual {
def ==(x: Int): Boolean = true
def !=(x: Int): Boolean = true
}
class NaNLength {
val length: NonEqual = new NonEqual
}
def test2(nums: NaNLength): Unit =
if (nums.length == 100) {
println("should be printed")
if (nums.length != 100) {
println("Dead code, so should be warned against")
}
}
Dead code is run as well:
scala> test2(new NaNLength)
should be printed
Dead code, so should be warned against
Scalac compiler isn't smart enough to distinguish well behaving and not-so-well behaving cases.
If you are going to submit the bug / feature-request, mention example like:
def test3(nums: Array[Int]): Unit = {
if (true) {
println("should be printed")
if (false) {
println("Dead code, so should be warned against")
}
}
}
def test4(nums: Array[Int]): Unit = {
val hundred = nums.length == 100
if (hundred) {
println("should be printed")
if (!hundred) {
println("Dead code, so should be warned against")
}
}
}
Seems that scalac dead code reporter isn't as polished as e.g. Java. I hope scalac does optimise these examples properly though, it shouldn't be too complicated.
After some toying around with the code, it appears that this is simply not a case where dead code is caught. I will see about continuing to peruse the compiler code itself, however upon review it seems that dead code is eliminated. Upon elimination is when it seems to emit the warning. So, if you review something as simple as
def foo = {return 1; 1}
You will see that the final code is simply to return 1 and not even emit the second 1. However, if you take a look at the final code of this nested if you will see that the second if is not eliminated.
Go ahead and submit a bug, although I'm not sure what kind of priority this would have.
Related
Imagine following variation of InputStream:
trait FutureInputStream {
//read bytes asynchronously. Empty array means EOF
def read(): Future[Array[Byte]]
}
Question is how to write discardAll function for such stream? Here is my solution:
//function that discards all input and returns Future completed on EOF
def discardAll(is: FutureInputStream): Future[Unit] = {
val f = is.read()
f.flatMap {
case v if v.length == 0 =>
Future successful Unit
case _ =>
discardAll(is)
}
}
Obvious problem with this code is non-optimizable recursion: it will quickly run out of stack. Is there more efficient solution?
There is nothing wrong with your solution. The call to discardAll(is) is done asynchronously. It doesn't happen in the same stack frame as the previous call, so there will be no stack overflow.
You can kind of see what happens with a naive implementation:
trait FutureInputStream {
var count = 0
def read(): Future[Array[Byte]] = {
if(count < 100000) {
count += 1
Future(Array(1))
} else
Future(Array())
}
}
If you were to feed discardAll with an instance of the above, it would be okay.
scala> val is = new FutureInputStream{}
is: FutureInputStream = $anon$1#255d542f
scala> discardAll(is).onComplete { println }
Success(())
I have the below requirement where I am checking whether a value is greater than 10 or not and based on that I will break, otherwise I will return a String. Below is my code:
import scala.util.control.Breaks._
class BreakInScala {
val breakException = new RuntimeException("Break happened")
def break = throw breakException
def callMyFunc(x: Int): String = breakable(myFunc(x))
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
break
}
}
}
Now what is the happening is that I am getting the error message saying "type mismatch; found : Unit required: String" The reason is :
def breakable(op: => Unit)
But then how I will write a function which can return value as well as break if required?
The Scala compiler can evaluate that a branch throws an exception and not use it to form a minimum bound for the return type, but not if you move the throwing code out in a method: since it can be overridden, the compiler cannot be sure it will actually never return.
Your usage of the Break constructs seems confused: it already provides a break method, there is no need to provide your own, unless you want to throw your exception instead, which would make using Break unnecessary.
You are left with a couple of options then, since I believe usage of Break is unnecessary in your case.
1) Simply throw an exception on failure
def myFunc(x: Int): String = {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
def usemyFunc(): Unit = {
try {
println("myFunc(11) is " + myFunc(11))
println("myFunc(5) is " + myFunc(5))
} catch {
case e: Throwable => println("myFunc failed with " + e)
}
}
2) Use the Try class (available from Scala 2.10) to return either a value or an exception. This differs from the previous suggestion because it forces the caller to inspect the result and check whether a value is available or not, but makes using the result a bit more cumbersome
import scala.util.Try
def myFunc(x: Int): Try[String] = {
Try {
if (x > 10) {
"I am fine"
} else {
throw new RuntimeException("Break happened")
}
}
}
def useMyFunc(): Unit = {
myFunc match {
case Try.Success(s) => println("myFunc succeded with " + s)
case Try.Failure(e) => println("myFunc failed with " + e)
}
}
3) If the thrown exception isn't relevant, you can use the Option class instead.
You can see how the multiple ways of working with Options relate to each other in
this great cheat sheet.
def myFunc(x: Int): Option[String] = {
if (x > 10) {
Some("I am fine") /* Some(value) creates an Option containing value */
} else {
None /* None represents an Option that has no value */
}
}
/* There are multiple ways to work with Option instances.
One of them is using pattern matching. */
def useMyFunc(): Unit = {
myFunc(10) match {
case Some(s) => println("myFunc succeded with " + s)
case None => println("myFunc failed")
}
}
/* Another one is using the map, flatMap, getOrElse, etc methods.
They usually take a function as a parameter, which is only executed
if some condition is met.
map only runs the received function if the Option contains a value,
and passes said value as a parameter to it. It then takes the result
of the function application, and creates a new Option containing it.
getOrElse checks if the Option contains a value. If it does, it is returned
directly. If it does not, then the result of the function passed to it
is returned instead.
Chaining map and getOrElse is a common idiom meaning roughly 'transform the value
contained in this Option using this code, but if there is no value, return whatever
this other piece of code returns instead'.
*/
def useMyFunc2(): Unit = {
val toPrint = myFunc(10).map{ s =>
"myFunc(10) succeded with " + s
}.getOrElse{
"myFunc(10) failed"
}
/* toPrint now contains a message to be printed, depending on whether myFunc
returned a value or not. The Scala compiler is smart enough to infer that
both code paths return String, and make toPrint a String as well. */
println(toPrint)
}
This is a slightly odd way of doing things (throwing an exception), an alternative way of doing this might be to define a "partial function" (a function which is only defined only a specific subset of it's domain a bit like this:
scala> val partial = new PartialFunction[Int, String] {
| def apply(i : Int) = "some string"
| def isDefinedAt(i : Int) = i < 10
}
partial: PartialFunction[Int, String] = <function1>
Once you've defined the function, you can then "lift" it into an Option of type Int, by doing the following:
scala> val partialLifted = partial.lift
partialOpt: Int => Option[String] = <function1>
Then, if you call the function with a value outside your range, you'll get a "None" as a return value, otherwise you'll get your string return value. This makes it much easier to apply flatMaps/ getOrElse logic to the function without having to throw exceptions all over the place...
scala> partialLifted(45)
res7: Option[String] = None
scala> partialLifted(10)
res8: Option[String] = Some(return string)
IMO, this is a slightly more functional way of doing things...hope it helps
In python you can avoid try {} catch {} finally {} boilerplate with with (see What is the python keyword "with" used for?). I remember seeing an alternative to that in Scala, but I can't find it anymore.
It goes along the lines of:
def using[O](r: {def close()})(doit: () => O): O = try {
doit()
} finally {
r.close
}
using(myWriter){() => myWriter.println("something or another")}
Is it built into 2.10, or do I need a separate library for it?
It's almost trivial to make your own that covers almost all use cases (here using 2.10):
implicit class TidyUpAnything[A](val a: A) extends AnyVal {
def tidily[Z](g: A=>Any)(f: A=>Z) = try { f(a) } finally { g(a) }
}
If you want exceptions to pass through, use as is:
scala> Option(null: String).tidily(println){_.get} // Should print None
None
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:313)
...
and if you want to handle exceptions, use it in conjunction with scala.util.Try:
scala> import scala.util._
scala> Try( Option(null: String).tidily(println){ _.get } )
None
res1: scala.util.Try[String] = Failure(java.util.NoSuchElementException: None.get)
Normally you would make g be something like _.close, but you can do arbitary resource cleanup with it. For example, here we back off a counter by one whenever we finish:
var i = 0
val a = Array(1,2)
a.tidily(_ => i -= 1){ _.foreach(_ => i += 1) }
scala> i
res2: Int = 1
I was wondering if scala had an equivalent to java's #SuppressWarnings that can be applied to a function or whatever to ignore any deprecation warnings[1] that function emits?
1: Relevant warning in my case is: method stop in class Thread is deprecated: see corresponding Javadoc for more information. I am aware of the problems with stop however there are still some cases where due to legacy code we have to use it.
No, and an enhancement request [1] for such a feature was closed as wontfix.
I agree it would be useful. I expect that the Scala core team aren't against the idea, but they have finite resources and many higher priorities.
update: this feature was eventually implemented in scala 2.13.2 release on 2020-04-22, see this answer
[1] https://issues.scala-lang.org/browse/SI-1781
EDIT: You should use #nowarn
There is a simple compiler plugin for this: silencer (a bit shameless plug)
Scala 2.13.2 provides #nowarn annotation developed on the basis of ghik's silencer, for example
import scala.annotation.nowarn
def t = { 0: #nowarn; 1 }
raises no warnings, whilst
def t = { 0; 1 }
gives
warning: a pure expression does nothing in statement position; multiline expressions might require enclosing parentheses
def t = { 0; 1 }
^
Here is how to suppress all warnings in sbt:
import sbt._
import Keys._
import KeyRanks.DTask
import xsbti.{Reporter, Problem, Position, Severity}
private lazy val compilerReporter = TaskKey[xsbti.Reporter](
"compilerReporter",
"Experimental hook to listen (or send) compilation failure messages.",
DTask
)
val ignoreWarnings = Seq(
compilerReporter in (Compile, compile) :=
new xsbti.Reporter {
private val buffer = collection.mutable.ArrayBuffer.empty[Problem]
def reset(): Unit = buffer.clear()
def hasErrors: Boolean = buffer.exists(_.severity == Severity.Error)
def hasWarnings: Boolean = buffer.exists(_.severity == Severity.Warn)
def printSummary(): Unit = {
print("\033c")
if (problems.nonEmpty) {
problems.foreach{ p =>
println("=====================================================")
println(p.position)
println(p.message)
println()
println()
}
}
}
def problems: Array[Problem] = buffer.toArray
def log(problem: Problem): Unit = {
if (problem.severity == Severity.Error) {
buffer.append(problem)
}
}
def log(pos: Position, msg: String, sev: Severity): Unit = {
log(new Problem {
def category: String = "foo"
def severity: Severity = sev
def message: String = msg
def position: Position = pos
})
}
def comment(pos: xsbti.Position, msg: String): Unit = ()
}
)
How might one implement C# yield return using Scala continuations? I'd like to be able to write Scala Iterators in the same style. A stab is in the comments on this Scala news post, but it doesn't work (tried using the Scala 2.8.0 beta). Answers in a related question suggest this is possible, but although I've been playing with delimited continuations for a while, I can't seem to exactly wrap my head around how to do this.
Before we introduce continuations we need to build some infrastructure.
Below is a trampoline that operates on Iteration objects.
An iteration is a computation that can either Yield a new value or it can be Done.
sealed trait Iteration[+R]
case class Yield[+R](result: R, next: () => Iteration[R]) extends Iteration[R]
case object Done extends Iteration[Nothing]
def trampoline[R](body: => Iteration[R]): Iterator[R] = {
def loop(thunk: () => Iteration[R]): Stream[R] = {
thunk.apply match {
case Yield(result, next) => Stream.cons(result, loop(next))
case Done => Stream.empty
}
}
loop(() => body).iterator
}
The trampoline uses an internal loop that turns the sequence of Iteration objects into a Stream.
We then get an Iterator by calling iterator on the resulting stream object.
By using a Stream our evaluation is lazy; we don't evaluate our next iteration until it is needed.
The trampoline can be used to build an iterator directly.
val itr1 = trampoline {
Yield(1, () => Yield(2, () => Yield(3, () => Done)))
}
for (i <- itr1) { println(i) }
That's pretty horrible to write, so let's use delimited continuations to create our Iteration objects automatically.
We use the shift and reset operators to break the computation up into Iterations,
then use trampoline to turn the Iterations into an Iterator.
import scala.continuations._
import scala.continuations.ControlContext.{shift,reset}
def iterator[R](body: => Unit #cps[Iteration[R],Iteration[R]]): Iterator[R] =
trampoline {
reset[Iteration[R],Iteration[R]] { body ; Done }
}
def yld[R](result: R): Unit #cps[Iteration[R],Iteration[R]] =
shift((k: Unit => Iteration[R]) => Yield(result, () => k(())))
Now we can rewrite our example.
val itr2 = iterator[Int] {
yld(1)
yld(2)
yld(3)
}
for (i <- itr2) { println(i) }
Much better!
Now here's an example from the C# reference page for yield that shows some more advanced usage.
The types can be a bit tricky to get used to, but it all works.
def power(number: Int, exponent: Int): Iterator[Int] = iterator[Int] {
def loop(result: Int, counter: Int): Unit #cps[Iteration[Int],Iteration[Int]] = {
if (counter < exponent) {
yld(result)
loop(result * number, counter + 1)
}
}
loop(number, 0)
}
for (i <- power(2, 8)) { println(i) }
I managed to discover a way to do this, after a few more hours of playing around. I thought this was simpler to wrap my head around than all the other solutions I've seen thus far, though I did afterward very much appreciate Rich's and Miles' solutions.
def loopWhile(cond: =>Boolean)(body: =>(Unit #suspendable)): Unit #suspendable = {
if (cond) {
body
loopWhile(cond)(body)
}
}
class Gen {
var prodCont: Unit => Unit = { x: Unit => prod }
var nextVal = 0
def yld(i: Int) = shift { k: (Unit => Unit) => nextVal = i; prodCont = k }
def next = { prodCont(); nextVal }
def prod = {
reset {
// following is generator logic; can be refactored out generically
var i = 0
i += 1
yld(i)
i += 1
yld(i)
// scala continuations plugin can't handle while loops, so need own construct
loopWhile (true) {
i += 1
yld(i)
}
}
}
}
val it = new Gen
println(it.next)
println(it.next)
println(it.next)