Weird Scala bug related to implicit conversions on default constructor parameters - scala

Consider the file bug.scala:
package sandbox
object Foo {
implicit def stringToInt(s: String) = 5
}
import Foo._
class Boo(val a: Int = "foo" / 3) {
val b: Int = "foo" / 3
def c(d: Int = "foo" / 3) = d
}
It defines an implicit conversion, imports it, and uses it in three slightly different scenarios. Compile it:
E:\prog\scala\test>scalac bug.scala
bug.scala:9: error: value / is not a member of java.lang.String
class Boo(val a: Int = "foo" / 3) {
^
one error found
The implicit conversion seems not to be working when used for a default constructor parameter, but works for the other scenarios.
Now watch this:
package sandbox
object Foo {
implicit def stringToInt(s: String) = 5
}
object dummy
import Foo._
import dummy._
class Boo(val a: Int = "foo" / 3) {
val b: Int = "foo" / 3
def c(d: Int = "foo" / 3) = d
}
We've simply added an empty object and imported it. Now the file compiles without errors!
I see two possibilities here: 1) My head is messing with me. 2) There's a bug in the compiler. Can anyone confirm it's the latter?
(Using Scala 2.8.1.)

Definitely a bug. I've lodged it on your behalf.
https://issues.scala-lang.org/browse/SI-4141

Related

Scala returns no annotations for a field

I have this:
class Max(val value : Int) extends StaticAnnotation{}
class Child() extends Parent {
#Max(5) val myMember= register("myMember")
}
abstract class Parent {
def register(fieldName : String) = {
val cls = getClass
import scala.reflect.runtime.universe._
val mirror = runtimeMirror(cls.getClassLoader)
val clsSymbol = mirror.staticClass(cls.getCanonicalName)
val fieldSymbol = clsSymbol.typeSignature.member(TermName(fieldName))
println(s"${fieldSymbol.fullName} " + fieldSymbol.annotations.size)
}
}
this does not work, somehow, it returns 0 annotations, if instead, I put the annotation on the class, then I can read it fine. Why?
Discovered that the previous line:
clsSymbol.typeSignature.member(TermName(fieldName))
was returning the symbol of the auto generated getter for the "val" (which of course does not have any annotation), instead of the symbol from the val itself. If instead I do:
clsSymbol.toType.decl(TermName(s"${fieldName} "))
that seems to work fine. For any reason that I do not know, if I write a space at the end of the TermName, then it returns the field symbol with the annotations.
Adding a bit of additional information to your answer to demonstrate and ilustrate the problem:
scala> import scala.annotation.StaticAnnotation
import scala.annotation.StaticAnnotation
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> class Max(val value : Int) extends StaticAnnotation
defined class Max
scala> class Child {
| #Max(5) val myMember = 2
| }
defined class Child
scala> val cls = classOf[Child]
cls: Class[Child] = class Child
scala> val mirror = runtimeMirror(cls.getClassLoader)
mirror: reflect.runtime.universe.Mirror = JavaMirror with... (I truncated this part which was super long and not useful)
scala> mirror.classSymbol(cls).selfType.decls
res0: reflect.runtime.universe.MemberScope = SynchronizedOps(constructor Child, value myMember, value myMember)
scala> println(mirror.classSymbol(cls).selfType.decls)
Scope{
def <init>: <?>;
val myMember: <?>;
private[this] val myMember: scala.Int
}
scala> mirror.classSymbol(cls).selfType.decls.map(_.annotations)
res2: Iterable[List[reflect.runtime.universe.Annotation]] = List(List(), List(), List(Max(5)))
scala> mirror.classSymbol(cls).selfType.decls.map(_.isMethod)
res4: Iterable[Boolean] = List(true, true, false)
scala> mirror.classSymbol(cls).selfType.decls.map(_.asTerm.name)
res15: Iterable[reflect.runtime.universe.TermName] = List(<init>, myMember, myMember )
Only one of them include the annotation, and we can see that the last one which is the actual attribute you defined and not the synthetic getter that the compiler defined automatically, has a space at the end of its name ! I really wonder who thought it was a good idea to do such horrible thing, but it seems to be the reality. I am no Scala expert but this whole API seems very complex to me and unpractical to work with. It probably suffers from the complexity of Scala as a language itself, which under appearances of simplicity and "magic" features, actually has some very complex mechanisms.
To me, a better API should propose one method to get def declarations and another one for getting val and var declarations. Also, the names should probably not be dedupes by a completely unexpected space at the end of the name !
PS: Martin Odersky explained this design choice on the following thread: https://contributors.scala-lang.org/t/design-choice-reflection-valdef-and-synthetic-getter/565

