I am trying to specify a value as a class parameter:
import scala.collection.mutable
class MyMap[K,V,D <: V] {
private val impl = mutable.Map[K, V]()
def apply(k:K):V = impl.getOrElse(k, valueOf[D])
// ^^^^^^^^^^ error
def put(k:K,v:V):Unit = impl += k -> v
}
val m = MyMap[Int, Int, 0]()
m(100) // must return 0
For some reason, the above does not work. Instead, what works is the below code with this illogical unusedName:
import scala.collection.mutable
class MyMap[K,V,D <: V] {
private val impl = mutable.Map[K, V]()
def apply(k:K)(implicit unusedName:ValueOf[D]):V = impl.getOrElse(k, valueOf[D])
def put(k:K,v:V):Unit = impl += k -> v
}
val m = MyMap[Int, Int, 0]()
m(100) // must return 0
I tried to pass the implicit agrument explicitly, which in theory should be possible, but it did not work as I would expect:
scala> m(2)(0)
-- [E007] Type Mismatch Error: ----
1 |m(2)(0)
| ^
| Found: (0 : Int)
| Required: ValueOf[(0 : Int)]
scala> m(2)(ValueOf[0])
-- Error: --------------------------
1 |m(2)(ValueOf[0])
| ^^^^^^^^^^
| missing arguments for constructor ValueOf in class ValueOf
scala> m(2)(ValueOf[0](0))
val res7: Int = 0
Questions:
How does all this ValueOf/valueOf magic work?
Why didn't just valueOf[D] work? (It would be only logical)
UPDATE
the code referenced in the comments is:
import scala.collection.mutable
final class MyMap[K, V] private (default: V) {
private val impl = mutable.Map.empty[K, V]
def apply(k: K): V =
impl.getOrElse(k, default)
def put(k: K,v: V): Unit = {
impl += k -> v
}
}
object MyMap {
def empty[K, V, D <: V](using ValueOf[D]): MyMap[K, V] =
new MyMap(default = valueOf[D])
}
val m = MyMap.empty[Int, Int, 0]
m(100)
Code fragment 2:
import scala.collection.mutable
final class MyMap[K, V, D <: V](using ValueOf[D]) {
private val default = valueOf[D]
private val impl = mutable.Map.empty[K, V]
def apply(k: K): V =
impl.getOrElse(k, default)
def put(k: K,v: V): Unit = {
impl += k -> v
}
}
val m = MyMap[Int, Int, 0]()
m(100)