【问题标题】:Type aliases that work in the REPL but not in a scala class/object键入在 REPL 中有效但在 scala 类/对象中无效的别名
【发布时间】:2015-01-10 07:14:11
【问题描述】:

我有一个测试程序,其中我们有内存中的静态数组。为简洁起见,我使用类型别名。

REPL 中的以下工作

type >[T] = Array[T]
val dat = >(>(1,2,3),>(2,3,4))

dat: Array[Array[Int]] = Array(Array(1, 2, 3), Array(2, 3, 4))

但是,将标识符从“>”更改为“A”确实起作用:类型已创建,但用于创建上述数组的相同语法失败:

scala> type A[T] = Array[T]
defined type alias A

scala> val dat = A(A(1,2,3),A(2,3,4))
<console>:7: error: not found: value A
       val dat = A(A(1,2,3),A(2,3,4))

此外,以上两个都不能在 Scala 程序 AFAICT 中工作:

  test("VectorProjection") {
    type  A[T] = Array[T]
    // Next line shows RED for all the A's and also has compiler error: "not found: value A"
    val dat  = A(A(1., 2., 3.), A(1.5,2.,2.5), A(2.,3.8,5.6), A(2.5,3.0,3.5), A(3.1,3.7,4.3) )
    val firsteigen =  subtractProject(dat(0), dat(4))
  }

正在寻找:

  • 1) 对于 REPL:解释为什么符号“>”有效但无效 标识符会很有帮助。
  • 2) 对于真正的 Scala 程序/类: 解释是否可以使用任何类似的语法 以上

更新根据 James Iry 的建议,以下方法确实有效:

    def A[T : ClassTag](ts: T*) = Array(ts:_*)

它在行动:

  test("VectorProjection") {
    def A[T : ClassTag](ts: T*) = Array(ts:_*)
    val dat  = A(
      A(1., 2., 3.),
      A(1.5,2.,2.5),
      A(3.,6.,9.)  )
    val firstEigen =  subtractProject(dat(0), dat(5))
    println(s"firstEigen: ${firstEigen.mkString(",")}")
  }

另一个更新另一个答案更接近这个 OP:

同时使用 type 和 val:

    type A = Array[Double]
    val A = Array

它在行动:

  test("VectorProjection") {
    type A = Array[Double]
    val A = Array
    val dat  = A(
      A(1., 2., 3.),
      A(1.5,2.,2.5),
      A(3.,6.,9.)  )
    val firstEigen =  subtractProject(dat(0), dat(5))
    println(s"firstEigen: ${firstEigen.mkString(",")}")
  }

【问题讨论】:

  • 你使用的是什么版本的scala?您的第一个示例对我不起作用(scala 2.11.2)(并且 afaik 不/不应该适用于任何版本)。至于为什么,见this answer
  • @Marth scala 2.10.4
  • 每个人都想知道你是如何破坏你的 repl 会话的。
  • 我的意思是,你的 REPL 进入了我们无法复制的状态。诊断一下就好了。 REPL 历史状态很多,会产生欺骗性的结果;注释您的代码// show 以显示您的代码编译成的内容,包括从历史记录中导入。顺便说一句,Iry 的回答是正确的;你不是说你的第一个例子有效,对吧?

标签: scala types


【解决方案1】:

我无法用'>'复制你的成功

scala> type >[T]=Array[T]
defined type alias $greater

scala> >(1,2,3)
<console>:8: error: not found: value >
              >(1,2,3)
              ^

至少,直到我定义它

scala> import scala.reflect._
import scala.reflect._

scala> def >[T : ClassTag](ts: T*) = Array(ts:_*)
$greater: [T](ts: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

scala> >(1,2,3)
res1: Array[Int] = Array(1, 2, 3)

同样适用于 A

scala> type A[T]=Array[T]
defined type alias A

scala> A(1,2,3)
<console>:11: error: not found: value A
              A(1,2,3)
              ^

scala> def A[T : ClassTag](ts: T*) = Array(ts:_*)
A: [T](ts: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]

scala> A(1,2,3)
res2: Array[Int] = Array(1, 2, 3)

解释一下:type X = Y 只是为类型 X 创建一个同义词。它不会为可能与该类型相关联的所有其他事物(如伴生对象、构造函数方法等)引入同义词。

【讨论】:

  • 有趣的是,您无法重现 REPL 的成功。我拿了你的代码(没有明确分配给变量),它也有效。但是这里的主要事件是:我喜欢你的 def 并将在一个真正的程序中尝试它。
  • 我最初授予了这个答案,但不久之后又出现了另一个答案,这是对 OP 的更准确的答案。这个问题无论如何都是有帮助的,我相应地投了赞成票。
【解决方案2】:

如果您创建一个值别名,它将起作用:

type A[T] = Array[T]
val A = Array
val dat = A(A(1,2,3),A(2,3,4)) //dat: Array[Array[Int]] = Array(Array(1, 2, 3), Array(2, 3, 4))

第 2 行创建一个值别名,因此您可以创建具有 A 类型别名的值。它将反过来能够调用 A.apply(1,2,3)。

【讨论】:

  • 我选择了这个答案作为正确的答案,因为它最直接地响应了 OP。
【解决方案3】:

用它来显示 repl 知道什么:

scala> $intp.definedTerms
res0: List[$intp.global.TermName] = List($intp)

scala> $intp.definedTypes
res1: List[$intp.global.TypeName] = List($greater)

例如,您可能有:

scala> object X
defined object X

scala> trait X
defined trait X
warning: previously defined object X is not a companion to trait X.
Companions must be defined together; you may wish to use :paste mode for this.

scala> type X = String
defined type alias X

但它不会警告别名。

【讨论】:

  • 感谢您提供有用的信息。
猜你喜欢
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多