Illegal character error when define Seq

I've created new Play-Scala project and added my first model class (case class).
I have a mock repository for my model class and when I try to add Seq variable in the repository class, project's compilation fails.
If I create companion object for my model class and add Seq variable inside this object, compilation is succeed. Without any Seq definition compilation is fine too.
Error text is very strange for me: Error:(7, 25) illegal character '\u2028'
I use IntelliJ Idea and file encoding is UTF-8.
My classes code:
case class Teacher(id: Long, name: String) extends BaseItem
object Teacher {
val list = Seq(1, 2, 3) //this compiles
}
class TeacherRepository extends BaseRepository[Teacher] with BaseTeacherRepository {
val int = List(1, 2, 3
 
 ) //this one fails
override def list: Seq[Teacher] = ???
override def getById(id: Long): Option[Teacher] = ???
override def getByLanguage(language: String): Seq[Teacher] = ???
}
Edited: It seems like IDE does not show line separators before closing bracket in the second case.
Valid code should be
val int = List(1, 2, 3)
Why not just format your code correctly?
class TeacherRepository extends BaseRepository[Teacher] with BaseTeacherRepository {
val int = List(1, 2, 3)
...
}

Scala - construction order and early definition syntax

I'm trying to learn Scala and thought I would begin by reading "Scala for the Impatient". There he cites the problem of construction order by using the following classes:
class Animal {
val range: Int = 10
val env: Array[Int] = new Array[Int](range)
}
class Ant extends Animal {
override val range: Int = 2
}
and then he explained why the env ends up being an empty Array[Int] and proceeds to explain ways to prevent that, including the early definition syntax.
But... can't I prevent that just by doing this:
class Animal(val range: Int = 10) {
val env: Array[Int] = new Array[Int](range)
/* do animal stuff */
}
class Ant(override val range: Int = 2) extends Animal(range) {
/* do ant stuff */
}
??? Why is the early definition syntax really necessary?
I think a better way to look at the need for early instantiation comes from mixing in traits. With traits, you won't have a constructor that you can tweak to get around this kind of issue. Consider this very trivial and completely unrealistic example:
trait Foo{
val bar:String
val barLength = bar.length()
}
object MyFoo extends Foo{
val bar = "test"
}
As it stands right now, this code will throw a NullPointerException when MyFoo is created because bar will not yet be defined when bar.length() is invoked. But if you used early initialization, and redefined MyFoo as:
object MyFoo extends {val bar = "test"} with Foo{
}
then everything works just fine.

In Scala, member of a class is not found when its instance is accessed from a list [Class]

