트랙
/
Roc
Roc
/
연습 문제
/
배열 연산
배열 연산

배열 연산

보통

지침

기본적인 배열 연산을 구현해요.

함수형 언어에서는 length, map, reduce 같은 배열 연산을 아주 흔하게 사용해요. 기존 함수를 사용하지 않고, 일련의 기본적인 배열 연산을 직접 구현해요.

구현할 연산의 정확한 개수와 이름은 기존 이름과의 충돌을 피하기 위해 track마다 달라요. 하지만 일반적으로 구현하게 될 연산은 다음과 같아요:

  • append (주어진 두 배열에서, 두 번째 배열의 모든 항목을 첫 번째 배열의 끝에 추가해요);
  • concatenate (주어진 여러 배열의 모든 항목을 하나로 평탄화한 배열로 합쳐요);
  • filter (주어진 술어와 배열에서, predicate(item)이 True인 모든 항목의 배열을 반환해요);
  • length (주어진 배열의 전체 항목 개수를 반환해요);
  • map (주어진 함수와 배열에서, 모든 항목에 function(item)을 적용한 결과의 배열을 반환해요);
  • foldl (주어진 함수, 배열, 초기 누적자를 받아, 왼쪽부터 각 항목을 누적자에 접어 넣어요(누적해요));
  • foldr (주어진 함수, 배열, 초기 누적자를 받아, 오른쪽부터 각 항목을 누적자에 접어 넣어요(누적해요));
  • reverse (주어진 배열의 모든 원래 항목을 뒤집힌 순서로 담은 배열을 반환해요).

참고로, fold 함수(foldl, foldr)에 인자가 전달되는 순서는 중요해요.

잠깐, 이건 불가능해요!

Roc에서는 내장 함수를 하나도 쓰지 않고 이런 배열 연산을 구현하는 건 사실상 불가능해요. 배열에 원소를 뒤에 붙이거나 앞에 추가할 방법이 필요하기 때문이죠. 다른 언어에서는 Haskell의 :나 Python의 += 같은 연산자를 쓸 수 있지만, Roc에서는 List 함수를 사용해야 해요.

그래서 이 연습 문제에서는 List.append를 사용해도 돼요. 다른 내장 함수는 사용하지 마세요.

많은 함수형 프로그래밍 언어는 연결 리스트를 기본 컬렉션 타입으로 사용해요. 연결 리스트에서는 원소를 앞에 추가하거나 첫 번째 원소를 꺼내는 게 효율적이라, 그런 언어에서는 List.prepend로 이런 연산을 구현하곤 하죠. 하지만 Roc에서 List는 배열이에요 (연속된 바이트 덩어리죠). 배열은 연결 리스트와 성질이 달라요. 예를 들어 인덱스로 원소에 빠르게 접근하거나 새 원소를 뒤에 추가할 수 있죠. 그래서 Roc에서는 List.append를 자주 쓰고 List.prepend는 거의 쓰지 않아요.

이름

Roc에서는 일반 안내에 나오는 것과 이름이 조금 달라요:

  • append 대신 concat
  • concatenate 대신 join
  • length 대신 len
  • foldl 대신 fold
  • foldr 대신 fold_rev

하지만 다음 함수 이름은 Roc에서 표준이에요:

  • filter
  • map
  • reverse

힌트

이런 식으로 해봐요:

match list {
    [] => ...
    [first, .. as rest] => ...
}

또는

match list {
    [] => ...
    [.. as rest, last] => ...
}
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Roc Exercism

배열 연산 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Roc 트랙을 연습 문제 126개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.

배열 연산 깊이 살펴보기!

재귀를 실용적으로 소개하는 내용을 즐기면서, 배열 연산의 명령형 및 함수형 대안을 살펴보고, 꼬리 호출 재귀와 누산기 함수까지 깊이 파고들어요.