배열

배열 (Array)

Array는 특정 타입 T의 원소들을 담는, 순서가 있고 정수 인덱스로 접근하는 제네릭 컬렉션이에요. 대괄호([])로 만드는 배열 리터럴과 of로 명시 타입을 지정하는 방법, 퍼센트 리터럴, 배열형 타입 리터럴, 스플랫 확장까지 살펴볼게요.

출처: Crystal 공식 문서 — Literals: Array

본문

Array는 특정 타입 T의 원소들을 담는, 순서가 있고 정수 인덱스로 접근하는 제네릭 컬렉션이에요.

배열은 보통 대괄호([])로 나타내는 배열 리터럴로 만들고, 각 원소는 쉼표(,)로 구분해요.

[1, 2, 3]

제네릭 타입 인자 (Generic Type Argument)

배열의 제네릭 타입 인자 T는 리터럴 안의 원소 타입들로부터 추론돼요. 배열의 모든 원소가 같은 타입이면 T는 그 타입이 되고, 그렇지 않으면 모든 원소 타입의 유니온이 돼요.

[1, 2, 3]         # => Array(Int32)
[1, "hello", 'x'] # => Array(Int32 | String | Char)

닫는 괄호 바로 뒤에 of와 타입을 써서 명시적 타입을 지정할 수 있어요. 이렇게 하면 추론된 타입을 덮어써요. 예를 들어 처음에는 몇몇 타입만 담고 나중에 다른 타입도 받아들일 수 있는 배열을 만들 때 쓸 수 있어요.

array_of_numbers = [1, 2, 3] of Float64 | Int32 # => Array(Float64 | Int32)
array_of_numbers << 0.5                         # => [1, 2, 3, 0.5]

array_of_int_or_string = [1, 2, 3] of Int32 | String # => Array(Int32 | String)
array_of_int_or_string << "foo"                      # => [1, 2, 3, "foo"]

빈 배열 리터럴은 항상 타입 지정이 필요해요:

[] of Int32 # => Array(Int32).new

퍼센트 배열 리터럴 (Percent Array Literals)

문자열 배열심볼 배열은 퍼센트 배열 리터럴로 만들 수 있어요:

%w(one two three) # => ["one", "two", "three"]
%W(one two three) # => ["one", "two", "three"]
%i(one two three) # => [:one, :two, :three]

배열형 타입 리터럴 (Array-like Type Literal)

Crystal은 배열과 배열형 타입을 위한 추가 리터럴을 지원해요. 타입 이름 뒤에 중괄호({})로 감싼 원소 리스트를 붙이고, 각 원소는 쉼표(,)로 구분해요.

Array{1, 2, 3}

이 리터럴은 인자 없는 생성자(argless constructor)가 있고 <<에 응답하는 타입이라면 어떤 타입이든 쓸 수 있어요.

IO::Memory{1, 2, 3}
Set{1, 2, 3}

IO::Memory 같은 비제네릭 타입의 경우 이 리터럴은 다음과 같아요:

array_like = IO::Memory.new
array_like << 1
array_like << 2
array_like << 3

Set 같은 제네릭 타입의 경우 제네릭 타입 T는 배열 리터럴과 같은 방식으로 원소 타입들로부터 추론돼요. 위 코드는 다음과 같아요:

array_like = Set(typeof(1, 2, 3)).new
array_like << 1
array_like << 2
array_like << 3

타입 인자는 타입 이름의 일부로 명시적으로 지정할 수 있어요:

Set(Int32){1, 2, 3}

스플랫 확장 (Splat Expansion)

스플랫 연산자는 배열 및 배열형 리터럴 안에서 여러 값을 한 번에 삽입하는 데 사용할 수 있어요.

[1, *coll, 2, 3]
Set{1, *coll, 2, 3}

유일한 요구사항은 coll의 타입이 Enumerable을 포함해야 한다는 거예요. 위 코드는 다음과 같아요:

array = Array(typeof(...)).new
array << 1
array.concat(coll)
array << 2
array << 3

array_like = Set(typeof(...)).new
array_like << 1
coll.each do |elem|
  array_like << elem
end
array_like << 2
array_like << 3

이런 경우 제네릭 타입 인자는 coll의 원소들로 추가로 추론돼요.

더 알아보기