Following is a Scala class with constructors. My questions are marked with ****
class Constructors( a:Int, b:Int ) {
def this() =
{
this(4,5)
val s : String = "I want to dance after calling constructor"
//**** Constructors does not take parameters error? What is this compile error?
this(4,5)
}
def this(a:Int, b:Int, c:Int) =
{
//called constructor's definition must precede calling constructor's definition
this(5)
}
def this(d:Int)
// **** no equal to works? def this(d:Int) =
//that means you can have a constructor procedure and not a function
{
this()
}
//A private constructor
private def this(a:String) = this(1)
//**** What does this mean?
private[this] def this(a:Boolean) = this("true")
//Constructors does not return anything, not even Unit (read void)
def this(a:Double):Unit = this(10,20,30)
}
Could you please answer my questions in the **** above? For example Constructors does not take parameters error? What is this compile error?
Ans 1:
scala> class Boo(a: Int) {
| def this() = { this(3); println("lol"); this(3) }
| def apply(n: Int) = { println("apply with " + n) }
| }
defined class Boo
scala> new Boo()
lol
apply with 3
res0: Boo = Boo#fdd15b
First this(3) is a delegation to primary constructor. The second this(3) invokes this object's apply method i.e. expands to this.apply(3). Observe the above example.
Ans 2:
= is optional in constructor definitions as they don't really return anything. They have different semantics from regular methods.
Ans 3:
private[this] is called object-private access modifier. An object cannot access other object's private[this] fields even though they both belong to the same class. Thus it's stricter than private. Observe the error below:
scala> class Boo(private val a: Int, private[this] val b: Int) {
| def foo() {
| println((this.a, this.b))
| }
| }
defined class Boo
scala> new Boo(2, 3).foo()
(2,3)
scala> class Boo(private val a: Int, private[this] val b: Int) {
| def foo(that: Boo) {
| println((this.a, this.b))
| println((that.a, that.b))
| }
| }
<console>:17: error: value b is not a member of Boo
println((that.a, that.b))
^
Ans 4:
Same as Ans 2.
Related to question 2 is:
Scala Auxilliary Constructor behavior
This is causing the error, the lack of (default) parameters for int b and int c throws called constructor's definition must precede calling constructor's definition
Related
class S {
case class A(a: Int)
}
abstract class R(val s: S) {
type T1 = R.this.s.A
type T2 = s.A
implicitly[T1 =:= T2] // compiles
type T3 = R.this.type
type T4 = this.type
implicitly[T3 =:= T4] // compiles
val v1 = R.this // v1 == `this`
val v2 = R.this.s // v2 == `s`
}
Looks like the .this part has no effect whatsoever. To make a concrete question:
When do you use the .this ?
It matters for inner classes. E.g.
class Outer(val x: Int) {
class Inner(val x: Int) {
def outer_this = Outer.this.x
def inner_this = this.x // or just x
}
}
val outer = new Outer(0)
val inner = new outer.Inner(1)
println(inner.outer_this) // 0
println(inner.inner_this) // 1
Each Outer.Inner instances "belongs to" a specific Outer instance, and can refer to that instance as Outer.this. By itself x in Inner refers to its own property, so if you need the enclosing instance's x property, you write Outer.this.x.
One rule is Scala never infers singleton type this.type. For example first consider the mechanics of it
scala> trait Foo {
| type T
| def f() = this // we left out the return type to see what Scala will infer
| }
// defined trait Foo
scala> new Foo { type T = String }
val res0: Foo{T = String} = anon$1#6d3ad37a
scala> res0.f()
val res1: Foo = anon$1#6d3ad37a
Note how res1 has return type of Foo and not Foo { type T = String }, so we have lost some type information
scala> val x: res1.T = ""
1 |val x: res1.T = ""
| ^^
| Found: ("" : String)
| Required: res1.T
Note compiler does not know res1.T is actually a String. So compiler did not infer the singleton type this.type which would have all the type information including what type member T was instantiated to
scala> trait Foo {
| type T
| def f(): this.type = this
| }
// defined trait Foo
scala> new Foo { type T = String }
val res2: Foo{T = String} = anon$1#7d381eae
scala> res2.f()
val res3: Foo{T = String} = anon$1#7d381eae
scala> val x: res3.T = ""
val x: res3.T = ""
Note how after we explicitly declared singleton return type this.type compiler knows T is a String.
Here is another mechanical example of what happens because compiler does not infer singleton type this.type
scala> trait Foo {
| def f() = this // let inference do its thing
| }
// defined trait Foo
scala> trait Bar {
| def g() = 42
| }
// defined trait Bar
scala> trait Bar extends Foo {
| def g(): Int = 42
| }
// defined trait Bar
scala> new Bar {}
val res5: Bar = anon$1#6a9a6a0c
scala> res5.f()
val res6: Foo = anon$1#6a9a6a0c
scala> res6.g()
1 |res6.g()
|^^^^^^
|value g is not a member of Foo
Note how f() call typed to Foo and not perhaps expected Bar. On the other hand if we provide explicit singleton return type this.type then
scala> trait Foo {
| def f(): this.type = this
| }
// defined trait Foo
scala> trait Bar extends Foo {
| def g(): Int = 42
| }
// defined trait Bar
scala> new Bar {}
val res7: Bar = anon$1#4707d60a
scala> res7.f()
val res8: Bar = anon$1#4707d60a
scala> res8.g()
val res9: Int = 42
we see f() call typed to Bar.
Those were the mechanics but what about practical applications? Two uses I am aware of are:
supporting fluent style of programming
supporting summoners of type class instances (see also Scala 3 summon)
With a type like trait A[T], finding an implicit in scope is simply implicitly[A[SomeType]]
Can this be done and, if so, how is this done where the type-parameter is replaced with an abstract type member, like in trait A { type T }?
You can do
implicitly[A { type T = Int }
but you risk to lose precision:
scala> trait Foo { type T ; val t: T }
defined trait Foo
scala> implicit val intFoo: Foo { type T = Int } = new Foo { type T = Int ; val t = 23 }
intFoo: Foo{type T = Int} = $anon$1#6067b682
scala> implicitly[Foo].t // implicitly loses precision
res0: Foo#T = 23
To solve this problem, you can use the newly introduced the method, from the shapeless library (from which I've take the example above)
scala> the[Foo].t // the retains it
res1: Int = 23
scala> the[Foo].t+13
res2: Int = 36
I just realized this can be done with implicitly[A { type T = SomeType }]
I would like to give a value of a type with an abstract type to a class and later use it's path dependent type. Look at the following example (using Scala 2.10.1):
trait Foo {
type A
def makeA: A
def useA(a: A): Unit
}
object Test {
class IntFoo extends Foo {
type A = Int
def makeA = 1
def useA(a: Int) = println(a)
}
class FooWrap(val a: Foo) {
def wrapUse(v: a.A) = a.useA(v)
}
val foo = new IntFoo
/* Path dependent locally */
val bar = foo
bar.useA(foo.makeA) // works
/* Path dependent through class value */
val fooWrap = new FooWrap(foo)
fooWrap.a.useA(foo.makeA) // fails
// error: type mismatch; found : Int required: Test.fooWrap.a.A
fooWrap.wrapUse(foo.makeA) // fails
// error: type mismatch; found : Int required: Test.fooWrap.a.A
}
First, I do not understand the fundamental difference between the local and the class-value case (note the public, immutable value) and why the type checking fails (because obviously Test.fooWrap.a.A =:= foo.A). Is this a limitation of the Scala compiler?
Second, how can I achieve what I am trying to do?
UPDATE
It seems that this can be achieved by using generics and inline type-constraints:
class FooWrap[T](val a: Foo { type A = T }) {
def wrapUse(v: T) = a.useA(v)
}
However, in my case, A is actually a higher-kinded type, so the example becomes:
trait Foo {
type A[T]
def makeA[T]: A[T]
def useA(a: A[_]): Unit
}
object Test {
class OptFoo extends Foo {
type A[T] = Option[T]
def makeA[T] = None
def useA(a: A[_]) = println(a.get)
}
class FooWrap(val a: Foo) {
def wrapUse(v: a.A[_]) = a.useA(v)
}
val foo = new OptFoo
/* Path dependent locally (snip) */
/* Path dependent through class value */
val fooWrap = new FooWrap(foo)
fooWrap.a.useA(foo.makeA) // fails
// polymorphic expression cannot be instantiated to expected type;
// found : [T]None.type required: Test.fooWrap.a.A[_]
fooWrap.wrapUse(foo.makeA) // fails
// polymorphic expression cannot be instantiated to expected type;
// found : [T]None.type required: Test.fooWrap.a.A[_]
}
In your original question, your problem is that the Scala compiler is unable to prove equality of the result type of foo.makeA with the argument type of fooWrap.a.useA. To do that it would need to be able to prove the identity of foo with fooWrap.a which we can intuitively see must be the case here, but which isn't straightforward for the compiler to track.
There are a couple of ways to work around this problem. First, you could use fooWrap.a uniformly in place of foo,
scala> fooWrap.a.useA(fooWrap.a.makeA)
1
Now it's simple for the compiler to recognize the prefix of A (fooWrap.a) as being the same in both occurrences.
Second, you could parametrize FooWrap in a way which captures the type of its Foo argument more precisely,
scala> class FooWrap[F <: Foo](val a: F) {
| def wrapUse(v: a.A) = a.useA(v)
| }
defined class FooWrap
scala> val fooWrap = new FooWrap(foo)
fooWrap: FooWrap[IntFoo] = FooWrap#6d935671
scala> fooWrap.a.useA(foo.makeA)
1
Here the type argument of FooWrap is inferred as IntFoo rather than as bare Foo, hence A is known to be exactly Int, as it is in the result type of foo.makeA.
In your update you introduce an additional wrinkle: you change the signature of useA to,
def useA(a: A[_]): Unit
The _ here is an existential which will frustrate all attempts to coax the compiler into proving useful type equalities. Instead you need something along the lines of,
trait Foo {
type A[T]
def makeA[T]: A[T]
def useA[T](a: A[T]): Unit
}
class OptFoo extends Foo {
type A[T] = Option[T]
def makeA[T]: A[T] = None
def useA[T](a: A[T]) = a map println
}
class FooWrap[F <: Foo](val a: F) {
def wrapUse[T](v: a.A[T]) = a.useA(v)
}
val foo = new OptFoo
Sample REPL session,
scala> val fooWrap = new FooWrap(foo)
fooWrap: FooWrap[OptFoo] = FooWrap#fcc10a7
scala> fooWrap.a.useA(foo.makeA)
scala>
The higher kinded-type can be added to FooWrap as generic parameter, too:
class FooWrap[T[V]](val a: Foo { type A[V] = T[V] }) {
def wrapUse(v: T[_]) = a.useA(v)
}
but (in this example) the inference fails:
val fooWrap = new FooWrap[Option](foo)
Otherwise:
- type mismatch; found : Test.foo.type (with underlying type Test.OptFoo) required: Foo{type A[V] = T[V]}
- inferred kinds of the type arguments (Option[V]) do not conform to the expected kinds of the type parameters (type T) in class FooWrap. Option[V]'s type parameters do not match type T's expected
parameters: class Option has one type parameter, but type T has one
Any other, nicer solutions?
I want to do this:
abstract class Context {
def getInt(id: Int): Int
}
abstract class Dependency[+T]
(val name: String, val id: Int)
extends Function1[Context,T]
class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
def apply(implicit context: Context): Int =
context.getInt(id)
}
But then I get an error message like this:
class IntDependency needs to be abstract, since method apply in trait
Function1 of type (v1: Context)Long is not defined (Note that T1 does
not match Context)
I understand that implicits should normally be part of the second parameter list, but I can't work out how to code it so it compiles, and gives the result I want.
Explanation: I'm trying to create a framework where one can define "Function" object, which can depend on other functions to compute their value. All functions should only take a single Context parameter. The context know the "result" of the other functions. The function instances should be immutable, with the state residing in the context. I want the functions to create "dependency" fields at creation time, which take the context implicitly, and return the value of the dependency within that context, so that accessing the dependency inside of the apply method "feels like" accessing a parameter or field, that is without explicitly giving the context as parameter to the dependency.
Are you sure you need your Dependency to extend a Function? Because if you don't, just leave the extends Function1[Context,T] part out and your code will work.
If you really need to extend a Function than I don't know of a solution in your case. But there are cases where you could try to overload the apply method. Like here:
scala> val sum = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = (b: Int) => a + b
| def apply(a: Int)(implicit b: Int) = a + b
|}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>
scala> sum(2)(3)
res0: Int = 5
scala> implicit val b = 10
b: Int = 10
scala> sum(2)
res1: Int = 12
A method may have its final parameter section marked implicit; it need not be the second section, although that is most commonly seen.
But it seems that when a subclass marks a parameter section implicit, it is no longer considered to override the method in the superclass.
scala> new (Int => Int) { def apply(implicit i: Int) = i }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
(Note that T1 does not match Int)
new (Int => Int) { def apply(implicit i: Int) = i }
^
scala> trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
<console>:8: error: object creation impossible, since method f in trait F1 of type (a: Any)Unit is not defined
trait F1 { def f(a: Any) }; new F1 { def f(implicit a: Any) = () }
^
The spec does not specifically mention this (§5.1.4 Overriding), so it may be an implementation restriction, or an bug.
Its sure, that your apply method signature with implicit doesn´t conform with the signature of Function1.apply.
Hopefully I get your problem right, so what about (assuming that your context is mutable and perhaps singleton) having the implicit context injected at creation time? Is that possible in your case?
class IntDependency(id: Int)(implicit context: Context) extends Dependency[Int](id)
But then I wonder (and still was wondering before) what to do with the context argument at the apply method.
Here is the working solution:
abstract class Context {
def getInt(id: Int): Int
}
abstract class Dependency[+T]
(val name: String, val id: Int) {
def get(context: Context): T
}
class IntDependency(name: String, id: Int)
extends Dependency[Int](name, id) {
def get(context: Context): Int =
context.getInt(id)
}
implicit def intDep2Int(dep: IntDependency)
(implicit context: Context): Int =
dep.get(context)
Section 4.6.2 of the Scala Language Specification Version 2.8 describes repeated parameters and says:
The last value parameter of a parameter section may be suffixed by “*”, e.g. (..., x:T*). The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T].
However, this code:
abstract class A { def aSeq : Seq[A] }
class B(val aSeq : A*) extends A
class C extends B { override val aSeq :Seq[A] = Seq() }
give an error when compiled:
overriding value aSeq in class B of type A*; value aSeq has incompatible type
The compiler seems to indicate that A* is a distinct type from Seq[A].
Investigating the actual class of aSeq in this case shows it to be an instance of scala.collection.mutable.WrappedArray$ofRef but even the following code fails to compile with the same message:
class C extends B { override val aSeq = new ofRef(Array[A]()) }
So the question is, how do I go about overriding a member defined by a repeated parameter on the class?
In case you're wondering where this is coming from, that is exacly what scala.xml.Elem does to override the child method in scala.xml.Node.
Your issue can be summarized as:
scala> class A { def aSeq(i: Int*) = 1 }
defined class A
scala> class B extends A { override def aSeq(i: Seq[Int]) = 2 }
<console>:6: error: method aSeq overrides nothing
class B extends A { override def aSeq(i: Seq[Int]) = 2 }
The methods have different types. The spec says (emphasis mine):
The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T]
As Int* and Seq[Int] aren't inside the method, this particular sentence does not apply.
Interestingly, this following code shows that the methods have different types before erasure but the same after:
scala> class G { def aSeq(i:Int*) = 1; def aSeq(i:Seq[Int]) = 2 }
<console>:5: error: double definition:
method aSeq:(i: Seq[Int])Int and
method aSeq:(i: Int*)Int at line 5
have same type after erasure: (i: Seq)Int
class G { def aSeq(i:Int*) = 1; def aSeq(i:Seq[Int]) = 2 }
So the question then becomes, why your B class can extend your A abstract class. There may be an inconsistency in the spec there. I don't know...
Edit: I re-read the spec and I can't figure out if there is anything related to repeated parameters and overriding. There does not seem to be anything about return type of repeated parameters, which is what you get for the val aSeq accessor method.
I think Mark's answer is a perfectly valid approach. In case you can't follow it, you can use the following workaround:
class C extends B {
private def aSeqHelper(a: A*) = a
override val aSeq = aSeqHelper(Seq[A](): _*)
}
So for instance:
import scala.xml._
class ElemX extends Elem("pref", "label", <xml a="b"/>.attributes, TopScope) {
private def childHelper(c: Node*) = c
override val child = childHelper(<foo/><bar/>: _*) }
Then:
scala> new ElemX
res4: ElemX = <pref:label a="b"><foo></foo><bar></bar></pref:label>
The copy method of xml.Elem uses it like this
def copy(
prefix: String = this.prefix,
label: String = this.label,
attributes: MetaData = this.attributes,
scope: NamespaceBinding = this.scope,
child: Seq[Node] = this.child.toSeq
): Elem = Elem(prefix, label, attributes, scope, child: _*)
So you can override the value in the B constructor
class C extends B(aSeq = Seq(): _*)
Or declare it as a parameter of the class C
class C(seq: Seq[A]) extends B(aSeq = seq: _*)
Though I am not sure it answers your question!
The spec never allowed for repeated types to leak out in this way. The compiler was changed in July 2011 to enforce this.
For more background, check out the comments in the ticket:
https://issues.scala-lang.org/browse/SI-4176