1

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 {
               ^
0

3 Answers 3

5

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.

Sign up to request clarification or add additional context in comments.

7 Comments

this seems the nicest solution. The readJavaFile function takes also other arguments. Is this considered good also in that case? I would have something like: def readFile(s:String, c:C, d:D)=.. . and def readFile(f:File, c:C, d:D)
c and d have default values
Looks OK to me. How do you want to handle the default values? Do you want readFile to also have default values?
yes I have edited the question with part of the real code
So if you will never need non-default values for the remaining parameters, then the code in my answer will work (with the obvious name changes). If you, then make the cvsread-String-parameter have the same default values, and pass those on to the underlying cvsread-File-parameter. Straightforward, I think?
|
4

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))

1 Comment

Ta. I'll remove my comment (and this one in a minute)
1

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))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.