simple REPL test...
def g(a:Int)(implicit b:Int) = {a+b}
Why do neither of these attempted usages work?
1.
scala> class A { var b:Int =8; var c = g(2) }
:6: error: could not find implicit value for parameter b: Int
class A { var b:Int =8; var c = g(2) }
2.
scala> class A(var b:Int) { var c = g(2) }
:6: error: could not find implicit value for parameter b: Int
class A(var b:Int) { var c = g(2) }
^
Thanks
you need to define b as implicit in A
scala> def g(a:Int)(implicit b:Int) = {a+b}
g: (a: Int)(implicit b: Int)Int
scala> class A { implicit var b:Int =8; var c = g(2) }
defined class A
scala> val a = new A
a: A = A#1f7dbd8
scala> a.c
res3: Int = 10
In general, only values/methods that are defined as implicits will be considered and they are searched in scope, or in the companion object of the required type (Int in this case)
You have to specify which var or val will be used as the implicit value:
scala> def g(a:Int)(implicit b:Int) = {a+b}
g: (a: Int)(implicit b: Int)Int
scala> class A { implicit var b:Int =8; var c = g(2) }
defined class A
scala> new A
res0: A = A#16b18b6
scala> res0.c
res1: Int = 10
scala> class A(implicit var b:Int) { var c = g(2) }
defined class A
Related
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
}
I have the code that instance.get returns value, and based on the type I process accordingly.
instance.get match {
case v:Range => {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
case v:Encoding => {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
...
}
In the code, I have duplication for the Range and Encoding type. How can I merge the two cases?
I tried the | operator, but it doesn't work.
case v:Range | v:Encoding
This can't work, because Range.size and Encoding.size are two completely different methods despite the fact that they are named the same. And same is true for Range.decode and Edncoding.decode.
So, when you write v.size, the type of v has to be known, it has to be either v:Encoding or v:Range, not v:Encoding|v:Range.
How to fix this? Make a common trait like this:
trait SomethingWithDecodeAndSize {
def size: Int
def decode(bytes: Array[Byte]): Whatever
}
And then, change the definitions of Range and Encoding:
class Range extends SomethingWithDecodeAndSize { ... }
class Encoding extends SomethingWithDecodeAndSize { ... }
Now you can just do case v: SomethingWithDecodeAndSize => ... in your match clause.
Also ... Don't do instance.get, that's bad taste. Do instead
instance match {
Some(v: SomethingWithDecodeAndSize) => ...
}
Update
If you cannot modify the definitions of the original classes, you can use an extractor:
object SomethingWithDecodeAndSize {
def unapply(a: Any): Option[SomethingWithDecodeAndSize] = a match {
case r: Range => Some(new SomethingWithDecodeAndSize {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
})
case r: Encoding => Some(new SomethingWithDecodeAndSize {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
})
case _ => None
}
}
Now, you can do case Some(SomethingWithDecodeAndSize(v)) => ... in your match.
An alternate solution to #Dima's in case you can't change definition of Range and Encoding (and there is no supertype with required methods):
trait RangeOrEncoding {
def size: Int
def decode(bytes: Array[Byte]): Whatever
}
implicit def liftRange(r: Range): RangeOrEncoding = new RangeOrEncoding {
def size = r.size
def decode(bytes: Array[Byte]) = r.decode(bytes)
}
// similar conversion for Encoding
// can also be a local def
private def handleRangeOrEncoding(v: RangeOrEncoding) = {
val sizeInBytes = util.conversion.Util.getBytesForBits(v.size)
val value = v.decode(contentByteArray.slice(index, index + sizeInBytes))
index += sizeInBytes
res(key) = value
}
instance match {
case Some(v: Range) => handleRangeOrEncoding(v)
case Some(v: Encoding) => handleRangeOrEncoding(v)
...
}
I remember the cheerleaders in high school asking us, "How loose is your goose?"
scala> class C { def f(i: Int) = 2 * i }
defined class C
scala> class D { def f(i: Int) = 3 * i }
defined class D
scala> def test(x: Any) = x match { case y: { def f(i: Int): Int } => y.f(42) }
<console>:11: warning: a pattern match on a refinement type is unchecked
def test(x: Any) = x match { case y: { def f(i: Int): Int } => y.f(42) }
^
warning: there was one feature warning; re-run with -feature for details
test: (x: Any)Int
scala> test(new C)
res0: Int = 84
scala> test(new D)
res1: Int = 126
scala> test(42)
java.lang.NoSuchMethodException: java.lang.Integer.f(int)
at java.lang.Class.getMethod(Class.java:1786)
at .reflMethod$Method1(<console>:11)
at .test(<console>:11)
... 32 elided
I believe the answer was: "Loose, baby, loose."
Edit:
scala> import reflect.runtime._,universe._,language.reflectiveCalls
import reflect.runtime._
import universe._
import language.reflectiveCalls
scala> class C { def f(i: Int) = 2 * i }
defined class C
scala> class D { def f(i: Int) = 3 * i }
defined class D
scala> def f[A](a: A)(implicit tt: TypeTag[A]) = a match {
| case b: { def f(i: Int): Int }
| if tt.tpe <:< typeOf[{ def f(i: Int): Int }] =>
| b.f(42)
| }
<console>:19: warning: a pattern match on a refinement type is unchecked
case b: { def f(i: Int): Int }
^
f: [A](a: A)(implicit tt: reflect.runtime.universe.TypeTag[A])Int
scala> f(new C)
res0: Int = 84
scala> f(new D)
res1: Int = 126
scala> f(3) // now an ordinary MatchError
scala.MatchError: 3 (of class java.lang.Integer)
at .f(<console>:18)
... 32 elided
So you can express it as an ordinary type bounds:
scala> def f[A <: { def f(i: Int): Int }](a: A) = a.f(42)
f: [A <: AnyRef{def f(i: Int): Int}](a: A)Int
scala> f(new C)
res3: Int = 84
scala> f(17)
<console>:20: error: inferred type arguments [Int] do not conform to method f's type parameter bounds [A <: AnyRef{def f(i: Int): Int}]
f(17)
^
<console>:20: error: type mismatch;
found : Int(17)
required: A
f(17)
^
You still need to accept the cost of the reflective call, of course.
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
After having discovered that currying multi parameter-groups method is possible, I am trying to get a partially applied function which requires implicit parameters.
It seams not possible to do so. If not could you explain me why ?
scala> def sum(a: Int)(implicit b: Int): Int = { a+b }
sum: (a: Int)(implicit b: Int)Int
scala> sum(3)(4)
res12: Int = 7
scala> val partFunc2 = sum _
<console>:8: error: could not find implicit value for parameter b: Int
val partFunc2 = sum _
^
I use a singleton object to create this partially applied function and I want to use it in a scope where the implicit int is defined.
That is because you don't have an implicit Int in scope. See:
scala> def foo(x: Int)(implicit y: Int) = x + y
foo: (x: Int)(implicit y: Int)Int
scala> foo _
<console>:9: error: could not find implicit value for parameter y: Int
foo _
^
scala> implicit val b = 2
b: Int = 2
scala> foo _
res1: Int => Int = <function1>
The implicit gets replaced with a real value by the compiler. If you curry the method the result is a function and functions can't have implicit parameters, so the compiler has to insert the value at the time you curry the method.
edit:
For your use case, why don't you try something like:
object Foo {
def partialSum(implicit x: Int) = sum(3)(x)
}
scala> object MySingleton {
| def sum(a: Int)(implicit b: Int): Int = { a+b }
|
|
| def caller(a: Int) = {
| implicit val b = 3; // This allows you to define the partial below
| def pf = sum _ // and call sum()() without repeating the arg list.
| pf.apply(a)
| }
| }
defined module MySingleton
scala> MySingleton.caller(10)
res10: Int = 13
Is it possible to ignore a field of a case class in the equals/haschode method of the case class?
My use case is that I have a field that is essentially metadata for rest of the data in the class.
Only parameters in the first parameter section are considered for equality and hashing.
scala> case class Foo(a: Int)(b: Int)
defined class Foo
scala> Foo(0)(0) == Foo(0)(1)
res0: Boolean = true
scala> Seq(0, 1).map(Foo(0)(_).hashCode)
res1: Seq[Int] = List(-1669410282, -1669410282)
UPDATE
To expose b as a field:
scala> case class Foo(a: Int)(val b: Int)
defined class Foo
scala> Foo(0)(1).b
res3: Int = 1
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Foo private(x: Int, y: Int) {
def fieldToIgnore: Int = 0
}
object Foo {
def apply(x: Int, y: Int, f: Int): Foo = new Foo(x, y) {
override lazy val fieldToIgnore: Int = f
}
}
// Exiting paste mode, now interpreting.
defined class Foo
defined module Foo
scala> val f1 = Foo(2, 3, 11)
f1: Foo = Foo(2,3)
scala> val f2 = Foo(2, 3, 5)
f2: Foo = Foo(2,3)
scala> f1 == f2
res45: Boolean = true
scala> f1.## == f2.##
res46: Boolean = true
You may override .toString if necessary.
You can override the equals and hasCode methods in a case class
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class Person( val name:String, val addr:String) {
override def equals( arg:Any) = arg match {
case Person(s, _) => s == name
case _ => false
}
override def hashCode() = name.hashCode
}
// Exiting paste mode, now interpreting.
scala> Person("Andy", "") == Person("Andy", "XXX")
res2: Boolean = true
scala> Person("Andy", "") == Person("Bob", "XXX")
res3: Boolean = false
If you override toString in the base class it will not be overridden by the derived case classes. Here is an example:
sealed abstract class C {
val x: Int
override def equals(other: Any) = true
}
case class X(override val x: Int) extends C
case class Y(override val x: Int, y: Int) extends C
Than we you test:
scala> X(3) == X(4)
res2: Boolean = true
scala> X(3) == X(3)
res3: Boolean = true
scala> X(3) == Y(2,5)
res4: Boolean = true