본문 바로가기

개발

[Scala] 순수함수와 참조투명성, 치환모형

순수함수 : 부수 효과가 없는 것

  • 부수효과 : 함수 외부세계와의 일정한 상호작용이 있는것
    • class Gift  { 
          def buyGift(cash:Cash) : MacBook = {
          val MacBook = new Mac() 
          cash.charge(MacBook.price)  // 외부세계와의 상호작용이 있다.
          MacBook
        }
      }
  • 참조투명성: 만일 모든 프로그램 p에 대해 표현식 e의 모든 출현을 e의 평가 결과로 치환해도 p의 의미에 아무 영향도 없다면 그 표현식 e는 참조 투명성이 있다. 그리고 이 참조에 투명한 모든 x에 대해 f(x)가 참조에 투명하면 함수 f는 순수하다. 
    • 예를 들어 '덧셈연산'은 순수함수다. 2 + 3 = 5 라는 표현식에 대해 프로그램 전체에 산재되어있는 2+3을 5로 바꿔도 프로그램은 문제가 없다. 
  • 참조 투명성은 함수가 수행하는 모든 것이, 함수가 돌려주는 값으로 대표된다는 불변 조건을 강제한다. 따라서 치환모형이라는 추론형식이 가능하다. 
  • scala> val x = "Hello, World"
    val x: String = Hello, World
    
    scala> val r1 = x.reverse
    val r1: String = dlroW ,olleH
    
    scala> val r2 = x.reverse
    val r2: String = dlroW ,olleH
    
    scala> val r3 = "Hello, World".reverse
    val r3: String = dlroW ,olleH
    x는 참조에 투명하다.
  • scala> val x = new StringBuilder("Hello")
    val x: StringBuilder = Hello
    
    scala> val y = x.append(", World")
    val y: StringBuilder = Hello, World
    
    scala> val z = x.append(", World")
    val z: StringBuilder = Hello, World, World
    Stringbuilder.append()는 순수함수가 아니다. new StringBuilder("Hello")와 x는 치환불가능하기 때문이다. 
  • 이런 순수성 개념을 감안하면 FP(Functional Programming)의 모듈성이 좋은 이유를 짐작할 수 있다. 

아래의 함수는 순수함수인가?

def formatAbs(x:Int) = {
    val msg = "The Value of %d is %d"
    msg.format(x,x)
}

formatAbs(3) === "The Value of %d is %d".format(x,x) 
/* 같으면 순수함수 다르면 순수함수 아님 */