Scala: using value field to implement a trait method - scala

I tried to do something like this in Scala
trait A {
def foo(i: Int): Int
}
class B(val foo: Int => Int = _ + 1) extends A
But somewhat surprisingly I got this error from the compiler:
error: class B needs to be abstract, since method foo in trait A of type (i: Int)Int is not defined
class B(val foo: Int => Int = _ + 1) extends A
And this didn't work either with the same error:
class C extends A {
val foo: Int => Int = _ + 1
}
However this (obviously) worked:
class D(val bar: Int => Int = _ + 1) extends A {
def foo(i: Int): Int = bar(i)
}
scala> (new D).foo(5)
res1: Int = 6
So the question is, why is Scala treating def foo(i: Int): Int = ... differently than val foo: Int => Int = ...

Because, def foo(i: Int): Int defined in the trait: is a function which takes an integer as input and returns an integer as the output.
Where as, val foo: Int => Int = _ + 1 defined in the class: is a function, which returns a function. That's the key point, you have not implemented the one from trait. The foo in the class B is returning a function and the returned function takes an integer as input and provided an integer in the output.

Finally, I found an embarrassingly simple solution to my problem. All I had to do was to change my trait into this:
trait A { def foo: Int => Int }
And now it works as desired:
class B(val foo: Int => Int = _ + 1) extends A
scala> (new B).foo(6)
res3: Int = 7

Related

Why implicit conversion is not applied to second argument?

When I try to compile the following code
case class A(x: Int = 0)
object Conversions {
case class Converter[T](c: T) {
def +[U](that: Converter[U]): String = "worked"
}
implicit def convert(c: A): Converter[A] = Converter[A](c)
implicit def convert(c: Int): Converter[Int] = Converter[Int](c)
}
object Main extends App {
import Conversions._
val a: String = A() + A()
val b: String = 1 + A() // FAIL
val c: String = A() + 1
val d: Int = 1 + 1
}
I get the following error message
error: type mismatch; found: A; required: String
What is the difference between Int and A, so that expression b fails, while a and c pass? What do I do to make it compile?
First, the difference is that Int already has another + method, which expects another Int and returns an Int;
If you add a similar method to A you'd get similar failures:
case class A(x: Int = 0) {
// this would be similar to Int's plus operation:
def +(other: A): A = A(x + other.x)
}
// now these would behave "symmetrically":
val a: A = A() + A()
val b: String = 1 + A() // FAIL
val c: String = A() + 1 // FAIL
val d: Int = 1 + 1
As for why that fact causes this specific failure - that's trickier, I assume it has to do with the order in which the compiler tries to "choose" the right implicit conversion based on the left and right argument.
If you replace the arithmetic + operator with, say plus:
def plus[U](that: Converter[U]): String = "worked"
your implicit conversions should work the way you expect:
val a = A() plus A() // worked
val b = 1 plus A() // worked
val c = A() plus 1 // worked
val d = 1 plus 1 // worked
Rather than a direct implicit conversion between Int and A, your implicit conversions are between Int and class Converter (and, between A and Converter). The compiler apparently is having a hard time sorting through the conversion rules between Int and A when it sees a + method well defined for Int – unless you provide a direct implicit conversion between Int and A like in the following example:
object A {
implicit def intToA(n: Int): A = A(n)
}
case class A(x: Int = 0) {
def +(that: A): A = A(this.x + that.x)
}
val a = A(1) + A(2) // A(3)
val b = 1 + A(1) // A(2)
val c = A() + 1 // A(1)
val d = 1 + 1 // 2
I have no clear understanding on why this attempt was successful, but I hope that it will be useful to other users. Here I'm matching on both arguments at the same time to minimize Scala's attempts to bruteforce correct tree of implicit conversions.
object Defs {
case class A(x: Int = 1)
case class B(x: Int = 2)
trait IsExpr[T] {
def conv(v: T): Int
}
implicit object aIsExpr extends IsExpr[A] {
override def conv(v: A): Int = v.x
}
implicit object bIsExpr extends IsExpr[B] {
override def conv(v: B): Int = v.x
}
implicit def canSum1[A, B](a: A, b: B)(implicit ca: IsExpr[A], cb: IsExpr[B]): Int = ca.conv(a) + cb.conv(b)
implicit def canSum2[A](a: A, b: Int)(implicit ca: IsExpr[A]): Int = ca.conv(a) + b
implicit def canSum3[A](a: Int, b: A)(implicit ca: IsExpr[A]): Int = a + ca.conv(b)
implicit def convert[A](a: A) = new {
def +[B](b: B)(implicit f: (A, B) => Int): Int = f(a, b)
}
}
object Main extends App {
import Defs._
val a: Int = A() + A()
val b: Int = 1 + A()
val c: Int = A() + 1
val d: Int = 1 + 1
}

