(Scala TYPE-SAFETY)仅当字符串具有.txt扩展名时才将字符串作为参数,否则会编译错误吗?

时间:2018-06-30 17:16:55

标签: scala types

我在考虑是否有可能创建一种将字符串作为参数的数据结构,并且该字符串不包含.txt或类似的东西,这会给我带来编译错误吗?

我可以针对我的问题进行具体说明-我试图将文件作为函数的参数(源),但被告知当前我正在传递任何类型的文件,并且只应采用文本文件,因此没有正确完成。我该如何处理? -谢谢!! ^^

3 个答案:

答案 0 :(得分:4)

是的,这不是问题。最大的问题是您是否应该这样做。如果您的代码是各种各样的库,那么在某些情况下这可能是有道理的。从http4s项目中检出Uri.uri

在您的情况下,实现可能如下所示:

import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

class Macros(val c: Context) {
  import c.universe._
  def txtFile(fileName: c.Expr[String]): Tree =
    fileName.tree match {
      case Literal(Constant(s: String)) if s.endsWith(".txt") =>
        fileName.tree
      case _ =>
        c.abort(
          c.enclosingPosition,
          s"Supplied parameter is not a text file"
        )
    }
}

object MyObject {
  def txtFile(fileName: String): String = macro Macros.txtFile
}

您可以这样使用:

val x: String = txtFile("abc.tx") // Fails to compile
val y: String = txtFile("abc.txt") // Compiles

同样可以做到,但是您可能想使用Option:-)

答案 1 :(得分:3)

假设String来自代码库之外的其他地方(Web请求,cmd行),则需要将该String传递给接受String的对象。这样,您就可以将String转换为特殊的文件名数据类型。因此,我看不出有什么方法可以防止某种运行时检查。

如果要进行运行时检查以避免错误,则可以返回Option,如果String不是有效的文件名,则返回None

答案 2 :(得分:1)

您可以使用refined库:

type TxtSuffix = EndsWith[W.`".txt"`.T]
type TxtFile = String Refined TxtSuffix

要构造TxtFile,您需要给它一个以“ .txt”结尾的字符串:

val file: TxtFile = refineMV[TxtSuffix]("some.pdf") // compiler error
error: Predicate failed: "some.pdf".endsWith(".txt")