Функция высокого порядка Scala - PullRequest
0 голосов
/ 04 сентября 2018

я хочу сделать функцию параметром построения класса. У меня есть некоторые функции, которые я хочу вычислить в классе (какой-то ленивый расчет)

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, для которого требуется PreparedStatement, для которого требуется Id и Connection

1 Ответ

0 голосов
/ 04 сентября 2018

Вы можете сделать это. Это будет выглядеть так

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

Или вы можете использовать карри

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

Для вас расширенный вопрос, я могу предложить этот класс:

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

...