I used that kind of line to test my implicits making it implicit by copy-paste accident. It took me quite some time to figure out, why this compiles despite me not expecting it to compile:
> console
[info] Starting scala interpreter...
[info]
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_66).
... skipped some comment lines ...
scala> case object Foo
defined object Foo
scala> object Bar { implicit val f: Foo.type = implicitly[Foo.type] }
defined object Bar
scala> val x = Bar.f
x: Foo.type = null
scala>
I would expect Bar to fail compilation, because there is NO implicit val of type Foo.type (the case object is NOT declared implicit).
For me it looks like the compiler uses f's own declaration (left hand side) to complete its implementation (right hand side).
Is this really the intended behavior? At runtime this results in unexpected behavior with null values (mostly NPEs for me).
This is happening because f is declared as implicit. So in a way the right hand side of implicit val f: Foo.type = implicitly[Foo.type] resolves to the implicit val f itself !
If you remove the implicit from that line the compilation would fail.
What i am wondering is why are you using such a line though.
This is definitely a issue to me. Someone looks like already took a note last year though.
Enhancement Request
Related
In Scala REPL I can use Seq[String]() as a default value for a parameter of type Seq[T].
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int
scala> d()
res0: Int = 12
Trying the same in IDEA, it complains “Seq[String] doesn't conform to expected type Seq[T]”. Why?
IntelliJ IDEA 2016.2.4
Scala Plugin 2016.2.1
Scala 2.11.7
Note 1: Sorry, I know that my example function does not make much sense. However, my real (and useful) function is unnecessarily complex to post it here.
Note 2: At first, instead of type T my type name in the example was Any which was not a good idea (because it shadowed scala.Any) and caused some confusion. Thus I fixed that.
When you say def d[Any], the Any here is a generic place holder. It does not point to class Any in scala. It basically shadows the Any class defined globally in scala. So, when you assign Seq[String] to Seq[Any], the compiler does not know any relation between String and Any. Note that Any could be replaced with any character / word as generic place holder. The result would be the same.
Now coming, to why this works in REPL, I am not exactly sure why REPL accepts if Seq[String] when given as a default value, but I was able to reproduce the error in repl when I do the same operation inside the method body.
The following code in REPL throws error:
def d[Any](foo: Seq[Any]) = {
val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found : Seq[String]
required: Seq[Any]
val a: Seq[Any] = Seq[String]()
^
I am not sure why REPL was not able to catch the error while given as a default argument.
One alternative theory is, in general when you use generics, the value of the type will be determined based on the caller. For example,
def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String
So, when you give default value, it assigns the value of String to Any. hence the compilation success.Intellij's Type Checker works based on the first theory and shows an error. But strangely as someone pointed out earlier, the compilation succeeds.
I'm new to Scala and I'm using the shapeless library to manipulate tuples. (Though this isn't specific to shapeless)
I've run in to a problem related to implicit parameters, which I don't quite understand. Here are there signatures:
def reverse(implicit reverse: Reverse[T]): reverse.Out = reverse(t)
def drop[N <: Nat](implicit drop: Drop[T, N]): drop.Out = drop(t)
And here is it in use:
val foo = ("foo","bar","other").reverse
val bar = ("foo","bar","other").drop(1)
However on Scala 2.10 I get this error:
Error:(25, 37) could not find implicit value for parameter reverse:
shapeless.ops.tuple.Reverse[(String, String, String)]
val zzy = ("foo","bar","other").reverse
Error:(29, 37) not enough arguments for method reverse: (implicit
reverse: shapeless.ops.tuple.Reverse[(String, String,
String)])reverse.Out. Unspecified value parameter reverse.
val foo = ("foo","bar","other").reverse
^
I'm not sure what the implicit parameter is that it is trying to reference, or why I need it. Also, this seems to work on 2.11 (but IntelliJ flags it)
On Scala 2.10.x you need to have the macro-paradise plugin included in your build: see the shapeless documentation here.
IntelliJ often reports spurious errors against code which uses aspects of the Scala type system which it doesn't have adequate support for. This is especially true of code which uses dependent method types as reverse and drop above do (notice that the result type of the methods depend on the argument values). In all cases the command line compiler is authoritative.
I run scala repl create simple value with Set function and try to figure out what flavor of Set was created.
$ scala
Welcome to Scala version 2.10.3-20130923-000000-e2fec6b28d (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val s = Set(0,3,1)
s: scala.collection.immutable.Set[Int] = Set(0, 3, 1)
scala> :type s
scala.collection.immutable.Set[Int]
scala> s.getClass
res0: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.Set$Set3
That does make thing clear for me. I read scaladoc for the Set and found out that Set is a generic trait that may have different concrete implementations.
So what implementation of the set trait was used this time inside REPL? How can I figure it out without deeping in scala source code and performing other complicated tasks? It would be perfect if searching the type would require only REPL itself.
I get confused out of nothing. Set3 is a valid class name, not a sort of garbage. So, the right way to determine class:
scala> val s = Range(0,1000).toSet
scala> s.getClass
res0: Class[_ <: scala.collection.immutable.Set[Int]] = class scala.collection.immutable.HashSet$HashTrieSet
With that the answer should be closed
I understand in Scala that Int is implicitly converted to RichInt. Where in the source does that occur (I was browsing the Scala source, but I couldn't find it...)
Look at Predef.intWrapper(Int): RichInt
This is inherited by Predef from LowPriorityImplicits. Inherited implicits have lower priorities than non inherited ones.
Note that by browsing library source you don't really get to see the conversion. The best way to see it on small snippet is to compile it (or run it in the REPL) with the -Xprint:typer option. This will show the conversion that is inserted by the typer to make the code compile when the types don't match:
$ scala -Xprint:typer
scala> 3.abs
[[syntax trees at end of typer]]// Scala source: <console>
// stuff removed
private[this] val res0: Int = scala.this.Predef.intWrapper(3).abs;
// more stuff removed
}
Using Scala's command line REPL:
def foo(x: Int): Unit = {}
def foo(x: String): Unit = {println(foo(2))}
gives
error: type mismatch;
found: Int(2)
required: String
It seems that you can't define overloaded recursive methods in the REPL. I thought this was a bug in the Scala REPL and filed it, but it was almost instantly closed with "wontfix: I don't see any way this could be supported given the semantics of the interpreter, because these two methods must to be compiled together." He recommended putting the methods in an enclosing object.
Is there a JVM language implementation or Scala expert who could explain why? I can see it would be a problem if the methods called each other for instance, but in this case?
Or if this is too large a question and you think I need more prerequisite knowledge, does someone have any good links to books or sites about language implementations, especially on the JVM? (I know about John Rose's blog, and the book Programming Language Pragmatics... but that's about it. :)
The issue is due to the fact that the interpreter most often has to replace existing elements with a given name, rather than overload them. For example, I will often be running through experimenting with something, often creating a method called test:
def test(x: Int) = x + x
A little later on, let's say that I'm running a different experiment and I create another method named test, unrelated to the first:
def test(ls: List[Int]) = (0 /: ls) { _ + _ }
This isn't an entirely unrealistic scenario. In fact, it's precisely how most people use the interpreter, often without even realizing it. If the interpreter arbitrarily decided to keep both versions of test in scope, that could lead to confusing semantic differences in using test. For example, we might make a call to test, accidentally passing an Int rather than List[Int] (not the most unlikely accident in the world):
test(1 :: Nil) // => 1
test(2) // => 4 (expecting 2)
Over time, the root scope of the interpreter would get incredibly cluttered with various versions of methods, fields, etc. I tend to leave my interpreter open for days at a time, but if overloading like this were allowed, we would be forced to "flush" the interpreter every so often as things got to be too confusing.
It's not a limitation of the JVM or the Scala compiler, it's a deliberate design decision. As mentioned in the bug, you can still overload if you're within something other than the root scope. Enclosing your test methods within a class seems like the best solution to me.
% scala28
Welcome to Scala version 2.8.0.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def foo(x: Int): Unit = () ; def foo(x: String): Unit = { println(foo(2)) }
foo: (x: String)Unit <and> (x: Int)Unit
foo: (x: String)Unit <and> (x: Int)Unit
scala> foo(5)
scala> foo("abc")
()
REPL will accept if you copy both lines and paste both at same time.
As shown by extempore's answer, it is possible to overload. Daniel's comment about design decision is correct, but, I think, incomplete and a bit misleading. There's no outlawing of overloads (since they are possible), but they are not easily achieved.
The design decisions that lead to this are:
All previous definitions must be available.
Only newly entered code is compiled, instead of recompiling everything ever entered every time.
It must be possible to redefine definitions (as Daniel mentioned).
It must be possible to define members such as vals and defs, not only classes and objects.
The problem is... how to achieve all these goals? How do we process your example?
def foo(x: Int): Unit = {}
def foo(x: String): Unit = {println(foo(2))}
Starting with the 4th item, A val or def can only be defined inside a class, trait, object or package object. So, REPL puts the definitions inside objects, like this (not actual representation!)
package $line1 { // input line
object $read { // what was read
object $iw { // definitions
def foo(x: Int): Unit = {}
}
// val res1 would be here somewhere if this was an expression
}
}
Now, due to how JVM works, once you defined one of them, you can't extend them. You could, of course, recompile everything, but we discarded that. So you need to place it in a different place:
package $line1 { // input line
object $read { // what was read
object $iw { // definitions
def foo(x: String): Unit = { println(foo(2)) }
}
}
}
And this explains why your examples are not overloads: they are defined in two different places. If you put them in the same line, they'd all be defined together, which would make them overloads, as shown in extempore's example.
As for the other design decisions, each new package import definitions and "res" from previous packages, and the imports can shadow each other, which makes it possible to "redefine" stuff.