简体   繁体   中英

Scala High Order Function

i want to make function as parameter of class construction. i have some functions that i want to calculate in class (some kind of lazy calculation)

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

}

prepare some functions

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
  }

and then some function like:

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

val foo = getInstance(id)

foo.runCalc()

Is it possible? Please Help

upd:

i tried to do my class like this :

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

but i don't understand how to write "f" function as written below

it need do mapping( getResultSet ( getPreparedStatement (id, getConnection))

in other words mapping need ResultSet that need PreparedStatement that need Id and Connection

You can do it. It will look like this

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

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

Usage example

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

Or you can use 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)
}

EDIT

For you extended question I can propose this class:

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

Usage example:

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

All those function have parameter from previous step so when for example you create ResultSet you can use statement (but you can't use connection ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM