In scala swing I can do something like the following:
val field = new TextField("", 4)
field.text = "Hello"
And the assignment is implemented thus:
def text_=(t: String): Unit = peer.setText(t)
But if I try my own implementation such as:
case class A(i: Int) {
def value_=(j: Int) = copy(i = j)
}
val a = A(3)
a.value = 3
This will not compile for me. What am I missing?
In Scala 2.13 (and 3) the setter def value_= (or def value_$eq) seems to work if you declare a field value
case class A(i: Int) {
val value: Int = 0
def value_=(j: Int) = copy(i = j)
}
or
case class A(i: Int, value: Int = 0) {
def value_=(j: Int) = copy(i = j)
}
By the way, it's a little confusing that a setter value_= returns A rather than Unit
println(a.value = 4) // A(4,0)
In Scala 2.12 the "setter" def value_= (or def value_$eq) works if you declare a "getter" too
case class A(i: Int) {
def value = "value"
def value_=(j: Int) = copy(i = j)
}
Related
Say I do the following:
trait A {
val i: Int
override def toString = s"A($i)"
}
case class B(i: Int, j: Int) extends A
println(B(2, 3))
This will give me the output:
A(2)
Is there a way I can make B.toString revert to the default toString for a case class without me having to explicitly write:
override def toString = s"B($i,$j)"
It used to be
override def toString = scala.runtime.ScalaRunTime._toString(this)
but that object was removed in 2.12 EDIT: it was only removed from ScalaDoc, but still exists.
To avoid relying on ScalaRunTime._toString, you can define it yourself:
def _toString(x: Product): String =
x.productIterator.mkString(x.productPrefix + "(", ",", ")")
Perhaps
trait A {
val i: Int
override def toString = this match {
case p: Product => scala.runtime.ScalaRunTime._toString(p)
case _ => s"A($i)"
}
}
case class B(i: Int, j: Int) extends A
class Foo extends A {
override val i = 42
}
B(2, 3)
new Foo
which outputs
res0: B = B(2,3)
res1: Foo = A(42)
I need to call a sort method of a library that takes an implicit Ordering parameter by using implicitly like this:
class OrderedRDDFunctions[K : Ordering : ClassTag,
V: ClassTag] (self: RDD[P]) {
private val ordering = implicitly[Ordering[K]]
def sort() = {
// uses ordering value
}
}
Now, I need to call this function twice in a loop, with different Orderings of same type like below.
var A: RDD[(Int, Int, Int)] = ...
var C: RDD[(Int, Int, Int)] = ...
while(...) {
implicit val ijOrdering:Ordering[(Int, Int, Int)] = new Ordering[(Int, Int, Int)] {
override def compare(a: (Int, Int, Int), b: (Int, Int, Int)) = {
val c = a._1.compare(b._1)
if(c != 0) c
else a._2.compare(b._2)
}
}
A.sort() // should use ijOrdering above
implicit val kjOrdering:Ordering[(Int, Int, Int)] = new Ordering[(Int, Int, Int)] {
override def compare(a: (Int, Int, Int), b: (Int, Int, Int)) = {
val c = a._3.compare(b._3)
if(c != 0) c
else a._2.compare(b._2)
}
}
C.sort() // should use kjOrdering above
}
There are two different implicit Ordering instances to be used in sort() method. But this gives me a compile error. How can I state different implicit ordering in this setup? Note that I cannot change the library method.
You can use blocks to limit the scope of implicits. A simple example:
object Blocks extends App {
def meth()(implicit e: Int) = e * 2
locally {
implicit val k = 21
println(meth()) // finds k and prints 42
}
locally {
implicit val j = 11
println(meth()) // finds j and prints 22
}
}
This does not work if there are conflicting implicits outside of the block.
Note that locally { ..stmts.. } is generally equivalent to { ..stmts.. }, tho I prefer it for readability's sake. You can read more on what's that here
Today I had an interview about Scala and request was:
Implement a data structure with fixed size N , with these functionalities:
get(index)
set(index,value)
setall(value)
The complexity should be O(1)
example:
val ds = DS(100)
ds.set(4,5)
ds.get(4) //would return 5
ds.set(1,4)
ds.setall(10)
ds.get(4) //would return 10
ds.get(7) //would return 10
ds.set(1,7)
ds.get(1) //would return 7
Please find code that I have sent below.
My question would be Is this right solution and if there is a better way of doing it ?
import scala.collection.mutable.HashMap
trait Operations {
def get(index: Int): Int
def set(index: Int, value: Int)
def setall(value: Int)
}
class DS(N: Int) extends Operations {
var myMutableHashMap = new HashMap[Int, Int]().withDefaultValue(0)
def get(index: Int) = myMutableHashMap(index)
def set(index: Int, value: Int) = {
if (index <= N) myMutableHashMap += (index -> value)
}
def setall(value: Int) = {
myMutableHashMap = new HashMap[Int, Int]().withDefaultValue(value)
}
}
object Task {
def main(args: Array[String]): Unit = {
val ds = new DS(100)
ds.set(4, 5)
ds.get(4)
println(ds.get(4)) // -> 5
ds.setall(10)
println(ds.get(4)) //-> 10
println(ds.get(7)) //-> 10
ds.set(1, 7)
println(ds.get(1)) //-> 7
}
}
I am not sure if it is better, but I think HashMap might be a bit of an overkill.
The following solution might have a smaller footprint and takes less code.
Although, I would probably rather implement something more generic, it should fulfill the requirements you mentioned.
trait Operations {
def get(index: Int): Int
def set(index: Int, value: Int): Unit
def setall(fill: Int): Unit
}
class DS(size: Int) extends Operations {
val underlying: Array[Int] = new Array(size)
def get(index: Int): Int = underlying(index)
def set(index: Int, value: Int): Unit = underlying(index) = value
def setall(fill: Int): Unit = (0 until size).foreach(underlying(_) = fill)
}
Alternative, which just might give us a better 'setall' complexity but at a cost ...
trait Operations {
def get(index: Int): Int
def set(index: Int, value: Int): Unit
def setall(fill: Int): Unit
}
class DS(size: Int) extends Operations {
var underlying: Array[Integer] = new Array(size)
var default: Integer = new Integer(0)
def get(index: Int): Int = {
val result = underlying(index)
if (result == null) default else result
}
def set(index: Int, value: Int): Unit = underlying(index) = value
def setall(fill: Int): Unit = {
default = fill
underlying = new Array(size)
}
}
I'm trying to create a custom data type that behaves like an Int, but has certain specific behavior and typing (eg., it has to be positive, it has to fit within the range of our database's 'integer' type, etc).
To make it a friendly class, I want to have custom assignment operators, etc., for instance I'd like the following to all work:
val g: GPID = 1 // create a GPID type with value 1
val g: GPID = 1L // take assignment from a Long (and downcast into Int)
if (g == 1) ... // test the value of GPID type against an Int(1)
This is what I have so far but I'm not getting the expected behavior:
case class GPID(value: Int) extends MappedTo[Int] {
require(value >= 1, "GPID must be a positive number")
require(value <= GPDataTypes.integer._2, s"GPID upper bound is ${GPDataTypes.integer._2}")
def this(l: Long) = this(l.toInt)
def GPID = value
def GPID_=(i: Int) = new GPID(i)
def GPID_=(l: Long) = new GPID(l.toInt)
override def toString: String = value.toString
override def hashCode:Int = value
override def equals(that: Any): Boolean =
that match {
case that: Int => this.hashCode == that.hashCode
case that: Long => this.hashCode == that.hashCode
case _ => false
}
}
object GPID {
implicit val writesGPID = new Writes[GPID] {
def writes(g: GPID): JsValue = {
Json.obj(
"GPID" -> g.value
)
}
}
implicit val reads: Reads[GPID] = (
(__ \ "GPID").read[GPID]
)
def apply(l: Long) = new GPID(l.toInt)
implicit def gpid2int(g: GPID): Int = hashCode
implicit def gpid2long(g: GPID): Long = hashCode.toLong
}
The problems I have are:
Assignment doesn't work, for instance:
val g: GPID = 1
Implicit conversion is not working, for instance:
val i: Int = g
Any help would be appreciated... haven't build a custom type like this before so overriding assignment and implicit conversion is new to me...
object TestInt extends App {
class GPID(val value: Int) {
require(value >= 1, "GPID must be a positive number")
require(value <= 10, s"GPID upper bound is 10")
override def equals(that: Any) = value.equals(that)
override def toString = value.toString
// add more methods here (pimp my library)
}
implicit def fromInt(value: Int) = new GPID(value)
implicit def fromInt(value: Long) = new GPID(value.toInt) //possible loss of precision
val g: GPID = 1
val g2: GPID = 1L
if (g == 1)
println("ONE: " + g)
else
println("NOT ONE: " + g)
}
Prints:
ONE: 1
I was wondering how to go about adding a 'partitionCount' method to Lists, e.g.:
(not tested, shamelessly based on List.scala):
Do I have to create my own sub-class and an implicit type converter?
(My original attempt had a lot of problems, so here is one based on #Easy's answer):
class MyRichList[A](targetList: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
var btrue = 0
var bfalse = 0
var these = targetList
while (!these.isEmpty) {
if (p(these.head)) { btrue += 1 } else { bfalse += 1 }
these = these.tail
}
(btrue, bfalse)
}
}
and here is a little more general version that's good for Seq[...]:
implicit def seqToRichSeq[T](s: Seq[T]) = new MyRichSeq(s)
class MyRichList[A](targetList: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
var btrue = 0
var bfalse = 0
var these = targetList
while (!these.isEmpty) {
if (p(these.head)) { btrue += 1 } else { bfalse += 1 }
these = these.tail
}
(btrue, bfalse)
}
}
You can use implicit conversion like this:
implicit def listToMyRichList[T](l: List[T]) = new MyRichList(l)
class MyRichList[T](targetList: List[T]) {
def partitionCount(p: T => Boolean): (Int, Int) = ...
}
and instead of this you need to use targetList. You don't need to extend List. In this example I create simple wrapper MyRichList that would be used implicitly.
You can generalize wrapper further, by defining it for Traversable, so that it will work for may other collection types and not only for Lists:
implicit def listToMyRichTraversable[T](l: Traversable[T]) = new MyRichTraversable(l)
class MyRichTraversable[T](target: Traversable[T]) {
def partitionCount(p: T => Boolean): (Int, Int) = ...
}
Also note, that implicit conversion would be used only if it's in scope. This means, that you need to import it (unless you are using it in the same scope where you have defined it).
As already pointed out by Easy Angel, use implicit conversion:
implicit def listTorichList[A](input: List[A]) = new RichList(input)
class RichList[A](val source: List[A]) {
def partitionCount(p: A => Boolean): (Int, Int) = {
val partitions = source partition(p)
(partitions._1.size, partitions._2.size)
}
}
Also note that you can easily define partitionCount in terms of partinion. Then you can simply use:
val list = List(1, 2, 3, 5, 7, 11)
val (odd, even) = list partitionCount {_ % 2 != 0}
If you are curious how it works, just remove implicit keyword and call the list2richList conversion explicitly (this is what the compiler does transparently for you when implicit is used).
val (odd, even) = list2richList(list) partitionCount {_ % 2 != 0}
Easy Angel is right, but the method seems pretty useless. You have already count in order to get the number of "positives", and of course the number of "negatives" is size minus count.
However, to contribute something positive, here a more functional version of your original method:
def partitionCount[A](iter: Traversable[A], p: A => Boolean): (Int, Int) =
iter.foldLeft ((0,0)) { ((x,y), a) => if (p(a)) (x + 1,y) else (x, y + 1)}