The Array2 구조

The Array2 구조

Array2 구조는 다형(polymorphic) 가변 2차원 배열을 제공해요. 1차원 배열과 마찬가지로, 두 배열이 같으려면 같은 배열이어야 해요. 즉 원시 배열 생성자의 같은 호출로 만들어졌을 때만 같고 그 외에는 같지 않아요. 길이 0인 배열에도 동일해요. 2차원 배열의 요소는 정수 쌍 (i,j)로 인덱싱되는데, i는 행 인덱스, j는 열 인덱스를 줘요. 관례대로 인덱스는 0에서 시작하고, 증가하는 인덱스는 왼쪽에서 오른쪽으로, 행의 경우 위에서 아래로 가요.

출처: 문서

본문

시놉시스 (Synopsis)

signature ARRAY2 (* OPTIONAL *)
structure Array2 :> ARRAY2 (* OPTIONAL *)

인터페이스 (Interface)

eqtype 'a array
type 'a region = {
base : 'a array,
row : int,
col : int,
nrows : int option,
ncols : int option
}
datatype traversal = RowMajor | ColMajor
val array : int * int * 'a -> 'a array
val fromList : 'a list list -> 'a array
val tabulate : traversal
-> int * int * (int * int -> 'a)
-> 'a array
val sub : 'a array * int * int -> 'a
val update : 'a array * int * int * 'a -> unit
val dimensions : 'a array -> int * int
val nCols : 'a array -> int
val nRows : 'a array -> int
val row : 'a array * int -> 'a Vector.vector
val column : 'a array * int -> 'a Vector.vector
val copy : {
src : 'a region,
dst : 'a array,
dst_row : int,
dst_col : int
} -> unit
val appi : traversal
-> (int * int * 'a -> unit)
-> 'a region -> unit
val app : traversal -> ('a -> unit) -> 'a array -> unit
val foldi : traversal
-> (int * int * 'a * 'b -> 'b)
-> 'b -> 'a region -> 'b
val fold : traversal
-> ('a * 'b -> 'b) -> 'b -> 'a array -> 'b
val modifyi : traversal
-> (int * int * 'a -> 'a)
-> 'a region -> unit
val modify : traversal -> ('a -> 'a) -> 'a array -> unit

설명 (Description)

type 'a region = {
base : 'a array,
row : int,
col : int,
nrows : int option,
ncols : int option
}

이 타입은 2차원 배열의 직사각형 부분 영역(region)을 명시해요. ncolsSOME(w)(0 <= w)이면 영역은 열 인덱스가 col부터 col + (w - 1)까지인 열의 요소만 포함해요. ncols가 NONE이면 영역은 col 열에 있거나 그 오른쪽에 있는 요소만 포함해요. 행과 nrows 필드에도 비슷한 해석이 적용돼요. 따라서 영역은 i가 행의 지정 범위 안에 있고 j가 열의 지정 범위 안에 있는 모든 (i,j) 위치 요소에 해당해요. 영역 reg는 그 기본 배열(base array)의 합법적인 부분 배열을 나타내면 유효하다고 해요.

datatype traversal = RowMajor | ColMajor

이 타입은 영역을 순회하는 방식을 명시해요. RowMajor는 주어진 영역에서 행을 왼쪽에서 오른쪽(작은 열 인덱스부터 큰 열 인덱스)으로, 영역의 첫 행부터 시작해 둘째, 셋째 식으로 마지막 행까지 순회한다는 뜻이에요. ColMajor는 행과 열의 역할을 뒤집어, 첫 열부터 시작해 아래로 열들을 순회해요.

array (r, c, init)

r개의 행과 c개의 열을 가진 새 배열을 만들고 각 요소를 init으로 초기화해요. r < 0, c < 0이거나 결과 배열이 너무 크면 Size 예외가 발생해요.

fromList l

리스트의 리스트(요소들)에서 새 배열을 만들어요. 요소들은 행 우선(row major) 형태로 제시돼야 해요. 즉 hd l이 첫 행, hd (tl l)이 둘째 행을 줘요. 결과 배열이 너무 크거나 l의 리스트 길이가 모두 같지 않으면 Size 예외가 발생해요.

tabulate trv (r, c, f)

r개의 행과 c개의 열을 가진 새 배열을 만들고, (i,j)번째 요소를 f (i,j)로 초기화해요. 요소는 trv가 지정한 순회 순서로 초기화돼요. r < 0, c < 0이거나 결과 배열이 너무 크면 Size 예외가 발생해요.

sub (arr, i, j)

배열 arr의 (i,j)번째 요소를 돌려줘요. i < 0, j < 0, nRows arr <= i, nCols arr <= j 중 하나면 Subscript 예외가 발생해요.

update (arr, i, j, a)

배열 arr의 (i,j)번째 요소를 a로 설정해요. i < 0, j < 0, nRows arr <= i, nCols arr <= j 중 하나면 Subscript 예외가 발생해요.

val dimensions : 'a array -> int * int
val nCols : 'a array -> int
val nRows : 'a array -> int

이 함수들은 배열의 크기 정보를 돌려줘요. nCols는 열 개수, nRows는 행 개수를 돌려주고, dimensions는 행 개수와 열 개수의 쌍을 돌려줘요. nRowsnCols는 각각 #1 o dimensions#2 o dimensions와 동등해요.

row (arr, i)

arr의 i번째 행을 돌려줘요. nRows arr <= i이거나 i < 0이면 Subscript를 발생시켜요.

column (arr, j)

arr의 j번째 열을 돌려줘요. j < 0이거나 nCols arr <= j이면 Subscript를 발생시켜요.

copy {src, dst, dst_row, dst_col}

영역 src를 배열 dst로 복사해요. (#row src, #col src) 위치의 요소를 목적지 배열의 (dst_row, dst_col) 위치로 복사해요. 소스 영역이 유효하지 않으면 Subscript 예외가 발생해요. 마찬가지로, 파생된 목적지 영역(소스 영역 src(dst_row,dst_col)로 이동한 것)이 dst에서 유효하지 않아도 Subscript 예외가 발생해요. 구현 참고: copy#base srcdst 배열이 같고 소스·목적지 영역이 겹치는 경우를 올바르게 처리해야 해요.

appi tr f reg

이 함수들은 tr이 지정한 순서로 배열의 요소에 함수 f를 적용해요. 더 일반적인 appi는 영역 reg의 요소에 f를 적용하면서 요소와 그 기본 배열에서의 좌표를 함께 제공해요. reg가 유효하지 않으면 Subscript 예외가 발생해요. app는 배열 전체에 f를 적용하고 요소의 좌표는 제공하지 않아요. 따라서 식 app tr f arr는 다음 식과 동등해요.

app tr f arr

이 함수들은 tr 순서로 배열 arr의 요소 위로 함수 f를 접으면서 init을 초기 값으로 사용해요. 더 일반적인 foldi는 영역 reg의 요소에 f를 적용하며 요소와 좌표를 함께 제공해요. reg가 유효하지 않으면 Subscript 예외가 발생해요. fold는 배열 전체에 f를 적용하고 좌표는 제공하지 않아요. 따라서 식 fold tr f init arr는 다음 식과 동등해요.

let
val range = {base=arr,row=0,col=0,nrows=NONE,ncols=NONE}
in
appi tr (f o #3) range
end

foldi tr f init reg

이 함수들은 tr이 지정한 순서로 배열 요소에 함수 f를 적용하고 각 요소를 f의 결과로 교체해요. 더 일반적인 modifyi는 영역 reg의 요소에 f를 적용하며 요소와 좌표를 제공해요. reg가 유효하지 않으면 Subscript 예외가 발생해요. modify는 배열 전체에 f를 적용하고 좌표는 제공하지 않아요. 따라서 식 modify tr f arr는 다음 식과 동등해요.

fold tr f init arr

이 함수들은 배열 arr의 요소 위로 함수 f를 접으면서 tr 순서로 요소를 순회하고 init 값을 초기 값으로 사용해요. 더 일반적인 foldi 함수는 영역 reg의 요소에 f를 적용하며 요소와 그 기본 배열에서의 좌표를 모두 f에 전달해요. reg가 유효하지 않으면 Subscript 예외가 발생해요. fold 함수는 전체 배열에 f를 적용하고 요소의 좌표는 f에 전달하지 않아요. 따라서 식 fold tr f init arr는 다음과 동등해요:

foldi tr (fn (_,_,a,b) => f (a,b)) init
{base=arr, row=0, col=0, nrows=NONE, ncols=NONE}

modifyi tr f reg

modify tr f arr

이 함수들은 tr이 지정한 순서로 배열의 요소에 함수 f를 적용하고 각 요소를 f의 결과로 교체해요. 더 일반적인 modifyi 함수는 영역 reg의 요소에 f를 적용하며 요소와 그 기본 배열에서의 좌표를 모두 f에 전달해요. reg가 유효하지 않으면 Subscript 예외가 발생해요. modify 함수는 전체 배열에 f를 적용하고 요소의 좌표는 f에 전달하지 않아요. 따라서 식 modify tr f arr는 다음과 동등해요:

let
val range = {base=arr,row=0,col=0,nrows=NONE,ncols=NONE}
in
modifyi tr (f o #3)
end

더 알아보기 (Learn more)