Inheritance : override in class constructor

I am reading the example in this link http://www.tutorialspoint.com/scala/scala_classes_objects.htm
Example :
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
class Location(override val xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("Point x location : " + x);
println ("Point y location : " + y);
println ("Point z location : " + z);
}
}
object Test {
def main(args: Array[String]) {
val loc = new Location(10, 20, 15);
// Move to a new location
loc.move(10, 10, 5);
}
}
I didn't understand the utility of override keyword in class location constructor !
Why it is mentioned since we have an extends here ?
Thanks !
Given
scala> class A(val a: Int)
defined class A
If you try to define B like this:
scala> class B(val a: Int) extends A(a)
<console>:11: error: overriding value a in class A of type Int;
value a needs `override' modifier
class B(val a: Int) extends A(a)
compiler complains because it looks like you are trying to define a member a in class B and it already exists there through inheritance (from A). You need to add override to be explicit about your intentions in this case:
scala> class B(override val a: Int) extends A(a)
defined class B
More specifically you don't have to provide an override if you are overriding abstract members:
scala> trait A { def a: Int }
defined trait A
scala> class B(override val a: Int) extends A
defined class B
scala> class B(val a: Int) extends A
defined class B
However, to avoid unintended overrides when mixing in traits Scala protects you by requiring explicit override.
Consider this example:
No problem here:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B
defined class B
scala> new B with A
res0: B with A = $anon$1#3e29739a
You are saved from ambiguity:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B { def a: Int = 2 }
defined class B
scala> new B with A
<console>:13: error: <$anon: B with A> inherits conflicting members:
method a in class B of type => Int and
method a in trait A of type => Int
(Note: this can be resolved by declaring an override in <$anon: B with A>.)
new B with A
^
Resolve the conflict manually:
scala> trait A { def a: Int = 1 }
defined trait A
scala> class B { def a: Int = 2 }
defined class B
scala> new B with A { override val a = super[B].a }
res6: B with A{val a: Int} = $anon$1#76f6896b

Passing in An Operator as a Parameter

I'm doing an exercise in "Scala for the Impatient", Chapter 14, Q8:
Essentially I need to create a function (utilizing pattern matching) that takes in an operator and nodes, and it outputs the result of the operation. E.G. Node(+, Node(*, Leaf(2), Leaf(3)) Leaf(1)) should output 7.
Here are some of the given classes:
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
So I create a Node class, but I'm having difficulties figuring out how to pass in the operator.
case class Node(op: Function (what goes here?) , leaves: BinaryTree*) extends BinaryTree
I want to use pattern matching like so:
tree match {
case Node(op, leaves # _*) => op match {
case op : Function => leaves.reduceLeft(_ op _)
}
case leaf: Leaf => leaf.value
But the
case op : Function => leaves.reduceLeft(_ op _)
part is wrong. I don't know how to use the operator that's being passed in the Node class. What am I doing wrong here?
I am assuming the operator will be always going to be binary hence, our So called BinaryTree will have atleast two operands :
trait BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(op: Function2[Int, Int, Int], l1: BinaryTree*) extends BinaryTree
object Operators {
val + = (a: Int, b: Int) => a + b
val * = (a: Int, b: Int) => a * b
}
def f(tree: BinaryTree): Int = {
tree match {
case n: Node => n.l1.map(f).reduceLeft((r,c) => n.op(r,c))
case leaf: Leaf => leaf.value
}
}
Some test results:
Simple one:
scala> f(Node(Operators.*,Leaf(4),Leaf(2),Leaf(3)))
res4: Int = 24
scala> f(Node(Operators.+,
Node(Operators.*, Leaf(2), Leaf(1), Leaf(4), Leaf(5)), Leaf(6)))
res5: Int = 46
scala> f(Node(Operators.+,
Node(Operators.*, Leaf(2), Leaf(1), Leaf(4), Leaf(5)),
Node(Operators.+,Leaf(9),Leaf(9)), Leaf(6)))
res6: Int = 64
Quite complex:
scala> f(Node(Operators.+,
Node(Operators.*, Leaf(2), Leaf(1),
Node(Operators.* ,Leaf(4), Leaf(5) ,Leaf(2))),
Node(Operators.+,Leaf(9),Leaf(9)), Leaf(6),
Node(Operators.*, Leaf(2), Leaf(2))))
res7: Int = 108
It has more elegant solutions, but since you want it with pattern matching:
sealed abstract class BinaryTree
case class Leaf(value: Int) extends BinaryTree
case class Node(op: (Int, Int) => Int , leaves: BinaryTree*) extends BinaryTree
def calc(tree: BinaryTree): Int = tree match {
case Leaf(v) => v
case Node(op, h, leaves # _*) => leaves.foldLeft(calc(h))((a,b) => op(a,calc(b)))
}
object Operators {
def +(a: Int, b: Int): Int = a + b
def *(a: Int, b: Int): Int = a * b
}
val tree = Node(Operators.+, Node(Operators.*, Leaf(9), Leaf(3)), Leaf(1))
calc(tree)

In Scala, fetched value of declared field cast to its class-declared type

I would like to ask how to achieve the following in Scala. Consider
scala> case class C(i:Int)
defined class C
scala> val c = C(1)
c: C = C(1)
Given a field of interest, in this case
scala> val fname = "i"
fname: String = i
we would like to retrieve the original value and type of field i in c.
A first, naive, attempt included the following,
scala> val f = c.getClass.getDeclaredField(fname)
f: java.lang.reflect.Field = private final int C.i
scala> f.setAccessible(true)
scala> f.getType
res3: Class[_] = int
However,
scala> val a:Int = f.get(c)
<console>:11: error: type mismatch;
found : Object
required: Int
val a:Int = f.get(c)
^
Put another way, how to fetch the Int value for i in c (*)
scala> :type -v case class C(i:Int)
// Type signature
AnyRef
with Product
with Serializable {
val i: Int <----------------------- (*)
private[this] val i: Int
def <init>(i: Int): C
def copy(i: Int): C
...
and for not necessarily Int type, consider field j in D,
scala> case class C(i:Int)
defined class C
scala> case class D(j:C)
defined class D
scala> :type -v case class D(j:C)
// Type signature
AnyRef
with Product
with Serializable {
val j: C
private[this] val j: C
def <init>(j: C): D
def copy(j: C): D
...
Thanks very much...
In Summary
Given
scala> f.get(c)
res1: Object = 1
and
scala> f.getType
res3: Class[_] = int
how to get
val a = 1
where a is of type Int, and knowing the type only from f.getType.
The static type of f.get(c) is Object, because it can be any class and any field. However, at the runtime it will return an Integer (the Java wrapper class for Int). You can cast it by using
f.get(c).asInstanceOf[Int]
or
f.getInt(c)
if you know in advance that you are calling for an Int field. If you don't, you can pattern match:
f.get(c) match {
case i: Integer => ...
case l: java.lang.Long => ...
case s: String => ...
// etc.
}
// actually compiles to same code, but avoids the need to use boxed classes
(f.get(c): Any) match {
case i: Int => ...
case l: Long => ...
case s: String => ...
// etc.
}
Note that the taken branch depends on the actual value of the field, not on its type; e.g. for val f: Any = "" the case s: String branch will be taken.
Or you can use f.getType to get its type and make your logic depend on that.

Scala: require that a function argument is a member of some class?

I want to do something like
class A {
def f1: Unit = ...
def f2: Unit = ...
}
def foo(f: => Unit) {
(new A).f // ???
}
where f is supposed to be a member function of class A. I believe the standard solution is
def foo(f: A => Unit) {
f(new A)
}
and use it in this way
foo(_.f1)
foo(_.f2)
But now I can pass in an arbitrary function that has this signature, which may be not desired. Is there anyway to ensure that, the function I pass in is a member of certain class?
Well, if you don't mind a few contortions, you can use the fact that a function IS a class after all...
// abstract class MyIntToString extends (Int => String) // declare here if you want
// to use from different classes
// EDIT: f1 and f2 are now val instead of def as per comment below
// by #Régis Jean-Gilles
class A {
abstract class MyIntToString private[A]() extends (Int => String)
// if MyIntToString is declared here
// with a constructor private to the enclosing class
// you can ensure it's used only within A (credit goes to #AlexeyRomanov
// for his comment below)
val f1 = new MyIntToString {
def apply(i: Int) = i.toString + " f1"
}
val f2= new MyIntToString {
def apply(i: Int) = i.toString + " f2"
}
}
def foo(f: A#MyIntToString) = f(42) // f: MyIntToString if MyIntToString not nested in A
val a = A
now you can do:
scala> foo((new A).f1)
res1: String = 42 f1
scala> foo((new A).f2)
res2: String = 42 f2
but foo will not accept Int => String signatures
scala> val itos = (i:Int) => i.toString
itos: Int => String = <function1>
scala> foo(itos)
<console>:11: error: type mismatch;
found : Int => String
required: MyIntToString
foo(itos)
^