Scala:选项[T]为?[T](甚至T?)

时间:2014-04-22 01:53:21

标签: scala

我试过

type ?[_] = Option[_]

def f(x: ?[Int]) = for (y <- x) yield y

(但我不知道我在做什么。)

就类型只是对象而言,我应该能够定义一个postix运算符(即零arity方法),用于类型签名(我认为)。它可能需要像

这样的空间
def f(x: Int ?) = for (y <- x) yield y

scala使得使用具有匹配和多态的Option类型变得容易,避免使用null。但是,大多数类都是(可空)变量,而java经常返回变量。使用类和调用java是scala的两个卖点。易于编写且易于阅读的语法将更强烈地支持选项。

  1. scala用“?”做的所有事情是什么?使其解析特别。

  2. 理想情况下,可以写

    def f(x:Int?)= for(y < - x)yield y

  3. 和其他语言一样。我们可以在scala(没有宏)中执行此操作吗?

3 个答案:

答案 0 :(得分:6)

首先,类型不是对象。实际上,Scala只有两个名称空间:值和类型。它们是非常不同的东西,并且遵循非常不同的规则。

实际上,后缀的想法很不错,但这是不可能的。但是,有一种类型的中缀表示法。

现在,你写的是:

type ?[_] = Option[_]

每个下划线都有不同的含义。 ?[_]中的下划线表示?更高,但你不关心它的类型参数是什么。 Option[_]中的下划线表示Option是一种存在类型。因此,当您编写x: ?[Int]时,Scala会将其转换为x: Option[t] { forSome type t }。这意味着您不仅没有获得Int,而且Option的类型参数也是不可知的(您只知道它存在)。

然而,它 编译:

scala> def f(x: ?[Int]) = for (y <- x) yield y
f: (x: ?[Int])Option[Any]

您使用的是哪个版本的Scala? 2.11?我的一个同事已经在2.11上找到了一些类型推断回归,所以可能就是这样。

编写类型别名的正确方法是:

type ?[+A] = Option[A]

不仅我们传递了类型参数(毕竟它一个参数!),但是我们需要指定它的共同方差才能使Option行动(这是共变体本身)。

现在,关于你的两个问题,Scala绝对没有?的特殊处理。而且,不,你不能这样做。这个?在语言中并不完全普遍,并且在支持它的所有语言中,它都是用语言构建的,而不是外部定义的。

此外,当与Java接口时,键入Option将是一个问题 - 而不是Java中的平均标识符大小,这是一个笑话!

答案 1 :(得分:4)

您打算获得Option[Int]

scala> type ?[A] = Option[A]
defined type alias $qmark

scala> def f(x: ?[Int]) = for (y <- x) yield y + 1
f: (x: ?[Int])Option[Int]

无论如何都会编译。

你可以

scala> type ?[A,_] = Option[A]
defined type alias $qmark

scala> def f(x: Int ? _) = for (y <- x) yield y + 1
f: (x: ?[Int, _])Option[Int]

或类似。

scala> def f(x: Int ?_) = for (y <- x) yield y + 1
f: (x: ?[Int, _])Option[Int]

看起来更像postfixy。

P.S。仍然好奇是否需要对类型别名的方差注释或仅仅是可取的。

scala> type ?[A] = Option[A]
defined type alias $qmark

scala> trait X ; trait Y extends X ; trait Z extends X
defined trait X
defined trait Y
defined trait Z

scala> val x: ?[X] = null.asInstanceOf[?[Y]]  // why is this OK?
x: ?[X] = null

scala> class C[A]
defined class C

scala> val c: C[X] = null.asInstanceOf[C[Y]]  // like this is not OK
<console>:10: error: type mismatch;
 found   : C[Y]
 required: C[X]
Note: Y <: X, but class C is invariant in type A.
You may wish to define A as +A instead. (SLS 4.5)
       val c: C[X] = null.asInstanceOf[C[Y]]
                                      ^

也许比较SI-8522和相关问题。

答案 2 :(得分:4)

您可以考虑重命名导入。创建类型别名时,只需重命名类型。在导入期间重命名符号时,包括该名称的所有引用,包括类型和值。

即便:

scala> import scala.{Option => ?}
import scala.{Option=>$qmark}

scala> val oi1: ?[Int] = Some(1)
oi1: Option[Int] = Some(1)

scala> def mi1(oi: ?[Int]): Int = oi.getOrElse(-1)
mi1: (oi: Option[Int])Int

scala> mi1(None)
res1: Int = -1

scala> mi1(?(1))
res2: Int = 1

与此比较:

scala> type ?[A] = Option[A]

scala> def mi1(oi: ?[Int]): Int = oi.getOrElse(-1)
mi1: (oi: ?[Int])Int

scala> mi1(?(1))
<console>:10: error: not found: value ?
              mi1(?(1))
                  ^