복붙노트

[SCALA] "시도 -과 - 자원 / 사용"에 대한 간단한 스칼라 패턴 (자동 자원 관리)

SCALA

"시도 -과 - 자원 / 사용"에 대한 간단한 스칼라 패턴 (자동 자원 관리)

C #이는 IDisposable 인터페이스를 사용하고있다. 자바 7+ 시도하고 AutoCloseable 인터페이스와 동일한 기능이 있습니다. 스칼라는이 문제에 대한 자신의 구현을 선택할 수 있습니다.

스칼라 팔은 인기있는 선택이 될 것 같습니다, 그리고 형태 보증 된 직원에 의해 관리되고 있습니다. 그러나, 아주 등의 간단한 동작에 대한 복잡한 것 같다. 사용 설명서는 간단하지만 그 코드는 내부적으로 작동하고 모두가 다소 복잡 방법을 이해 명확합니다.

난 그냥 다음 슈퍼 간단한의 ARM 솔루션을 썼다 :

object SimpleARM {
  def apply[T, Q](c: T {def close(): Unit})(f: (T) => Q): Q = {
    try {
      f(c)
    } finally {
      c.close()
    }
  }
}

해결법

  1. ==============================

    1.하나의 간단한 대출 패턴 당신의 접근 방식은 모두 관리 할 필요, 여러 자원을 작업에 필요하지 않은 긴만큼 잘 작동한다. 함께 사용할 수 있다는 모나드 접근 방식을 스칼라 - 팔.

    하나의 간단한 대출 패턴 당신의 접근 방식은 모두 관리 할 필요, 여러 자원을 작업에 필요하지 않은 긴만큼 잘 작동한다. 함께 사용할 수 있다는 모나드 접근 방식을 스칼라 - 팔.

    import resource.managed
    
    managed(openResA).and(managed(openResB)) acquireFor { (a, b) => ??? }
    
    val res = for {
      a <- managed(openResA)
      b <- managed(openResB)
      c <- managed(openResC)
    } yield (a, b, c)
    
    res acquireAndGet {
      case (a, b, c) => ???
    }
    

    스칼라 팔에 알 수있는 주요 기능은 BTW 정말 복잡하지, resource.managed 및 {승리했습니다의 경우,} .acquired된다.

  2. ==============================

    2.여기 내 새로운 간단한이며, 한 눈에, 스칼라 ARM에서 이해합니다. 이것은 완전히 내가 여러 자원 및 수율 값을 포함 생각할 수있는 모든 사용 사례 지원합니다. 이것은 이해의 사용 구문은 매우 간단합니다 :

    여기 내 새로운 간단한이며, 한 눈에, 스칼라 ARM에서 이해합니다. 이것은 완전히 내가 여러 자원 및 수율 값을 포함 생각할 수있는 모든 사용 사례 지원합니다. 이것은 이해의 사용 구문은 매우 간단합니다 :

    class AutoCloseableWrapper[A <: AutoCloseable](protected val c: A) {
      def map[B](f: (A) => B): B = {
        try {
          f(c)
        } finally {
          c.close()
        }
      }
    
      def foreach(f: (A) => Unit): Unit = map(f)
    
      // Not a proper flatMap.
      def flatMap[B](f: (A) => B): B = map(f)
    
      // Hack :)    
      def withFilter(f: (A) => Boolean) = this
    }
    
    object Arm {
      def apply[A <: AutoCloseable](c: A) = new AutoCloseableWrapper(c)
    }
    

    여기 데모 사용이다 :

    class DemoCloseable(val s: String) extends AutoCloseable {
      var closed = false
      println(s"DemoCloseable create ${s}")
    
      override def close(): Unit = {
        println(s"DemoCloseable close ${s} previously closed=${closed}")
        closed = true
      }
    }
    
    object DemoCloseable {
      def unapply(dc: DemoCloseable): Option[(String)] = Some(dc.s)
    }
    
    object Demo {
      def main(args: Array[String]): Unit = {
        for (v <- Arm(new DemoCloseable("abc"))) {
          println(s"Using closeable ${v.s}")
        }
    
        for (a <- Arm(new DemoCloseable("a123"));
             b <- Arm(new DemoCloseable("b123"));
             c <- Arm(new DemoCloseable("c123"))) {
          println(s"Using multiple resources for comprehension. a.s=${a.s}. b.s=${b.s}. c.s=${c.s}")
        }
    
        val yieldInt = for (v <- Arm(new DemoCloseable("abc"))) yield 123
        println(s"yieldInt = $yieldInt")
    
        val yieldString = for (DemoCloseable(s) <- Arm(new DemoCloseable("abc")); c <- s) yield c
        println(s"yieldString = $yieldString")
    
        println("done")
      }
    }
    
  3. ==============================

    3.이 코드 I를 사용하는 것입니다 :

    이 코드 I를 사용하는 것입니다 :

    def use[A <: { def close(): Unit }, B](resource: A)(code: A ⇒ B): B =
        try
            code(resource)
        finally
            resource.close()
    

    자바 시도 -과 - 자원과는 달리, 자원이 AutoCloseable를 구현할 필요는 없습니다. 만 close () 메소드가 필요하다. 그것은 단지 하나 개의 자원을 지원합니다.

    여기의 InputStream과 사용 예제입니다 :

    val path = Paths get "/etc/myfile"
    use(Files.newInputStream(path)) { inputStream ⇒
        val firstByte = inputStream.read()
        ....
    }
    
  4. ==============================

    4.http://illegalexception.schlichtherle.de/2012/07/19/try-with-resources-for-scala/

    http://illegalexception.schlichtherle.de/2012/07/19/try-with-resources-for-scala/

    또한 아마 더 "자바 사양에 따라"관점에서 깨끗하고 있지만, 또 다른 구현은 여러 자원을 지원하기 위해 실패

  5. ==============================

    5.이 사람은 정말 잘 나를 위해 작동합니다 :

    이 사람은 정말 잘 나를 위해 작동합니다 :

      implicit class ManagedCloseable[C <: AutoCloseable](resource: C) {
        def apply[T](block: (C) => T): T = {
        try {
          block(resource)
        } finally {
          resource.close()
        }
      }
    

    이 아파치 카산드라 클라이언트 코드의 예를 들어 그것을 사용 :

    val metadata = Cluster.builder().addContactPoint("vader").withPort(1234).build() { cluster =>
      cluster.getMetadata
    }
    

    심지어 짧은은 :

    val metadata = Cluster.builder().addContactPoint("sedev01").withPort(9999).build()(_.getMetadata)
    
  6. ==============================

    6.개선 난 당신이 제안한 방법으로 추천 할 수 있습니다 :

    개선 난 당신이 제안한 방법으로 추천 할 수 있습니다 :

      def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): B = {
        try
          code(resource)
        finally
          resource.close()
      }
    

    사용하는 것입니다 :

      def autoClose[A <: AutoCloseable, B](resource: A)(code: A ⇒ B): Try[B] = {
        val tryResult = Try {code(resource)}
        resource.close()
        tryResult
      }
    

    이럴 시도는 [B]는 tryResult 갖는 나중에에게 쉽게 제어 흐름을 허용한다.

  7. ==============================

    7.(: 나는 저자 해요 공개) 고르지의 게으른 TryClose 모나드 당신이 찾고있는 수 있습니다. 그것은 스칼라의 시도와 매우 유사하지만, 자동으로 자동으로 자원을 닫습니다.

    (: 나는 저자 해요 공개) 고르지의 게으른 TryClose 모나드 당신이 찾고있는 수 있습니다. 그것은 스칼라의 시도와 매우 유사하지만, 자동으로 자동으로 자원을 닫습니다.

    val ds = new JdbcDataSource()
    val output = for {
      conn  <- TryClose(ds.getConnection())
      ps    <- TryClose(conn.prepareStatement("select * from MyTable"))
      rs    <- TryClose.wrap(ps.executeQuery())
    } yield wrap(extractResult(rs))
    
    // Note that Nothing will actually be done until 'resolve' is called
    output.resolve match {
        case Success(result) => // Do something
        case Failure(e) =>      // Handle Stuff
    }
    

    추가 정보를 원하시면 여기를 참조하십시오 : https://github.com/choppythelumberjack/tryclose

  8. from https://stackoverflow.com/questions/25634455/simple-scala-pattern-for-using-try-with-resources-automatic-resource-manageme by cc-by-sa and MIT license