순수 함수 (Pure Function)

2022. 9. 19. 00:00CSharp/Functional Programming

반응형

동일한 input 에 대해 항상 같은 값을 output 하는 함수

매개변수가 같다면 return 값이 항상 같은 함수를 말한다.

 

특징

  • side effect 가 없다. side effect 란 함수 내에서 함수 외부와의 모든 상호 작용, 함수 외부 변수를 변경하거나 다른 함수를 호출 하는 것. 
  • 일관성이 있다. 결과는 입력값에 의해서만 결정된다.  

side effect 의 예

  • 전역 상태 변경 – 예를 들어 인스턴스 필드.
  • 인수 또는 외부 변수 변경.
  • I/O 또는 HTTP 요청을 수행.
  • 현재 시간을 가져오는 것.

아래 method 는 pure function 의 예이다. 

private string Hello(string name) => $"Hello, {name}"; // pure function

Hello function 은 name 이 같은 이상 항상 같은 값을 return 한다. (순수함수)

 

만약 여기에 side effect 가 있는 datetime 이 들어간다면 impure function 이 된다. 

private string HelloWithTime(string name) => $"Hello, {name}, {DateTime.Now}"; // impure function

HelloWithTime function 은 name 이 같아도 실행할때 마다 다른 값을 return 한다.

DateTime.Now 가 state 가 되어 side effect 를 발생 시킨다. (impure function)

 

이러한 pure, impure 를 구분하고 functional programming 에서 pure function 을 선호하는 이유는

내부상태가 없기 때문에 유지 보수가 쉽고 확장이 편리하기 때문이다.

parallel 작업을 한다고 가정해보고 아래 예제를 확인하자

 

여러 사람들이 이름이 있는 list 가 있다고 하자

해당 list 에 이름들을 대문자로 바꾸고 내부함수를 통해 counter 를 계산하여 No 를 정해주는 함수가 있다고 하자

c# 으로 구현하면 아마 아래와 같을 것이다.

Impure function counter

var names = new List<string>() { "John", "Melcy", "Thor" };
int counter = 1;

string Format(string s) => $"{counter++}) {s}"; // 내부 함수 

List<string> result = names
    .Select(x => x.ToUpper())
    .Select(Format)
    .ToList();

이제 이 함수를 병렬화 해보자

 

...
List<string> result = names
    .AsParallel() // <--- parallel 추가 하여 병렬 처리
    .Select(x => x.ToUpper())
    .Select(Format)
    .ToList();
...

그리고 값을 찍어보면 우리가 예상한것과 다른 값들이 나온다.

...

2) JOHN,1) MELCY,3) THOR

2) JOHN,3) MELCY,1) THOR

3) JOHN,1) MELCY,2) THOR

...

 

카운터를 읽고 업데이트하는 여러 스레드가 있어 결과를 예측할 수 없게 된다.

순수함수 형태로 함수를 변경하여 이 문제를 해결해 보자

 

Pure function counter

var names = new List<string>() { "John", "Melcy", "Thor" };
List<string> result = names
    .AsParallel()
    .Select(x => x.ToUpper())
    .Zip(ParallelEnumerable.Range(1, names.Count), (name, c) => $"{c}) {name}")
    .ToList();

 

위와 같이 zip 을 통해 format 이라는 내부함수를 대체 하고 counter 라는 state 를 삭제였다. 

이로인해 side effect 가 제거 되었고 순수함수로 변경되었다. 

 

관련영상

https://youtu.be/-ssK235-CNE

 

반응형

'CSharp > Functional Programming' 카테고리의 다른 글

Semigroup  (2) 2022.09.21
Magma  (2) 2022.09.20
Expression, Method chaining with Extension methods  (0) 2022.09.16
Functors (Map, Filter, Reduce)  (0) 2022.09.15
Higher Order Function  (0) 2022.09.14