I know about two:
#deprecated("use blabla instead") is used to add an explanation to the warning output by the compiler when the annotated definition is used in client code.
#implicitNotFound(msg = "more meaningful explanation") is used to output an additional error message whenever an implicit of the type of the annotated definition cannot be found. Looking at CanBuildFrom, msg can contain placeholders of the type ${A} if A is the name of a type parameter of the annotated type, which is filled in by the compiler with the actual expected type, e.g.:
#implicitNotFound(msg = "Cannot construct a collection of type ${To} with elements of type ${Elem} based on a collection of type ${To}.")
trait CanBuildFrom[-From, -Elem, +To] { ... }
Are there any other such annotations?
There is #migration, which is used with -Xmigration to indicate semantic changes in methods from one version to another, in helping port code between versions.
#migration(2, 8, "As of 2.8, keys returns Iterable[A] rather than Iterator[A].")
There is #tailrec, which makes the compiler output an error if tail call optimization cannot be applied to the annotated method.
As of Scala 2.9, there's also #deprecatedName: “An annotation that designates the name of the parameter to which it is applied as deprecated. Using that name in a named argument generates a deprecation warning.”
Related
I have a scala compiler 2.12.11 and compiler prints some warnings, like:
private default argument in class SomeClass is never used
while as it is used.
I have seen a Scala 2.12.2 emits a ton of useless "Warning: parameter value ... in method ... is never used" warnings. How to get rid of them? however it doesn't help me, as it is not possible to negate params.
Can you help me to surpress this warning, however saving another unused warnings? Currently, I have -Xlint option.
Instead of -Xlint which is a batch, you can turn on specific options manually. For instant in 2.13 I can print available options like this:
scalac -Xlint:help
Enable recommended warnings
adapted-args An argument list was modified to match the receiver.
nullary-unit `def f: Unit` looks like an accessor; add parens to look side-effecting.
inaccessible Warn about inaccessible types in method signatures.
infer-any A type argument was inferred as Any.
missing-interpolator A string literal appears to be missing an interpolator id.
doc-detached When running scaladoc, warn if a doc comment is discarded.
private-shadow A private field (or class parameter) shadows a superclass field.
type-parameter-shadow A local type parameter shadows a type already in scope.
poly-implicit-overload Parameterized overloaded implicit methods are not visible as view bounds.
option-implicit Option.apply used an implicit view.
delayedinit-select Selecting member of DelayedInit.
package-object-classes Class or object defined in package object.
stars-align In a pattern, a sequence wildcard `_*` should match all of a repeated parameter.
strict-unsealed-patmat Pattern match on an unsealed class without a catch-all.
constant Evaluation of a constant arithmetic expression resulted in an error.
unused Enable -Wunused:imports,privates,locals,implicits,nowarn.
nonlocal-return A return statement used an exception for flow control.
implicit-not-found Check #implicitNotFound and #implicitAmbiguous messages.
serial #SerialVersionUID on traits and non-serializable classes.
valpattern Enable pattern checks in val definitions.
eta-zero Usage `f` of parameterless `def f()` resulted in eta-expansion, not empty application `f()`.
eta-sam The Java-defined target interface for eta-expansion was not annotated #FunctionalInterface.
deprecation Enable -deprecation and also check #deprecated annotations.
byname-implicit Block adapted by implicit with by-name parameter.
recurse-with-default Recursive call used default argument.
unit-special Warn for specialization of Unit in parameter position.
multiarg-infix Infix operator was defined or used with multiarg operand.
implicit-recursion Implicit resolves to an enclosing definition.
Default: All choices are enabled by default.
so I could e.g. enable -Xlint:inaccessible -Xlint:adapted-args -Wunused:privates,locales or whatever I want instead of everything. For 2.12 this list would be different. (You can also check scalac -X, scalac -Y and scalac -W).
An alternative is to enable warnings and suppress them when you "breaking" something consciously. For unused you have #scala.annotation.unused, for other warnings in 2.12 and before there is silencer plugin and since 2.13 there is #scala.annotation.nowarn annotation.
In Scala 2.12 is there any difference between any of these options:
-Xlint:adapted-args vs -Ywarn-adapted-args
-Xlint:nullary-unit vs -Ywarn-nullary-unit
-Xlint:inaccessible vs -Ywarn-inaccessible
-Xlint:nullary-override vs -Ywarn-nullary-override
-Xlint:infer-any vs -Ywarn-infer-any
If not, which one makes more sense to use? I also compile with fatal-warnings, and almost all -Ywarn and -Xlint options.
If you run scalac -Xlint:help you'll see
❯ scalac -Xlint:help
Enable or disable specific warnings
adapted-args Warn if an argument list is modified to match the receiver.
nullary-unit Warn when nullary methods return Unit.
inaccessible Warn about inaccessible types in method signatures.
nullary-override Warn when non-nullary `def f()' overrides nullary `def f'.
infer-any Warn when a type argument is inferred to be `Any`.
missing-interpolator A string literal appears to be missing an interpolator id.
doc-detached A Scaladoc comment appears to be detached from its element.
private-shadow A private field (or class parameter) shadows a superclass field.
type-parameter-shadow A local type parameter shadows a type already in scope.
poly-implicit-overload Parameterized overloaded implicit methods are not visible as viewbounds.
option-implicit Option.apply used implicit view.
delayedinit-select Selecting member of DelayedInit.
by-name-right-associative By-name parameter of right associative operator.
package-object-classes Class or object defined in package object.
unsound-match Pattern match may not be typesafe.
stars-align Pattern sequence wildcard must align with sequence component.
constant Evaluation of a constant arithmetic expression results in an error.
unused Enable -Ywarn-unused:imports,privates,locals,implicits.
Default: All choices are enabled by default.
so there's no difference between selecting Xlint options or using the corresponding flags directly. I would just go with -Xlint (no options, so all enabled by default) and remove the ones I don't need, for example
-Xlint:-unused,_
to enable everything but the unused flag.
I have a simple question, why is the Scala compiler not able to infer the function parameter types by itself ?
Some functional programming languages, like Haskell, can infer almost
all types, because they can perform global type inference. Scala can’t
do this, in part because Scala has to support subtype polymorphism
(inheritance), which makes type inference much harder. Here is a
summary of the rules for when explicit type annotations are required
in Scala.
When Explicit Type Annotations Are Required
In practical terms, you have to provide explicit type annotations for the following situations:
A mutable var or immutable val declaration where you don’t assign a value, (e.g., abstract declarations in a class like val book: String, var count: Int
All method parameters (e.g., def deposit(amount: Money) = {…}).
Method return types in the following cases:
1)When you explicitly call return in a method (even at the end).
2)When a method is recursive.
3)When two or more methods are overloaded (have the same name) and one of them calls another; the calling method needs a return type annotation.
4)When the inferred return type would be more general than you intended, e.g., Any.
Source Programming Scala, 2nd Edition - O'Reilly Media
I have a simple question, why is the Scala compiler not able to infer the function parameter types by itself ?
Scala has local type inference. If you look at the method, and look at what information is there locally, it should be easy to see, that there simply is no information about what the types could possibly be.
Say, you have the following method:
def foo(a) = a + a
How is Scala going to figure out what type a is? It can only figure that out from looking at how the method is called, but that is non-local information!
And even worse: since Scala supports dynamic code loading, it is possible that the calling code doesn't even exist yet at compile time.
I wrote the following simple program:
import java.util.{Set => JavaSet}
import java.util.Collections._
object Main extends App {
def test(set: JavaSet[String]) = ()
test(emptySet()) //fine
test(emptySet) //error
}
DEMO
And was really surprised the the final line test(emptySet) was not compiled. Why? What is the difference between test(emptySet())? I thought in Scala we could omit parenthesis freely in such cases.
See Method Conversions in Scala specification:
The following four implicit conversions can be applied to methods which are not applied to some argument list.
Evaluation
A parameterless method m
of type => T is always converted to type T by evaluating the expression to which m is bound.
Implicit Application
If the method takes only implicit parameters, implicit arguments are passed following the rules here.
Eta Expansion
Otherwise, if the method is not a constructor, and the expected type pt
is a function type (Ts′)⇒T′, eta-expansion is performed on the expression e.
Empty Application
Otherwise, if e
has method type ()T, it is implicitly applied to the empty argument list, yielding e().
The one you want is "Empty Application", but it's only applied if none of the earlier conversions are, and in this case "Eta Expansion" happens instead.
EDIT: This was wrong and #Jasper-M's comment is right. No eta-expansion is happening, "Empty Application" is just inapplicable to generic methods currently.
I have a couple of functions whose only parameter requirement is that it has some sort of collection that is also growable (i.e. it could be a Queue, List, PriorityQueue, etc.), so I attempted to create the following type alias:
type Frontier = Growable[Node] with TraversableLike[Node, Frontier]
to use with function definitions like so:
def apply(frontier: Frontier) = ???
but the type alias returns the error "Illegal cyclic reference involving type Frontier." Is there any way to get around the illegal cyclic reference to use the type alias or something similar to it?
One solution is to use the following:
def apply[F <: Growable[Node] with TraversableLike[Node, F]](f: F) = ???
but this seems to add unnecessary verbosity when the function definition is doing seemingly the exact same thing as the type alias. The type is also used in other places, so a type alias would greatly increase readability.
From section 4.3 of the spec:
The scope rules for definitions (§4) and type parameters (§4.6) make
it possible that a type name appears in its own bound or in its
right-hand side. However, it is a static error if a type alias refers
recursively to the defined type constructor itself.
So no, there's no way to do this directly, but you can accomplish much the same thing with a type parameter on the type alias:
type Frontier[F <: Frontier[F]] = Growable[Int] with TraversableLike[Int, F]
Now you just write your apply like this:
def apply[F < Frontier[F]](frontier: F) = ???
Still a more little verbose than your hypothetical first version, but shorter than writing the whole thing out.
You could also just use the wildcard shorthand for an existential type:
type Frontier = Growable[Node] with TraversableLike[Node, _]
Now your first apply will work as it is. You're just saying that there has to be some type that fits that slot, but you don't care what it is.
In this case specifically, though, is there a reason you're not using Traversable[Node] instead? It would accomplish practically the same thing, and isn't parameterized on its representation type.