根据Scala中动态指定的类型解析数字

时间:2013-09-20 15:44:16

标签: python parsing scala

来自Python背景,我习惯在运行时将类型作为对象使用。有了这个,结合至少在intfloat的情况下,这些类型对象也恰好是充当解析器的callables(例如int("234") == 234,就像Scala的{{1}我可以想出一个解析来解析一个文本文件中整数或浮点数的矩阵。我唯一要做的就是配置一个参数:

"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 list list个} {没有静态类型但内容float仍然强烈输入matrixlist[list[int]]}。

在Scala中,我希望静态类型为list[list[float]],例如matrixMatrix[Int](来自更一般的Matrix[Double])。但是,作为Scala的相对初学者,我对如何实现这一点感到有点迷茫。没有明显/简单的方法可以将参数的值从type Matrix[T: Numeric] = Vector[Vector[T]]切换到classOf[Int] - 即使我这样做并相应地动态选择了解析器函数(这很简单),我该如何处理将classOf[Double]的运行时类型从matrix更改为Matrix[Int]?那么我需要将Matrix[Double]的静态类型声明为 - matrix

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

3 个答案:

答案 0 :(得分: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方法来进行转换)。

答案 1 :(得分: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。

答案 2 :(得分: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](小心你的类型),但它会在中间做正确的事。