Scala高阶函数

时间:2018-09-04 09:01:08

标签: scala user-defined-functions implicit

我想将功能作为类构造的参数。 我有一些要在课堂上计算的函数(某种惰性计算)

class Foo(calc: PGSimpleDataSource => Connection => PreparedStatement => ResultSet => Option[A] ??? ) {

  here some logic like:

  def runCalc = calc ( resultSet ( preparedStatement ( connection )

  resultSet.close()
  preparedStatement.close()
  connection.close()

  send result somewhere ...

}

准备一些功能

implicit val dataSource: PGSimpleDataSource = Service.ds

implicit def getConnection(implicit ds: PGSimpleDataSource): Connection = ds.getConnection

implicit def getPreparedStatement(userId: UUID)(implicit con: Connection): PreparedStatement ={
    val st = con.prepareStatement("SELECT * FROM bar WHERE id = CAST(? as UUID)")
    st.setString(1, id.toString)
    st
  }

implicit def getResultSet(implicit ps: PreparedStatement): ResultSet = ps.executeQuery()

implicit def mapping(implicit rs: ResultSet): Option[Bar] = {
    Iterator.continually(rs.next)
      .takeWhile(identity)
      .map(_ => Bar(UUID.fromString(rs.getString(1)))).toList.headOption
  }

然后是一些功能,例如:

def getInstance(id: UUID) = new Foo(???)

val foo = getInstance(id)

foo.runCalc()

有可能吗?请帮助

更新:

我试图像这样上课:

class Foo[A](
                con: => Connection,
                ps: => PreparedStatement,
                rs: => ResultSet,
                mapping: => Option[A],
                calc: Connection => PreparedStatement => ResultSet => Option[A]
              ) {
  def run(): Unit = {
    val result: Option[A] = calc(con)(ps)(rs)(mapping)

    rs.close()
    ps.close()
    con.close()
  }
}

但是我不明白如何编写如下的“ f”函数

需要映射(getResultSet(getPreparedStatement(id,getConnection))

换句话说,映射需要ResultSet,而ResultSet需要带ID和Connection的PreparedStatement

1 个答案:

答案 0 :(得分:1)

您可以做到。看起来像这样

case class Foo(calc: String => String => String => Option[String]) {
  def run = {
    val p1 = "p1"
    val p2 = "p2"
    val p3 = "p3"

    calc(p1)(p2)(p3)
  }
}

用法示例

object App extends App {
  val f = (x: String) => (y: String) => (z: String) => {
    Option(x + y + z)
  }
  val foo = Foo(f)
  println(foo.run)
}

或者您可以使用currying

object App extends App {
  val f = (x: String, y: String, z: String) => {
    Option(x + y + z)
  }

  val foo = Foo(f.curried)

  println(foo.run)
}

编辑

对于您的扩展问题,我可以建议此类:

case class Foo[A](
                   getConnection: () => Connection,
                   getStatement: Connection => PreparedStatement,
                   getResultSet: PreparedStatement => ResultSet,
                   mapping: ResultSet => Option[A]) {
  def run(): Option[A] = {
    val connection = getConnection()
    try{
      val statement = getStatement(connection)
      try{
        val resultSet = getResultSet(statement)
        try{
          mapping(resultSet)
        }finally {
          resultSet.close()
        }
      }finally{
        statement.close()
      } 
    } finally {
      connection.close()
    }
  }
}

用法示例:

  val foo = Foo(
    () => new Connection(),
    connection => new PreparedStatement(),
    statement => new ResultSet(),
    resultSet => Option("")
  )

所有这些功能都具有上一步中的参数,因此,例如,当您创建ResultSet时,可以使用statement(但是不能使用connection)。