복붙노트

[SCALA] 불변의 데이터 구조 파악

SCALA

불변의 데이터 구조 파악

나는 스칼라을 배우고 좋은 학생으로 나는 내가 찾은 모든 규칙을 준수하려고합니다.

하나의 규칙은 다음과 같습니다 변하지!

가끔 불변의 데이터 구조와 발스과 함께 코드 모든 것을 시도했다 그래서이 정말 어렵다.

하지만 오늘 나는 나 자신에게 생각 : 유일하게 중요한 것은 객체 / 클래스에는 변경 가능한 상태가 없다해야한다는 것입니다. 이러한 방법은 서로 영향을주지 않기 때문에 나는, 불변의 스타일의 모든 방법을 코딩하도록 강요하고 있지 않다.

내 질문 : 오전 내가 올바른 또는 내가보고 해달라고 문제 / 단점이있다?

편집하다:

aishwarya에 대한 코드 예제 :

def logLikelihood(seq: Iterator[T]): Double = {
  val sequence = seq.toList
  val stateSequence = (0 to order).toList.padTo(sequence.length,order)
  val seqPos = sequence.zipWithIndex

  def probOfSymbAtPos(symb: T, pos: Int) : Double = {
    val state = states(stateSequence(pos))
    M.log(state( seqPos.map( _._1 ).slice(0, pos).takeRight(order), symb))
  }

  val probs = seqPos.map( i => probOfSymbAtPos(i._1,i._2) )

  probs.sum
}  

설명 : 변수 순서의 균일 한 마르코프 모델의 로그 가능성을 계산하는 방법이다. 상태의 방법은 이전의 모든 기호와 앞으로 기호를 취하고 그렇게하는 확률을 반환 적용됩니다.

당신이 볼 수있는 바와 같이 : 전체 방법은 단지 바르를 사용하여 훨씬 쉬울 것 몇 가지 확률을 곱합니다.

