我试过
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的两个卖点。易于编写且易于阅读的语法将更强烈地支持选项。
scala用“?”做的所有事情是什么?使其解析特别。
理想情况下,可以写
def f(x:Int?)= for(y < - x)yield y
答案 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))
^