0

来自 Python 背景,我习惯于在运行时将类型作为对象提供。有了这一点,再加上至少在intfloat这些类型的对象也恰好是充当解析器的可调用对象(例如int("234") == 234,像 Scala's "234".toInt == 234)的事实,我可以想出一个解决方案来解析,比如说,一个矩阵文本文件中的整数或浮点数。我唯一要做的就是配置一个参数:

 ITEM_TYPE = int  # or float

我很高兴:

 with open('matrix.dat') as f:
   matrix_data_raw = parse_raw_matrix(f.read())
 matrix = [map(ITEM_TYPE, row) for row in matrix]

将值更改ITEM_TYPE为立即在运行时float给我一个listof s(没有静态类型,但的内容仍然强类型为要么或)。listfloatmatrixlist[list[int]]list[list[float]]

在 Scala 中,我期望的静态类型matrix是例如,Matrix[Int]或者Matrix[Double](来自,比如说,更一般的type Matrix[T: Numeric] = Vector[Vector[T]])。但是,作为 Scala 的相对初学者,我对如何实现这一点有点迷茫。没有明显/简单的方法可以将参数的值从切换classOf[Int]classOf[Double]- 即使我这样做并相应地动态选择解析器函数(这很简单),我将如何更改运行时类型matrixfrom,比如说Matrix[Int]Matrix[Double]? 我必须将静态类型声明matrix为-<code>Matrix[Numeric] 吗?

在你判断这个问题的天真之前,我承认我知道 Scala 的解决方案可能需要一种不同的方法,但我只是喜欢从(IMO 相当优雅的)Python 开始我的想法的想法解决方案。

4

3 回答 3

1

尝试这个:

// Define this whereever makes sense, possibly as an abstract method in a trait
// with suitable concrete implementations that you can mix in to the class doing
// the matrix work, or with the body determined based on config data, etc.:
def itemType: String => Number = _.toInt // or _.toDouble or whatever

// Set up your read:
val matrixDataRaw = parseRawMatrix(f.read()) // Matrix[String] at this point
val matrix = matrixDataRaw.map(itemType)

但是,最好将 itemType 传递给解析函数并在将文本片段放入矩阵类之前转换它们(当前需要在其上定义一个 map 方法来进行转换)。

于 2013-09-20T22:55:42.067 回答
0

我认为值得指出的是,矩阵的运行时类型始终为 Matrix[Object] - 在 JVM 上运行,泛型类型在运行时被擦除。

也就是说,您仍然可以指定矩阵中元素的运行时类型。我认为你必须用一个函数来做到这一点。我将使用列表来说明这一点:

val int: (String => Number) = _.toInt
val float: (String => Number) = _.toFloat

您必须定义可能在运行时使用的任何这些。完成后,用法很简单:

val NUM_TYPE: (String => Number) = int // or whichever you choose

...

val list = List("1", "2", "3") map (NUM_TYPE)

这将始终为您返回一个 List[Number],但它将填充(在这种情况下)Ints。

于 2013-09-20T16:21:18.623 回答
0

你不能做这个。我可以建议的最好的事情是,如果您知道您将获得整数或浮点数,那么两者都做。

trait Matrix[+A]

def parseRawData[A : Numeric](fp: io.Source, parseNum: String => A): Matrix[A]...

def manipulateRawData[A : Numeric](fp: io.Source): Matrix[A] = {
  val mat = parseRawData
  val numeric = implicitly[Numeric[A]]
  ...
}

if (ints) {
  manipulateRawData[Int](fp, _.toInt)
}
else if (doubles) {
  manipulateRawData[Double](fp, _.toDouble)
}

你可以看到你最后得到了一个 Matrix[AnyVal] (小心你的类型),但它会在中间做正确的事情。

于 2013-09-20T16:21:19.780 回答