본문 바로가기

프로그래밍 기술 노트/Functional Study

Lazy 한 시퀀스에서의 부수효과가 있는 함수 사용시 주의

포커 게임을 제작하다가 다음과 같은 코드를 사용했다.

let Random = System.Random()

type Suit = Spade | Dia | Heart | Club 

type Card = {suit:Suit; number:int}

type Concentration = Card * bool * int

let Deck = seq { for s in [Spade;Dia;Heart;Club]  do 
                    for y in 1..12 ->  ({suit=s;number=y},true) }
let Shuffled = Seq.sortBy (fun x -> Random.Next()) Deck 

let GameDeck = Seq.mapi (fun i (c,b) -> Concentration(c,b,i)) Shuffled

Deck 을 만들고

Shuffle 하기위해 랜덤을 사용하였고 섞었고

필요에의하여 인덱스를 부여하였는데

 

로직을짜는데 자꾸 말도 안되게 돌아가길래 확인해보니

GameDeck이 사용할때마다 값이 계속 바뀌는문제가 발생..

이유를 생각해보니 Seq는 Lazy 한 평가를 하기때문에 사용할때 평가가 이루어진다.

사용할때마다 -> Random.Next 가 사용하여 섞이고 반복..

이로인하여 완전불순수한 게임덱의 탄생..

 

굳이 F# 뿐 만 아니라 Lazy 한 시퀀스에서 순수하지 않은 함수가 사용된경우 시퀀스 자체가 문제가 될수있다.

따라서 eager 하게 변경해주어야한다.

let GameDeck = Seq.mapi (fun i (c,b) -> Concentration(c,b,i)) Shuffled
               |> Seq.toList

 

728x90