Reputation: 17617
I want a function readFile
that takes as input a variable file
. File can be both a string
or a java.io.File
. Suppose to have a function readJavaFile
that accept a java.io.File
as input.
I want to do something like:
def readFile(file:Either[String, File]) = {
file match {
case s:String => readJavaFile(new File(s))
case s:File => readJavaFile(s)
}
}
What is the right way to implement this? I saw similar questions on SO but they were referring to more complex situations.
EDIT:
I am afraid that Either
is not the way to follow. I want to be able to call the function as :
readFile(s)
where s
is a string or readFile(f)
where f
is a File
EDIT: This is my real code:
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)
And I want to call it as:
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")
}
}
but I receive and error:
Error:(41, 16) in package object linalg, multiple overloaded alternatives of method csvread define default arguments.
package object linalg {
^
Upvotes: 1
Views: 1711
Reputation: 1326
I suppose you want something like this:
def readFile(file:Either[String, File]) = {
file match {
case Left(s) => readJavaFile(new File(s))
case Right(s) => readJavaFile(s)
}
}
Either is a collection of two sets: Left and Right. You can also solve it using fold:
def readFile(file: Either[String, File]): File =
readJavaFile(file.fold(new File(_), identity))
Upvotes: 4
Reputation: 41769
Sounds like a perfect case for overloading to me.
def readFile(s:String) = readJavaFile(new File(s))
def readFile(f:File) = readJavaFile(f)
Unless you already have the string-or-file in an Either
, putting them into an Either
just to get them out again seems more complex than is needed.
Upvotes: 5
Reputation: 2337
What your pattern does, is, match on the type of "file". But that is actualy Either. What you should do instead is match on the kind of Either-instance you have:
file match {
case Left(s) => readJavaFile(new File(s))
case Right(s) => readJavaFile(s)
}
What you have would work if your parameter type was Any, but you do not want to do that. (Or the union of File and String, which is something different than Either and something Scala does not have (yet))
Upvotes: 1