Move는 반복문 (for, while 등)을 지원하지 않지만, 재귀함수와 조건문을 통해서 반복적인 작업을 수행할 수 있습니다. Move에서 반복문을 지원하지 않는 이유는 무한 루프를 방지하고, 블록체인 환경에서의 계산 자원을 효율적으로 사용하기 위함입니다. 대신, 주어진 작업을 반복적으로 수행해야 할 경우 재귀적 접근 방식을 사용해야 합니다.
다음은 Move에서 반복문 대신 재귀를 사용하는 방법과 그 예시입니다.
1. 재귀를 통한 반복작업
Move는 재귀함수를 지원하므로, 함수가 특정 조건에 도달할 때까지 자신을 호출하도록 하여 반복작업을 수행할 수 있습니다. 예를 들어서, 1부터 n까지의 합을 구할 때 재귀를 사용할 수 있습니다.
module ExampleModule{
public fun sum_recursive(n :u64):u64{
if( n== 0 ){
0
}else{
n + sum_recursive(n-1)
}
}
}
위 예제에서 sum_recursive 함수는 n이 0이 될 때까지 n값을 더하며 자신을 호출하여 재귀적으로 합을 구합니다. if문을 사용해 종료조건 n==0 을 지정하고, 그 외에는 재귀 호출을 통해서 반복작업을 수행합니다.
2. 조건문을 통한 반복분기 처리
조건문을 사용해 특정 조건에 따라 다른 처리를 반복할 수 있습니다. Move에서는 각 함수가 호출될 때마다 스택 프레임이 생성되기 때문에, 재귀적으로 호출하는 방법은 반복문의 대안이 됩니다. 예를 들어서, 배열의 값을 순차적으로 누적하는 작업도 재귀를 통해서 가능합니다.
3. 리스트와 재귀를 활용한 반복 예제
다음은 리스트의 모든 요소를 누적하여 더하는 함수입니다. Move는 기본적으로 배열타입을 제공하지 않지만, 데이터 구조로 리스트를 사용할 수 있으며, 리스트의 각 요소를 재귀적으로 처리하여 반복작업을 수행할 수 있습니다.
module ExampleModule{
use std::vector; // 벡터(리스트) 라이브러리 가져오기
public fun sum_vector(vec: vector<u64>, index, u64): u64{
if( index == vector::length<u64>(&vec) ){
0
}else{
vector::borrow<u64>(&vec, index) + sum_vector(vec, index+1)
}
}
}
이 코드는 u64 타입의 숫자들을 담고 있는 벡터(리스트)를 입력받아서, 벡터에 있는 모든 숫자를 더한 값을 반환받는 함수입니다.
한 줄씩 살펴볼까요?
3-1.
public fun sum_vector(vec: vector<u64>, index: u64): u64
- vec: u64 타입의 요소들을 담고 있는 벡터입니다.
- index: 현재 위치를 나타내는 인덱스입니다. 이 인덱스를 통해서 벡터의 특정 위치에 접근합니다.
- 함수는 u64 타입의 합계 값을 반환합니다.
3-2. 종료조건
if (index == vector::length<u64>(&vec))
- vector::length<u64>(&vec) 는 벡터 vec의 길이(요소개수)를 반환합니다.
- &vec은 vec의 주소를 전달하여 벡터가 직접 복사되지 않고 참조를 통해 길이를 가져옵니다.
- if( index == vector :: length<u64>(&vec)) 부분은 종료 조건입니다.
index가 벡터 길이와 같아지면, 벡터의 모든 요소를 순회했다는 뜻이므로, 더이상 추가로 더할 요소가 없습니다. 이 경우에 함수는 0을 반환하여 재귀 호출이 종료됩니다.
3-3
vector::borrow<u64>(&vec, index)
- 이것은 Move 표준 라이브러리의 vector 모듈에 있는 함수로, 벡터의 특정 인덱스에 있는 요소를 읽을 때 사용하는 함수입니다.
vector::borrow 함수의 역할
- vector::borrow<T>(&vec, index) 는 벡터 vec의 index 위치에 있는 요소에 접근할 수 있도록 참조(&)를 제공합니다.
- Move에서는 직접적으로 벡터의 특정 위치에 접근하기 보다는, 안전한 접근을 위해 borrow를 사용해 참조를 얻어오는 방식으로 데이터를 읽습니다.
vector::borrow<u64>(&vec, 0)
- 이것은 u64가 담긴 벡터 vec의 0번째 요소의 참조입니다.
4. 무한 재귀 방지
재귀함수는 종료조건을 명확히 정의하지 않으면, 스택오버플로우를 일으킬 수 있습니다. 따라서 재귀함수 사용 시 항상 종료 조건을 명시적으로 지정하는 것이 중요합니다. 예를 들어 sum_recursive 함수에서 if(n==0)을 종료 조건으로 사용했습니다. 이처럼 종료 조건을 설정해두면 무한 재귀가 발생하지 않습니다.
그러나 주의 사항이 한가지 더 있습니다.
재귀 깊이에 대해서 고려를 잘 해야합니다.
블록체인 스마트 컨트랙트에서는 재귀 깊이가 너무 깊으면 계산 자원을 과다하게 소모할 수 있습니다. 따라서 Move에서 재귀를 사용할 때는 충분히 깊이가 낮은 반복작업에서만 사용하는 것이 좋습니다. 대규모 반복 작업이 필요한 경우에는 스마트 컨트랙트 설계를 조정해 여러 트랜잭션으로 나누는 것도 한가지 방법입니다.
'Blockchain > Move' 카테고리의 다른 글
자료형에 대해서 알아볼까요 (0) | 2024.10.27 |
---|---|
Move의 특징 (0) | 2024.10.27 |