作为AnyRef传递的伴随对象的静态断言

时间:2014-12-22 14:55:21

标签: scala static-assert

对于类似akka的框架,当发送或匹配(预期)发送或匹配(预期)伴随对象而不是case类实例时,错别字很常见,反之亦然。 代码如下:

case class Foo()
...
def receive(ev: AnyRef) = {
...
    case Foo() =>
        // do some stuff
...
}

偶尔发送这样的信息:

actor ! Foo

而不是

actor ! Foo()

错误版本编译完美但代码不能像预期的那样工作(出于显而易见的原因)。

现在问题:有没有办法指定一些静态(编译时)断言,无法传递伴侣对象(可能除了“case object Foo”之外)!运营商?并且对于类似接收的函数,某些方式指定它不应包含它们的匹配情况。

防止无参数案例类被声明的一些方法(强制这些案例的案例对象)。 E. g。编译器选项会使'case class Foo()'非法强制使用'case object Foo'。但这不会阻止案件Foo =>从而被用来代替案例Foo(_)=>对于带参数的case类(用例:actor只能重定向一些收到的消息而忽略参数)。

2 个答案:

答案 0 :(得分:1)

几个星期前我遇到了类似的想法,这是我得出的结论:

我无法强迫Akka只考虑采用某种类型的数据,而不会覆盖框架的大块或在接收和发送时实施我自己的检查。例如,您可以将您的发送操作包装在您调用的只接受某种类型参数的方法中。

如果我理解了您的第二个问题,您希望禁止使用以下val a = Foo,这是不可能的,因为Scala可以保留一个值类型。

在创建我自己的框架实现和包装发送调用之间,我选择了包装我的发送和请求调用的方法,正如我所说,只接受某种类型的参数。它运作良好。类似的东西:

def customSend[T <: MyType](msg: T) = 
  actor ! msg

希望这有帮助。

答案 1 :(得分:0)

将类型排除在推断之外的通常(或不寻常)方法是模糊的暗示技巧。

但是因为scalac不会推断单一类型,所以你无法让它堕落。

较小的替代方法是重载多态方法,这样一个方法接收单例而另一个方法不接收。

然后你至少可以发现发送方的编程错误。

scala> object F {
     | def f[A](a: A) = println(a)
     | def f[A <: Singleton](a: A)(implicit d: DummyImplicit) = println(s"Reject $a")
     | }
defined object F

scala> F f 3
3

scala> object X
defined object X

scala> F f X
Reject $line5.$read$$iw$$iw$X$@5aa9e4eb

scala> F f (3: Singleton)
Reject 3

scala> F f[Singleton] 3
<console>:9: error: overloaded method value f with alternatives:
  (a: Singleton)(implicit d: DummyImplicit)Unit <and>
  (a: Singleton)Unit
 cannot be applied to (Int)
              F f[Singleton] 3
              ^

这没有帮助:

scala> :pa
// Entering paste mode (ctrl-D to finish)

  trait NoSing[A]
  implicit val `no sing 1`: NoSing[Singleton] = null.asInstanceOf[NoSing[Singleton]]
  implicit val `no sing 2`: NoSing[Singleton] = null.asInstanceOf[NoSing[Singleton]]
  implicit def `anything but`[A]: NoSing[A]   = null.asInstanceOf[NoSing[A]]

// Exiting paste mode, now interpreting.

defined trait NoSing
no sing 1: NoSing[Singleton] = null
no sing 2: NoSing[Singleton] = null
anything$u0020but: [A]=> NoSing[A]

scala> object G {
     | def g[A : NoSing](a: A) = println(a)
     | }
defined object G

scala> G g X
$line5.$read$$iw$$iw$X$@5aa9e4eb

scala> G g[Singleton] X
<console>:14: error: ambiguous implicit values:
 both value no sing 1 of type => NoSing[Singleton]
 and value no sing 2 of type => NoSing[Singleton]
 match expected type NoSing[Singleton]
              G g[Singleton] X
                ^