Allomorph — 문자열이면서 숫자인 이중 값 타입

Allomorph — 문자열이면서 숫자인 이중 값 타입

<42>처럼 따옴표 없는 단어 리스트에서 숫자처럼 보이는 토큰을 만들면, 그 값은 문자열이면서 동시에 숫자로도 쓰일 수 있어요. 이런 값을 담당하는 공통 부모 클래스가 바로 Allomorph예요. ComplexStr, IntStr, NumStr, RatStr처럼 Raku의 이중 값(dual value) 타입들이 이 클래스를 상속해요.

class Allomorph is Str { }

본문

이중 값 타입은 흔히 '얼로모프(allomorph)'라고 불러요. 값을 문자열과 숫자 타입 둘 다로 표현할 수 있게 해줘요. 보통은 코드를 직접 만들기보다, 문맥이 '끈적한(stringy)' 상황에서 값이 숫자로 판별될 수 있을 때 자동으로 만들어져요. 예를 들어 따옴표 관련 구조에서 그렇죠.

my $c = <42+0i>;  say $c.^name; # OUTPUT: «ComplexStr␤»
my $i = <42>;     say $i.^name; # OUTPUT: «IntStr␤»
my $n = <42.1e0>; say $n.^name; # OUTPUT: «NumStr␤»
my $r = <42.1>;   say $r.^name; # OUTPUT: «RatStr␤»

Allomorph의 하위 클래스는 Numeric 계열과 Str 계열을 모두 상속하므로, 둘 중 어느 쪽이 기대되는 자리에도 들어갈 수 있어요. 다만 객체 정체성(object identity)은 공유하지 않아요. 그래서 (원소 검사) 연산자는 객체 정체성까지 따지기 때문에, 같은 값처럼 보여도 False가 나올 수 있어요.

my ($complex-str, $int-str, $num-str, $rat-str)
           = < 42+0i 42 42e10 42.1 >;

my (Complex $complex, Int $int, Num $num, Rat $rat)
           =  $complex-str, $int-str, $num-str, $rat-str;  # OK!

my Str @strings
           =  $complex-str, $int-str, $num-str, $rat-str;  # OK!

# ∈ operator cares about object identity
say 42+0i ∈ < 42+0i 42 42e10 42.1 >;  # OUTPUT: «False␤»
say 42    ∈ < 42+0i 42 42e10 42.1 >;  # OUTPUT: «False␤»
say 42e10 ∈ < 42+0i 42 42e10 42.1 >;  # OUTPUT: «False␤»
say 42.1  ∈ < 42+0i 42 42e10 42.1 >;  # OUTPUT: «False␤»

얼로모프를 실제로 어떻게 다루는지는 Numerics 문서 — Allomorphs에서 더 자세히 볼 수 있어요.

메서드

Allomorph에는 문자열 동작과 숫자 동작을 각각 위임하는 메서드들이 많아요. 대표적으로 볼게요.

method ACCEPTS

multi method ACCEPTS(Allomorph:D: Any:D \a)

a 인자가 Numeric(다른 얼로모프 포함)이라면 invocant의 Numeric 값이 aACCEPTS하는지 확인해요. a 인자가 Str이라면 Str 값이 ACCEPTS하는지 확인하고, 그 외 타입이라면 NumericStr 양쪽 값이 모두 ACCEPTS해야 True가 돼요.

say "5.0" ~~ <5>; # OUTPUT: «False␤»
say 5.0   ~~ <5>; # OUTPUT: «True␤»
say <5.0> ~~ <5>; # OUTPUT: «True␤»

method Bool

multi method Bool(::?CLASS:D:)

invocant가 숫자로 0이면 False, 그 외엔 True를 돌려줘요. Str 값은 고려하지 않아요. RatStr 서브클래스는 Rational.Bool도 함께 보면 좋아요.

문자열 위임 메서드들

chomp, chop, comb, fc, flip, lc, samecase, samemark, split 등은 invocant의 Str 값에 대해 해당 Str 메서드를 호출해요. 예를 들면:

method chomp(Allomorph:D:)

이 메서드는 invocant의 Str 값에 대해 Str.chomp를 호출해요.

method pred

method pred(Allomorph:D:)

invocant의 숫자 값에 대해 Numeric.pred를 호출해요.

method raku

multi method raku(Allomorph:D:)

EVAL로 값을 재구성할 수 있는 객체 표현을 돌려줘요.

출처: Raku 공식 문서 — Allomorph