* 부작용(side effect)


함수가 결과값 이외에 다른 상태를 변경시킬 때 부작용이 있다고 말한다. 문서에서 side effect에 대해서 부정적으로 봐서는 안된다. 



* 순수 함수

부작용이 없는 함수



* 참조 투명성(referential transparency)


참조 투명성(referential transparency)은 부작용(side effect)이 없음을 표현하는 속성이다. 

입력 값에 대해 항상 같은 값을 돌려주는 것 외에 다른 기능이 없다. 내부적으로 관리되는 변수(상태)에 영향이 없는 것을 말한다. 



참조 투명성에 대한 예제는 다음과 같다.  항상 매개변수를 주면, 그 값을 언제 어디서든 그 값을 기대할 수 있다. 


scala> def sum(x: Int, y: Int): Int = x + y

sum: (x: Int, y: Int)Int


scala> sum(sum(1, 2), 3)

res2: Int = 6


scala> sum(3, 3)

res3: Int = 6





하지만, 변수(상태)값과 의존성이 있는 코드가 있다고 하자. sum 메소드를 호출하면, 계속 값이 변경된다. 이를 참조 투명성이 없다고 말할 수 있다. 

scala> var m = 0
m: Int = 0

scala> def sum(x: Int, y: Int): Int = { m = m + x + y; m}
sum: (x: Int, y: Int)Int

scala> sum(sum(1, 2), 3)
res10: Int = 21

scala>  sum(3, 3)
res11: Int = 27

scala>  sum(3, 3)
res12: Int = 33




sum 메소드는 바로 값을 기억하고 연산에 사용되기 때문에, 순수 함수가 아니고 참조 투명성이 없다. 


함수형 프로그래밍 언어에서는 참조 투명성을 극히 중요하는 것 같아서, 함 정리했다. 





나중에 scalaz의 Task와 Future를 설명하겠지만.. 

scala의 Future는 계산한 후 Future의 결과를 기억하는 반면, 

scalaz(외부 라이브러리)의 Task는 unsafePerformSync를 호출할 때마다 계산을 수행한다. 


다른 말로 말하면, Task는 참조 투명성이고 Future보다는 함수형 프로그래밍 패러다임에 가깝다.





이런 내용을 잘 설명한 내용이 하스켈의 참조 투명성 자료이다. 

https://wiki.haskell.org/Referential_transparency


Posted by '김용환'
,

scala에서 REPL을 사용하려면 간단하게 scala를 실행하면 된다.


$ scala 



그리고, 필요한 내부 라이브러리는 다음처럼 import문을 사용한다.


scala> import scalaz._




만약 외부 라이브러리(lib)를 어떻게 입력해야 하는가?



그러기 위해서는 sbt를 활용할 수 있다. 



sbt 프로젝트에서 sbt를 실행해서 아래처럼 간단하게 사용할 수 있다.  (참고로 sbt는 디렉토리 기반이기 때문에 global 설정이 아니다)


$ sbt



set scalaVersion := "2.11.8"

set libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.2.0"

set initialCommands := ""

set initialCommands += "import scalaz._, Scalaz._, scala.concurrent._, scalaz.concurrent._, java.util.concurrent._"

session save

console



console을 실행하면 다음과 같은 로그가 생성된다. lib을 로딩하고,import 문이 자연스럽게 만들어진다. 


[info]

import scalaz._

import Scalaz._

import scalaz.concurrent._

import java.util.concurrent._

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).

Type in expressions for evaluation. Or try :help.



실행 환경을 구성한다. 

scalaz.concurrent.Promise는 외부 라이브러리이지만, REPL에서 사용할 수 있다. 

scala> val p = Promise[Int]
p: scala.concurrent.Promise[Int] = List()


scala> p.future.value
res19: Option[scala.util.Try[Int]] = None


scala>  p.success(20)
res20: p.type = Success(20)

scala> p.future.value
res21: Option[scala.util.Try[Int]] = Some(Success(20))





만약 중간에 외부 라이브러리를 읽어야 한다면, Ctrl + D를 누르고,  다시 모드 환경에서 내용을 설정한다.


ctrl + D를 눌러 REPL import문을 다시 구성할 수 있다. 


scala> // 여기서 Ctrl + D


[success] Total time: 371 s...



> set initialCommands := ""

> set initialCommands += "import scalaz._, Scalaz._, scala.concurrent._, scalaz.concurrent._, java.util.concurrent._, java.util.collections._ "





Posted by '김용환'
,