메서드 찾을 수 없음 Fallback
I’m happy to translate the article for you, but I’ll need the actual text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source link at the top and preserve all formatting, code blocks, URLs, and technical terms as requested.
개요
This is part eleven in the Cases of UPPER series, describing the Raku syntax elements that are completely in UPPERCASE.
In this part we discuss the interface method that can be provided in a class to handle calls to methods that do not actually exist in the class (or its parents).
Method Lookup in Raku
Raku 프로그래밍 언어에서 메서드 디스패치는 특히 멀티‑디스패치가 포함될 때 상당히 복잡합니다. 첫 번째 단계는 주어진 이름을 가진 (멀티) 메서드가 존재하는지 확인하는 것입니다. 내부적으로 이는 클래스의 메타‑오브젝트에 있는 find_method 메서드에 의해 처리되며(보통 .^method 구문으로 호출됩니다).
# an empty class
class A { }
dd A.^find_method("foobar"); # Mu
dd A.^find_method("gist"); # proto method gist (Mu $:: |) {*}
빈 클래스 A( Any를 상속함)는 foobar 메서드를 제공하지 않으며( Mu 타입 객체로 표시), gist 메서드는 제공합니다(Any에서 상속됨).
디스패치 로직이 주어진 이름으로 메서드를 찾지 못하면 X::Method::NotFound 오류를 발생시킵니다. CATCH 페이저로 이러한 경우를 처리할 수 있지만, 더 간단하고 관용적인 방법이 있습니다: FALLBACK 메서드.
FALLBACK 메서드
클래스가 FALLBACK 메서드를 제공할 때(직접 정의하거나, 상속받거나, 역할을 통해 제공할 때) 해당 메서드는 찾을 수 없는 메서드가 호출될 때 실행됩니다. 찾지 못한 메서드의 이름이 첫 번째 인수로 전달되고, 나머지 인수들은 그대로 전달됩니다.
간단한 예제
class B {
method FALLBACK($name) { $name }
}
say B.foo; # foo
say B.bar(42); # Too many positionals passed; expected 2 arguments but got 3
다중 메서드 FALLBACK
class C {
multi method FALLBACK($name) {
$name
}
multi method FALLBACK($name, $value) {
"$value.raku() passed to '$name'"
}
}
say C.foo; # foo
say C.bar(42); # 42 passed to 'bar'
인수 무시하기
인수에 신경 쓰지 않고 단순히 Nil을 반환하고 싶다면, 시그니처에 이름 없는 캡처(|)를 사용할 수 있습니다:
class D {
method FALLBACK(|) { Nil }
}
say D.foo; # Nil
say D.bar(42); # Nil
언더스코어/하이픈 실수를 교정하기 위한 FALLBACK 사용
Raku는 식별자 이름에 하이픈(케밥 케이스)을 허용합니다. 다른 언어에서 온 프로그래머들은 종종 언더스코어(스네이크 케이스)를 사용해 실수하게 되며, 이 경우 런타임 오류가 발생합니다. FALLBACK 메서드를 이용하면 이러한 오류를 가로채어 자동으로 교정할 수 있습니다.
class E {
method foo-bar() { "foobar" }
method FALLBACK($name, |c) {
my $corrected = $name.trans("_" => "-");
if self.^find_method($corrected, :no_fallback) -> &code {
code(self, |c)
}
else {
X::Method::NotFound.new(
:invocant(self), :method($name), :typename(self.^name)
).throw;
}
}
}
foo-bar는 유효한 메서드입니다.FALLBACK메서드는 존재하지 않는 메서드 이름($name)과 추가 인수(|c)를 받습니다.- 언더스코어를 하이픈으로 바꾸고,
.^find_method에:no_fallback옵션을 줘서(재귀적 fallback 방지) 교정된 이름을 찾아본 뒤, 메서드가 존재하면 원래 인수를 그대로 사용해 호출합니다. - 교정된 메서드가 없을 경우
Method::NotFound오류를 다시 발생시킵니다.
say E.foo-bar; # foobar
say E.foo_bar; # foobar
재사용 가능한 역할: Method::Misspelt
위의 로직을 역할(role)로 패키징하여 모듈로 배포할 수 있습니다. 이를 통해 Method::Misspelt 역할이 만들어졌으며, 동일한 기능을 제공함과 동시에 역할을 사용하는 여러 클래스에 대한 추가 기능 및 최적화를 제공합니다. 자세한 내용은 모듈의 내부 문서를 참조하십시오.
결론
이번 에피소드에서는 FALLBACK 메서드를 소개하고, 이를 커스터마이즈하는 여러 방법을 시연했으며, 언더스코어를 하이픈으로 잘못 입력한 경우를 교정하는 실용적인 사용 사례를 보여주었습니다. 이 블로그 포스트의 결과물로 보너스 모듈 Method::Misspelt도 만들어졌습니다.
다음 에피소드를 기대해 주세요!