Hash 리터럴
Hash 리터럴
Hash는 키-값 쌍으로 이루어진 제네릭 컬렉션이에요. 타입 K의 키를 타입 V의 값에 매핑하죠.
해시는 보통 해시 리터럴로 만드는데, 중괄호({ }) 안에 키와 값 사이를 =>로 구분하고 쉼표(,)로 쌍을 나열해요.
{"one" => 1, "two" => 2}
출처: Crystal 공식 문서
본문
제네릭 타입 인자
키 K와 값 V의 제네릭 타입 인자는 각각 리터럴 안의 키 타입과 값 타입에서 추론돼요. 모두 같은 타입이면 K/V도 그 타입이 되고, 그렇지 않으면 각각 모든 키 타입 또는 값 타입의 유니온이 돼요.
{1 => 2, 3 => 4} # Hash(Int32, Int32)
{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32)
명시적 타입을 지정하고 싶으면 닫는 중괄호 바로 뒤에 (공백으로 구분해) of를 쓰고, 키 타입(K)과 => 구분자, 값 타입(V)을 적으면 돼요. 이렇게 하면 추론된 타입을 덮어쓰는데, 예를 들어 처음에는 일부 타입만 담고 나중에 다른 타입도 받을 수 있게 만드는 데 쓸 수 있어요.
빈 해시 리터럴은 항상 타입 지정이 필요해요.
{} of Int32 => Int32 # => Hash(Int32, Int32).new
해시류 타입 리터럴
Crystal은 해시와 해시류 타입을 위한 추가 리터럴을 지원해요. 타입의 이름 뒤에 중괄호({})로 감싼, 쉼표로 구분된 키-값 쌍 목록을 붙이는 형태예요.
Hash{"one" => 1, "two" => 2}
이 리터럴은 인자 없는 생성자(argless constructor)가 있고 []=에 응답하는 타입이라면 어떤 타입에도 사용할 수 있어요.
HTTP::Headers{"foo" => "bar"}
HTTP::Headers처럼 제네릭이 아닌 타입의 경우 이 리터럴은 다음 코드와 같아요.
headers = HTTP::Headers.new
headers["foo"] = "bar"
제네릭 타입의 경우, 제네릭 타입은 해시 리터럴과 마찬가지로 키·값의 타입에서 추론돼요.
MyHash{"foo" => 1, "bar" => "baz"}
MyHash가 제네릭이라면, 위 코드는 이 코드와 같아요.
my_hash = MyHash(typeof("foo", "bar"), typeof(1, "baz")).new
my_hash["foo"] = 1
my_hash["bar"] = "baz"
타입 인자는 타입 이름의 일부로 명시적으로 지정할 수도 있어요.
MyHash(String, String | Int32){"foo" => "bar"}
더 알아보기
- Symbol 리터럴: 해시 키로 자주 쓰이는 또 다른 리터럴
- Hash API: 해시가 제공하는 메서드들