해결법

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

    1.규칙은 정말 변하지 만, 참조 투명성이 아니다. 효과 중 어느 것도 전체 프로그램의 다른 부분을 관찰 할 수 없기 때문에 그것은 로컬로 선언 된 가변 변수와 배열을 사용하여 완벽하게 OK입니다.

    규칙은 정말 변하지 만, 참조 투명성이 아니다. 효과 중 어느 것도 전체 프로그램의 다른 부분을 관찰 할 수 없기 때문에 그것은 로컬로 선언 된 가변 변수와 배열을 사용하여 완벽하게 OK입니다.

    참조 투명성 (RT)의 원칙은 이것이다 :

    모든 프로그램의 P에 대한 P의 전자가 발생할 때마다 P의 관찰 결과에 영향을 미치지 않고, 즉 평가의 결과로 대체 될 수 있다면 발현 referentially E는 투명하다.

    참고 전자는 일부 로컬 상태를 만들고 변이 경우, 그것은 아무도 이후 RT를 위반하지 않는 이런 일을 관찰 할 수 있습니다.

    그게 당신의 구현이 더 간단 바르 함께 나는 매우 의심 것을 말했다.

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

    2.함수형 프로그래밍의 경우 코드에서 간결 인과 더 수학적 접근 방식에서 가져 오는 중 하나입니다. 이 버그의 가능성을 줄이고 코드가 더 작고 더 읽기 쉽게 만들 수 있습니다. 쉽게 것에 대한 여부, 그것은 당신이 다른 문제에 대해 생각해야 않습니다. 당신은 기능적인 패턴으로 생각에 사용을 일단 그러나 기능이 그 더 필수적 스타일 쉽게 될 것입니다 가능성이 높습니다.

    함수형 프로그래밍의 경우 코드에서 간결 인과 더 수학적 접근 방식에서 가져 오는 중 하나입니다. 이 버그의 가능성을 줄이고 코드가 더 작고 더 읽기 쉽게 만들 수 있습니다. 쉽게 것에 대한 여부, 그것은 당신이 다른 문제에 대해 생각해야 않습니다. 당신은 기능적인 패턴으로 생각에 사용을 일단 그러나 기능이 그 더 필수적 스타일 쉽게 될 것입니다 가능성이 높습니다.

    완벽하게 기능하고 제로 변경 가능한 상태를 가지고 정말 열심히하지만 최소한의 변경 가능한 상태가 매우 유용합니다. 기억해야 할 것은 극단적으로 균형이 아니라 일에 모든 것이 필요하다. 변경 가능한 상태의 양을 줄임으로써 당신은 의도하지 않은 결과와 쓰기 코드를 어렵게 만들어 결국. 일반적인 패턴은 값이 불변 인 가변 변수를 가질 것이다. 이 방법은 신원 (명명 된 변수)과 값 (변수가 할당 될 수있는 불변 객체)는 별도이다.

    var acc: List[Int] = Nil
    // lots of complex stuff that adds values
    acc ::= 1
    acc ::= 2
    acc ::= 3
    // do loop current list
    acc foreach { i => /* do stuff that mutates acc */ acc ::= i * 10 }
    println( acc ) // List( 1, 2, 3, 10, 20, 30 )
    

    foreach는 우리가 foreach는 시작시에 지문 값을 통해 반복된다. ACC에 대한 모든 돌연변이는 루프에 영향을 미치지 않습니다. 이 목록 중순 반복을 변경할 수 있습니다 자바 전형적인 반복자보다 훨씬 안전합니다.

    동시성 문제가있다. 불변의 객체로 인해의 초기화가 어떤 스레드가 기간을 그 회원들에게 가시성을 확보하기 전에 최종 멤버가 발생할 오브젝트 것을 표명 JSR-133 메모리 모델 사양의 유용합니다! 그들이 최종하지 않은 경우 그들은 "가변"이며, 적절한 초기화의 보장은 없습니다.

    배우 변경 가능한 상태를 넣을 수있는 완벽한 장소입니다. 데이터를 나타내는 개체는 불변이어야한다. 다음의 예를보십시오.

    object MyActor extends Actor {
      var acc: List[Int] = Nil
      def act() {
        loop {
          react {
            case i: Int => acc ::= i
            case "what is your current value" => reply( acc )
            case _ => // ignore all other messages
          }
        }
      }
    }
    

    목록 개체의 모든 멤버는 최종 결과이며 일명 목록은 불변이기 때문에이 경우 우리는 동기화에 대해 (목록입니다) 지문 값이 아닌 걱정을 보낼 수 있습니다. 또한 불변의 우리는 다른 배우를 보낸 기본 데이터 구조를 변경할 수 있습니다 때문에 다른 배우가이 배우의 가변 상태를 변경할 수 있다는 것을 알고 있기 때문이다.

  3. ==============================

    3.Apocalisp 이미 내가 그를에 인용하려고 한 물건을 언급했기 때문에, 나는 코드를 논의 할 것이다. 당신은 단지 물건을 곱하여하고 있다고, 그러나 나는 것을 볼 수 없습니다 - 그것은 적어도 세 가지 중요한 외부 정의 방법을 참조한다 : 순서 상태와 M.log을. 그 순서는 int이며 추론 할 수있다, 그 상태는 목록 [T]와 T 반환 더블을받는 함수를 반환합니다.

    Apocalisp 이미 내가 그를에 인용하려고 한 물건을 언급했기 때문에, 나는 코드를 논의 할 것이다. 당신은 단지 물건을 곱하여하고 있다고, 그러나 나는 것을 볼 수 없습니다 - 그것은 적어도 세 가지 중요한 외부 정의 방법을 참조한다 : 순서 상태와 M.log을. 그 순서는 int이며 추론 할 수있다, 그 상태는 목록 [T]와 T 반환 더블을받는 함수를 반환합니다.

    계속 이상한 물건도 있습니다 ...

    def logLikelihood(seq: Iterator[T]): Double = {
      val sequence = seq.toList
    

    그렇게 할 이유 순서는 seqPos을 정의하는 것을 제외하고 사용하지 않는, 그래서 않습니다?

      val stateSequence = (0 to order).toList.padTo(sequence.length,order)
      val seqPos = sequence.zipWithIndex
    
      def probOfSymbAtPos(symb: T, pos: Int) : Double = {
        val state = states(stateSequence(pos))
        M.log(state( seqPos.map( _._1 ).slice(0, pos).takeRight(order), symb))
    

    않는 모두가 zipWithIndex 취소이기 때문에 사실, 당신은 여기에 대신 seqPos.map (_._ 1)의 순서를 사용할 수 있습니다. 또한, 슬라이스 (0, POS) 단지 (POS)을 가지고있다.

      }
    
      val probs = seqPos.map( i => probOfSymbAtPos(i._1,i._2) )
    
      probs.sum
    }
    

    이제 누락 된 방법을 제공,이 정말 기능적인 스타일로 작성하는 방법을 주장하기는 어렵다. 얻을 것이다 신비 방법을 유지 :

    def logLikelihood(seq: Iterator[T]): Double = {
      import scala.collection.immutable.Queue
      case class State(index: Int, order: Int, slice: Queue[T], result: Double)
    
      seq.foldLeft(State(0, 0, Queue.empty, 0.0)) {
        case (State(index, ord, slice, result), symb) =>
          val state = states(order)
          val partial = M.log(state(slice, symb))
          val newSlice = slice enqueue symb
          State(index + 1, 
                if (ord == order) ord else ord + 1, 
                if (queue.size > order) newSlice.dequeue._2 else newSlice,
                result + partial)
      }.result
    }
    

    만 나는 상태 / M.log 물건뿐만 아니라 국가의 일부가 될 수있다 생각한다. 나는 지금이처럼 쓴 것을 다른 최적화를 확인할 수 있습니다. 사용중인 슬라이딩 윈도우는 슬라이딩 물론, 저를 생각 나게한다 :

    seq.sliding(order).zipWithIndex.map { 
      case (slice, index) => M.log(states(index + order)(slice.init, slice.last))
    }.sum
    

    일부 적응 순서에있을 것입니다 그래서에만 orderth 요소에서 시작됩니다. 너무 어렵지 않다,하지만. 그럼 다시 다시 보자 :

    def logLikelihood(seq: Iterator[T]): Double = {
      val sequence = seq.toList
      val slices = (1 until order).map(sequence take) ::: sequence.sliding(order)
      slices.zipWithIndex.map { 
        case (slice, index) => M.log(states(index)(slice.init, slice.last))
      }.sum
    }
    

    나는 내가 foldLeft에 그지도를 설정하고 이러한 두 가지 방법으로 멀리 할 수 ​​내기 ... 나는 M.log 및 상태를 볼 수 있으면 좋겠다. 그리고 난 상태에서 반환하는 방법은 두 개의 매개 변수 대신에 전체 조각이 걸릴 수 있습니다 생각한다.

    아직 ... 나쁜, 그것은 무엇입니까?

  4. from https://stackoverflow.com/questions/8346119/a-grasp-of-immutable-datastructures by cc-by-sa and MIT license