raku-type-sethash

class SetHash does Setty { }

SetHash수정 가능한(mutable) 집합, 즉 특별한 순서 없이 서로 다른 원소를 모아 둔 컬렉션이에요. (수정 불가능한 집합은 Set을 보면 돼요.)

집합 원소로는 아무 타입의 객체/값이든 허용돼요. 그리고 Set 안의 모든 원소는 서로 다르다는 게 보장돼요. 다시 말해 어떤 두 원소도 ===로 같게 비교되지 않는다는 뜻이죠.

my $fruits = <peach apple orange apple apple>.SetHash;

say $fruits.elems;      # OUTPUT: «3␤»
say $fruits.keys.sort;  # OUTPUT: «apple orange peach␤»

Set과 마찬가지로 SetHash{ } 후치 연산자를 써서 객체 해시처럼 다룰 수 있어요. 집합의 원소인 키에는 True를, 아닌 키에는 False를 돌려주죠.

my $fruits = <peach apple orange apple apple>.SetHash;

say $fruits<apple>;     # OUTPUT: «True␤»
say $fruits<kiwi>;      # OUTPUT: «False␤»

Set과 달리 SetHash는 수정할 수 있어요. set 메서드로 항목(또는 항목 목록)을 집합에 추가하고, unset 메서드로 제거할 수 있어요.

my $fruits = <peach>.SetHash;
$fruits.set('apple');
say $fruits;            # OUTPUT: «SetHash(apple peach)␤»

$fruits.unset('peach');
say $fruits;            # OUTPUT: «SetHash(apple)␤»

$fruits.set(<kiwi banana apple>);
say $fruits;            # OUTPUT: «SetHash(apple banana kiwi)␤»

$fruits.unset(<apple banana kiwi>);
say $fruits;            # OUTPUT: «SetHash()␤»

주의할 점이 하나 있어요. 집합에 항목을 추가하는 set 메서드와, 수정 가능한 SetHash를 수정 불가능한 Set으로 변환하는 Set 메서드를 헷갈리지 말아야 해요.

set·unset 메서드 대신, 각각 True/False로 불리언 변환되는 값을 할당해서 집합 원소를 추가하거나 제거할 수도 있어요.

my $fruits = <peach apple orange>.SetHash;

$fruits<apple kiwi> = False, True;
say $fruits.keys.sort;  # OUTPUT: «kiwi orange peach␤»

할당을 이용해 SetHash 원소를 추가·제거하는 편리한 짧은 관용구도 있어요.

my SetHash $fruits .= new;
say $fruits<cherry>;      # OUTPUT: «False␤»
$fruits<cherry>++;
say $fruits<cherry>;      # OUTPUT: «True␤»
$fruits<apple banana kiwi>»++; # Add multiple elements

$fruits<cherry>--;
say $fruits<cherry>;      # OUTPUT: «False␤»
$fruits<banana kiwi>»--; # Remove multiple elements

Creating SetHash objects

SetHash 객체는 SetHash.new로 만들 수 있어요. 타입과 무관하게, 위치 인자는 전부 집합의 원소가 돼요.

my $n = SetHash.new: "zero" => 0, "one" => 1, "two" => 2;
say $n.keys.raku;        # OUTPUT: «(:two(2), :zero(0), :one(1)).Seq␤»
say $n.keys.map(&WHAT);  # OUTPUT: «((Pair) (Pair) (Pair))␤»

다른 방법으로는 기존 객체에 .SetHash 강제 변환자(또는 함수형인 SetHash())를 호출해서 SetHash로 바꿀 수 있어요. 그 의미는 객체의 타입과 내용에 따라 달라지는데요. 일반적으로 객체를 리스트 맥락에서 평가해 나온 항목들을 원소로 하는 집합을 만들죠. 다만 해시류 객체나 Pair 항목의 경우엔 키만 집합 원소가 되고, False로 불리언 변환되는 값에 매핑된 키는 건너뛰어요.

my $n = ("zero" => 0, "one" => 1, "two" => 2).SetHash;
say $n.keys.raku;        # OUTPUT: «("one", "two").Seq␤»
say $n.keys.map(&WHAT);  # OUTPUT: «((Str) (Str))␤»

{ }를 써서 단일 키를 초기화하는 것도 가능해요.

my $sh = SetHash.new;
$sh{ 'key1' } = True;
$sh{ 'key2' } = 'Hello World!';
$sh{ 'key3' } = 0;  # does not store the key since 0.Bool is False
say $sh;            # OUTPUT: «SetHash(key1 key2)␤»
say $sh.keys.raku;  # OUTPUT: «("key1", "key2").Seq␤»

여러 키를 한 번에 초기화하려면 리스트 할당을 쓰면 돼요.

my $sh = SetHash.new;
$sh{ 'a', 'b', 'c' } = True, False, True;
say $sh.keys.raku;  # OUTPUT: «("a", "c").Seq␤»

is 트레잇을 쓰면 해시로 위장한 SetHash도 만들 수 있어요.

my %sh is SetHash = <a b c>;
say %sh<a>;  # OUTPUT: «True␤»
say %sh<d>;  # OUTPUT: «False␤»

6.d(2019.03 이후)부터는 SetHash에 허용할 값의 타입을 지정할 수도 있어요. .new을 부를 때 하거나,

# only allow Pairs
my $n = SetHash[Pair].new: "zero" => 0, "one" => 1, "two" => 2;

위장 문법으로 할 수 있어요.

# only allow strings
my %sh is SetHash[Str] = <a b c>;
say %sh<a>;  # OUTPUT: «True␤»
say %sh<d>;  # OUTPUT: «False␤»

# only allow whole numbers
my %sh is SetHash[Int] = <a b c>;
# Type check failed in binding; expected Int but got Str ("a")

Operators

SetHash에도 적용되는 "집합 연산자"의 전체 목록은 집합 의미론 연산자 문서에서 볼 수 있어요.

예시를 보여드릴게요.

my ($a, $b) = SetHash.new(1, 2, 3), SetHash.new(2, 4);

say $a (<) $b;  # OUTPUT: «False␤»
say $a (&) $b;  # OUTPUT: «SetHash(2)␤»
say $a (^) $b;  # OUTPUT: «SetHash(1 3 4)␤»
say $a (|) $b;  # OUTPUT: «SetHash(1 2 3 4)␤»

# Unicode versions:
say $a ⊂ $b;  # OUTPUT: «False␤»
say $a ∩ $b;  # OUTPUT: «SetHash(2)␤»
say $a ⊖ $b;  # OUTPUT: «SetHash(1 3 4)␤»
say $a ∪ $b;  # OUTPUT: «SetHash(1 2 3 4)␤»

Methods

method set

method set(SetHash:D: \to-set --> Nil)

단일 키가 주어지면 set은 그 키를 SetHash에 추가해요. List, Array, Seq, 또는 Iterator 역할을 하는 다른 어떤 타입이 주어지면, 그 이터레이터의 각 원소를 키로 추가해요.

참고: 2020.02 릴리스부터.

method unset

method unset(SetHash:D: \to-unset --> Nil)

단일 키가 주어지면 unset은 그 키를 SetHash에서 제거해요. List, Array, Seq, 또는 Iterator 역할을 하는 다른 어떤 타입이 주어지면, 그 이터레이터의 각 원소를 (키로 존재했다면) SetHash에서 제거해요.

참고: 2020.02 릴리스부터.

See Also

집합, 가방, 그리고 혼합(Sets, Bags, and Mixes) 문서도 함께 보면 돼요.