순수 함수로 부작용 피하기

 

순수 함수 : 동일한 입력에 대해서는 항상 같은 결과를 반환하는 함수

 

함수 내에서 전역 변수 등 외부의 변수를 참조하지 않기 때문에 외부 상태를 변경하는 부작용이 발생하지 않는다.

 

float circleArea(float r)
{
    return 3.14f * r * r;
}

float f = 2.5f; // 지역 변수
for (int i = 1; i <= 5; ++i) circleArea(f);

 

동일한 입력에 대해 항상 같은 값을 출력하므로 circleArea는 순수 함수이다.

 

int currentState = 0; // 전역 변수

int increment(int i)
{
    currentState += i;
    return currentState;
}

int fix = 5; // 지역 변수
for (int i = 1; i <= 5; ++i) increment(fix);

 

increment는 매번 다른 값을 반환할 뿐만 아니라 함수 외부의 전역 변수에 의존하므로 순수 함수가 아니다.

 

float phi = 3.14f; // 전역 변수

float circleArea(float r)
{
    return phi * r * r;
}

float f = 2.5f; // 지역 변수
for (int i = 1; i <= 5; ++i) circleArea(f);

 

circleArea는 매번 같은 값을 반환하지만 함수 외부의 전역 변수를 참조하기 때문에 순수 함수가 아니다.

 

추가로 함수에 의해 변경되는 전역 변수나 참조자의 상태뿐만 아니라 화면 출력, I/O 연산 등의 IPC 역시 부작용에 포함된다.

 

 

 

 

커링으로 함수 분리하기

 

커링 : 여러 개의 인수를 갖는 하나의 함수를 단일 인수를 갖는 여러 개의 연속된 함수로 나누는 것

 

template<typename Func, typename... Args>
auto curry(Func func, Args... args)
{
    return [=](auto... lastParam) {
        return func(args..., lastParam...);
    };
}

int areaOfRectangle(int length, int width)
{
    return legnth * width;
}

auto length5 = curry(areaOfRectangle, 5);

for (int i = 0; i <= 5; ++i) std::cout << length5(i) << '\n';
/* length5(i) == areaOfRectangle(5, i); */

 

다수의 인자를 받는 함수를 단일 인자를 받는 함수로 줄인 코드이다.

 

auto multiply2(int a)
{
    return [=](int b) {
        return a * b;
    };
}

auto multiply3(int a)
{
    return [=](int b) {
        return multiply2(a * b);
    };
}

std::cout << multiply3(5)(10)(2) << '\n';

 

이런 식으로도 사용 가능하다.

+ Recent posts