【问题标题】:scala pattern matching with eitherscala模式匹配
【发布时间】:2016-05-17 06:06:18
【问题描述】:

我想要一个函数readFile,它将变量file 作为输入。文件可以是stringjava.io.File。假设有一个函数 readJavaFile 接受 java.io.File 作为输入。

我想做这样的事情:

def readFile(file:Either[String, File]) = {
   file match {
     case s:String => readJavaFile(new File(s))
     case s:File => readJavaFile(s)
   }
}

实现这一点的正确方法是什么?我在 SO 上看到了类似的问题,但他们指的是更复杂的情况。

编辑: 恐怕Either 不是遵循的方式。我希望能够将该函数称为: readFile(s) 其中s 是一个字符串或readFile(f) 其中f 是一个File

编辑: 这是我的真实代码:

def csvread(file: File,
             separator: Char=',',
             quote: Char='"',
             escape: Char='\\',
             skipLines: Int = 0): DenseMatrix[Double] = {
    val input = new FileReader(file)
    var mat = CSVReader.read(input, separator, quote, escape, skipLines)
    mat = mat.takeWhile(line => line.length != 0 && line.head.nonEmpty) // empty lines at the end
    input.close()
    if(mat.length == 0) {
      DenseMatrix.zeros[Double](0,0)
    } else {
      DenseMatrix.tabulate(mat.length,mat.head.length)((i,j)=>mat(i)(j).toDouble)
    }
  }

  def csvread(file: String,
              separator: Char=',',
              quote: Char='"',
              escape: Char='\\',
              skipLines: Int = 0): DenseMatrix[Double] = csvread(new File(file), separator, quote, escape, skipLines)

我想这样称呼它:

package breeze.linalg

/**
  * Created by donbeo on 07/02/16.
  */

import org.scalatest._
import org.scalatest.junit._
import org.scalatest.prop._
import org.junit.runner.RunWith
import breeze.linalg.csvread
import java.io.File

@RunWith(classOf[JUnitRunner])
class ReadCsvTest extends FunSuite with Checkers{

  test("Try readcsv") {
    val f = csvread(new File("/Users/donbeo/Documents/datasets/glass.csv"))
    val v = csvread("/Users/donbeo/Documents/datasets/glass.csv")

  }

}

但我收到并出错:

Error:(41, 16) in package object linalg, multiple overloaded alternatives of method csvread define default arguments.
package object linalg {
               ^

【问题讨论】:

    标签: java scala


    【解决方案1】:

    对我来说,这听起来像是一个完美的超载案例。

     def readFile(s:String) = readJavaFile(new File(s))
     def readFile(f:File) = readJavaFile(f)
    

    除非您已经将字符串或文件放在 Either 中,否则将它们放入 Either 只是为了再次取出它们似乎比需要的复杂。

    【讨论】:

    • 这似乎是最好的解决方案。 readJavaFile 函数还接受其他参数。在那种情况下这也被认为是好的吗?我会有类似的东西:def readFile(s:String, c:C, d:D)=.. .def readFile(f:File, c:C, d:D)
    • cd 有默认值
    • 对我来说看起来不错。你想如何处理默认值?你想让 readFile 也有默认值吗?
    • 是的,我已经用部分真实代码编辑了问题
    • 因此,如果您永远不需要其余参数的非默认值,那么我的答案中的代码将起作用(具有明显的名称更改)。如果你是这样,那么让 cvsread-String-parameter 具有相同的默认值,并将它们传递给底层的 cvsread-File-parameter。我认为直截了当?
    【解决方案2】:

    我想你想要这样的东西:

      def readFile(file:Either[String, File]) = {
        file match {
          case Left(s) => readJavaFile(new File(s))
          case Right(s) => readJavaFile(s)
        }
      }
    

    任何一个都是两个集合的集合:左和右。 你也可以使用 fold 来解决它:

    def readFile(file: Either[String, File]): File = 
      readJavaFile(file.fold(new File(_), identity))
    

    【讨论】:

    • Ta。我将删除我的评论(一分钟后删除此评论)
    【解决方案3】:

    您的模式的作用是匹配“文件”的类型。但这实际上是。相反,您应该做的是匹配您拥有的 Either-instance:

    file match {
      case Left(s) => readJavaFile(new File(s))
      case Right(s) => readJavaFile(s)
    }
    

    如果您的参数类型是 Any,您所拥有的会起作用,但您不想这样做。 (或者 File 和 String 的联合,这与 Either 不同,Scala 还没有)

    【讨论】:

      猜你喜欢
      • 2021-12-17
      • 2014-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-31
      • 2015-10-07
      • 2011-05-24
      相关资源
      最近更新 更多