我正在尝试将一个值指定为类参数:
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
出于某种原因,上述方法不起作用。取而代之的是下面这段不合逻辑的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
我试图明确地传递隐含的议论,理论上这应该是可能的,但它并没有像我预期的那样起作用:
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
问题:
所有这些ValueOf
/valueOf
魔法是如何工作的?
为什么valueOf[D]
不起作用?(这是合乎逻辑的)
更新
评论中引用的代码为:
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)
代码片段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)
1条答案
按热度按时间2vuwiymt1#
所有这些魔法的价值是如何起作用的?
ValueOf[T]
是存在T
型的一个区别值的命题。所有合理类型
T
的见证示例都由编译器自动生成。对于每个
v: ValueOf[T]
,成员访问v.value
提供类型T
的区别值。方法
valueOf[T]
只是将见证者ValueOf[T]
解压缩成T
类型的值。从头开始快速重建这一机制可能会有一定的启发意义:
为什么
valueOf[D]
不起作用?(这是合乎逻辑的)因为,正如签名所说,方法
valueOf[D]
需要ValueOf[D]
作为隐式参数。当D
已知时,可以生成ValueOf[D]
的示例。它不能为任意泛型类型D
生成(如果是这样的话,那么您的代码可以为Map[Int, Int, Nothing]
工作,这显然是荒谬的)。关于你的REPL实验:
m(2)(0)
显然不应该工作,因为0
的类型是Int
,而不是ValueOf[Int]
。ValueOf[0]
被解释为不完整的构造函数调用。如果您指的是类型而不是值,则必须使用summon
来示例化类型的值,即m(2)(summon[ValueOf[0]])
ValueOf[0](0)
基本上与要求summon[ValueOf[0]]
时编译器生成的内容相同。关于您的
Map
Package 器:在创建贴图时,您可能希望传递一次默认值:
Package 器本身似乎没有太大帮助,因为已经在所有可变Map上定义了一个方法
withDefault
。