프로그래밍/Scala

[Scala] 재귀함수

Dibrary 2022. 9. 1. 09:50
반응형

안녕하세요 Dibrary입니다.

어떤 언어든 함수 기능은 다 가지고 있습니다. 그럼에도 스칼라의 함수가 좀 더 특별하게 느껴지는 이유는 스칼라로 순수함수를 구성하면 굉장히 유용하기 때문일거 같네요.

 

순수함수가 가지는 특징은 아래와 같습니다.

  • 입력 매개변수만을 가지고 계산을 수행한다.
  • 동일 입력에 대해 항상 같은 값을 반환한다.
  • 함수 외부의 어떤 데이터에 영향을 주거나 / 받지 않는다.

이런 특징 덕분에 스칼라는 함수형 프로그래밍에 적합한 언어입니다. 특히 부수효과를 발생시키지 않을 수 있다는 점이 매력적이죠.

 


간단하게 곱셈을 하는 함수를 정의해보았습니다.

33*44의 결과를 내보냅니다.

 

함수 정의할 때 중요한 점은 자료형을 명시해주어야 한다는 겁니다. 명시하지 않으면 아래와 같이 에러를 볼 수 있습니다.

 

임의 문자열에 대해 조건처리하는 함수를 작성해 보았습니다.

 

만일 함수의 반환값이 없다면 어떨까요? 예를 들면, 단순히 출력만 하고 끝내는 함수 같이 말이죠.

자료형을 Unit으로 써 주면 됩니다.

 

반환이 없을 수도 있다면, 당연히 전달인자가 없을 수도 있겠죠?

전달인자를 그냥 안 써주기만 해도 함수는 동작합니다.

 


스칼라는 함수 전달인자 위치에 표현식을 넣어서 전달할 수도 있습니다.

표현식을 쓰려면 ( ) 대신에 { }로 바꿔서 해 줘야 합니다. 위 코드는 1.32라는 rate값의 5배인 6.6이 함수 안으로 들어가서 0.66이 출력되는 것입니다.

 

흔히 알고리즘을 풀 때 많이 쓰는 '재귀'함수도 가능합니다.

주어진 수의 n제곱을 구하는 함수인데 power 함수 내부에 power함수를 다시 쓰고 있습니다. (재귀로 들어가면서 곱한 값이 반환되죠.

 

그런데, 우리가 흔히 알다싶이 재귀 깊이가 너무 깊으면 메모리를 왕창 써버리죠...

이 문제를 그나마 약간 완화할 수 있는 방법이 'tail-recursion' 입니다. tail-recursion으로 하겠다는 표기를 함수앞에 달아놓으면 됩니다. 그 표기는 @annotation.tailrec 입니다.

앞서 사용한 power 함수에 @annotation.tailrec을 달았는데... 뭔가 이상하죠?

해당 tail-recursion을 사용하고 싶으면, 함수의 마지막줄이 재귀적 호출 그 자체여야 합니다. 위 코드는 else라서 에러가 난 것이죠.

결국, 이 코드의 에러를 없에려면 순서를 바꾸기만 하면 됩니다. if와 else의 내용을 말이죠.

아까와 똑같은 동작을 하는 함수가 만들어졌습니다. 

728x90
반응형