I have a feeling that the problem I am facing has something to do with Type Erasure of Scala, but as a newbie I can't put my fingers on it. Need some help here.
First, the code:
class C (val i: Int) {
def mkString() = { println("C.i =" + this.i) }
object C {
implicit val cOrdering = new Ordering [C]
{
def compare (a: C, b: C)=
{
a.i compare b.i;
}
}
Then, I create another class which holds a collection of class 'C' thus:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) {
var internalCollection = new TreeSet[C]()
def + (c:C): ContainerOfC [C] = {
this.internalCollection += c
this
}
def mkStringOfElems () = {
val y = this.internalCollection.toList
println (y.head.i) // <--- Problem here
}
}
This is what REPL tells me:
error: value i is not a member of type parameter C
println(y.head.i)
^
I have checked the type of 'y' out there: it is a List[C]. If so, why am I not allowed to access the 'i'? It is a construction parameter alright, but it is a val and hence, can be treated as a member variable, can't it be?
I have gone through a few of the other related posts in the forum, and Manifests and Typetags are possible ways out here. But, I am not sure if I need to go to that level for this simple use-case.
This have a strange and familiar feeling of "been there, done that".
How about you try to change this:
class ContainerOfC [C] (s:Int) (implicit ordering: cOrdering[C]) { ... }
to this without the type parameter C in the declaration :
class ContainerOfC(s:Int) (implicit ordering: cOrdering[C]) { ... }
The code you showed created a class and specific type C. When you later write class ContainerOfC[C], that C is a type parameter that could be named by any other identifier. It is the same as defining class ContainerOfC[A] where A does not have any relation to the class/type C defined in the earlier code. In your example the type parameter C would shadow the name of the class defined earlier... The error message is indicating that C does not have a value i and that's because the compiler is not referring to the same C than you are thinking of.
Edit: just so you know quickly if we are on the same page without getting bogged down in other compilation errors, here are a few edits to make the code compile and using more commonly used indentation and brace style:
class C(val i: Int) {
def mkString() = println("C.i =" + this.i)
}
object C {
implicit val cOrdering = new Ordering[C] {
def compare(a: C, b: C) = a.i compare b.i
}
}
class ContainerOfC(s: Int)(implicit ordering: Ordering[C]) {
var internalCollection = new collection.mutable.TreeSet[C]()
def +(c: C): ContainerOfC = {
this.internalCollection += c
this
}
def mkStringOfElems() = {
val y = this.internalCollection.toList
println(y.head.i)
}
}

Scala - DSL: overloaded prefix function ambiguity

In my DSL I want this functionality:
class Test {
val compA = dependant(true, true)(Component("parameters"))
//and this shortcut:
val compB = dependant Component("parameters")
}
where:
def dependant(onEnable: Boolean, onDisable: Boolean)(c: Component): Component = {
//...
}
def dependant(c: Component): Component = dependant(false, true)(c)
all is fine, however, I cannot use this syntax:
val compB = dependant Component("parameters")
because it says
ambiguous reference to overloaded definition, both method dependant in
class Test of type (onEnable: Boolean, onDisable: Boolean)(c:
Component)Component and method dependant in class Test of type (c:
Component)Component match expected type ?
But if I enclose the parameter in parenthesis:
val compB = dependant(Component("parameters"))
the error is gone. Obviously, the compiler fails in desugarating the parenthesisless case. Is this expected or am I doing something wrong? If this is expected, then Why? How can I reclaim the ability to use the method dependant as a prefix, without parenthesis?
In dependant Component("parameters") you are trying to use a prefix notation to call the dependant. Scala's support for prefix notation is limited.
See Scala - Prefix Unary Operators.
An alternative is to use a postfix notation (as in Component("parameters") dependant).
If you can modify the implementaiton of Componenet, this simply means adding the dependant methods to Component:
class Component(name: String) {
def dependant: Component = //...
def dependant(onEnable: Boolean, onDisable: Boolean): Component = {
//...
}
}
class Test {
val compA = Component("parameters") dependant(true, true)
val compB = Component("parameters") dependant
}
If you can't modify Component, you can use the "pimp my library idiom".
See http://www.decodified.com/scala/2010/12/02/the-quickpimp-pattern.html for a short introduction to this idiom (along with a warning on using an anonymous class as below):
case class Component(name: String)
implicit def toPostifxDependentOps( c: Component ) = new {
def dependant: Component = dependant(false, true)
def dependant(onEnable: Boolean, onDisable: Boolean): Component = {
//...
}
}
class Test {
val compA = Component("parameters") dependant(true, true)
val compB = Component("parameters") dependant
}
Writing myObject functionName paraminstead of myObject.functionName(param) works as expected if you propvide an object. If you don't, the compiler will be lost. For example:
scala> println("Hello")
Hello
scala> println "Hello"
<console>:1: error: ';' expected but string literal found.
println "Hello"
^
A possible workaround: create an object to wrap your method:
scala> case class Component(name: String, components: Option[Component] = None)
defined class Component
scala> object depends {def on(c: Component) = Component("dependant", Some(c))}
defined module depends
scala> depends on Component("foo")
res3: Component = Component(dependant,Some(Component(foo,None)))