Perl 5의 기능 프로토 타입이 왜 나쁜가요?
문제
~ 안에 또 다른 스택 오버플로 질문 레온 티머 맨 주장 :
프로토 타입을 사용하지 말라고 조언합니다. 그들은 그들의 용도를 가지고 있지만 대부분의 경우에는 그렇지 않으며 분명히 이것에는 그렇지 않습니다.
이것이 왜 (또는 그렇지 않으면) 왜 될 수 있습니까? 나는 거의 항상 내 Perl 기능에 대한 프로토 타입을 제공하며, 이전에 다른 사람이 그것들을 사용하는 것에 대해 나쁜 말을 본 적이 없습니다.
해결책
제대로 사용하면 프로토 타입이 나쁘지 않습니다. 어려움은 Perl의 프로토 타입이 사람들이 종종 기대하는 방식으로 작동하지 않는다는 것입니다. 다른 프로그래밍 언어에 대한 배경 지식을 가진 사람들은 프로토 타입이 기능 호출을 확인하기위한 메커니즘을 제공 할 것으로 기대하는 경향이 있습니다. 즉, 올바른 숫자와 인수 유형을 가지고 있습니다. Perl의 프로토 타입은이 작업에 적합하지 않습니다. 그건 오용 그 나쁜. Perl의 프로토 타입은 특이적이고 매우 다른 목적을 가지고 있습니다.
프로토 타입을 사용하면 내장 기능처럼 작동하는 기능을 정의 할 수 있습니다.
- 괄호는 선택 사항입니다.
- 인수에 문맥이 부과됩니다.
예를 들어 다음과 같은 기능을 정의 할 수 있습니다.
sub mypush(\@@) { ... }
그리고 그것을라고 부릅니다
mypush @array, 1, 2, 3;
글을 쓸 필요없이 \
배열을 참조합니다.
간단히 말해서 프로토 타입을 사용하면 자신의 구문 설탕을 만들 수 있습니다. 예를 들어 무스 프레임 워크는 이들을 사용하여보다 일반적인 OO 구문을 모방합니다.
이것은 매우 유용하지만 프로토 타입은 매우 제한적입니다.
- 컴파일 타임에 눈에 띄어 야합니다.
- 그들은 우회 할 수 있습니다.
- 인수에 대한 컨텍스트를 전파하면 예상치 못한 행동이 발생할 수 있습니다.
- 엄격하게 처방 된 양식 이외의 다른 것을 사용하여 기능을 호출하기가 어려울 수 있습니다.
보다 프로토 타입 모든 gory 세부 사항에 대한 Perlsub에서.
다른 팁
문제는 Perl의 기능 프로토 타입이 사람들이 생각하는 것을 수행하지 않는다는 것입니다. 그들의 목적은 Perl의 내장 기능처럼 구문 분석 할 함수를 작성할 수 있도록하는 것입니다.
우선, 메소드 호출은 프로토 타입을 완전히 무시합니다. OO 프로그래밍을 수행하는 경우 방법의 프로토 타입은 중요하지 않습니다. (그래서 그들은 프로토 타입이 없어야합니다.)
둘째, 프로토 타입은 엄격하게 시행되지 않습니다. 서브 루틴을 함께 전화하면 &function(...)
, 프로토 타입은 무시됩니다. 따라서 그들은 실제로 어떤 유형의 안전도 제공하지 않습니다.
셋째, 그들은 으스스한 행동입니다. (특히 $
해당 매개 변수를 기본 목록 컨텍스트 대신 스칼라 컨텍스트에서 평가하게하는 프로토 타입.)
특히, 그들은 배열에서 매개 변수를 전달하기가 어렵습니다. 예를 들어:
my @array = qw(a b c);
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
sub foo ($;$$) { print "@_\n" }
foo(@array);
foo(@array[0..1]);
foo($array[0], $array[1], $array[2]);
인쇄물:
a b c
a b
a b c
3
b
a b c
3 가지 경고와 함께 main::foo() called too early to check prototype
(경고가 활성화 된 경우). 문제는 스칼라 컨텍스트에서 평가 된 배열 (또는 배열 슬라이스)이 배열의 길이를 반환한다는 것입니다.
내장 된 것처럼 작용하는 기능을 작성 해야하는 경우 프로토 타입을 사용하십시오. 그렇지 않으면 프로토 타입을 사용하지 마십시오.
참고 : PERL 6은 완전히 개선되고 매우 유용한 프로토 타입이 있습니다. 이 답변은 Perl 5에만 적용됩니다.
위의 포스터에 동의합니다. 일반적으로 사용합니다 $
피해야한다. 프로토 타입은 블록 인수를 사용할 때만 유용합니다 (&
), 글로스 (*
) 또는 참조 프로토 타입 (\@
, \$
, \%
, \*
)
일부 사람들은 Perl Subroutine 프로토 타입을 보면 그것이 그렇지 않은 것을 의미한다고 생각합니다.
sub some_sub ($$) { ... }
이는 파서가 두 가지 주장을 기대한다는 것을 의미합니다. 그것은 당신이 내장 코드에서 무엇을 기대 해야하는지 알고있는 내장과 같은 서브 루틴을 만들도록하는 Perl의 방법입니다. 프로토 타입에 대해 읽을 수 있습니다 Perlsub
문서를 읽지 않고 사람들은 프로토 타입이 실행 시간 인수 확인 또는 다른 언어에서 본 것과 유사한 것을 지칭한다고 추측합니다. 사람들이 Perl에 대해 추측하는 대부분의 것들과 마찬가지로, 그들은 틀린 것으로 판명되었습니다.
그러나 PERL v5.20부터 Perl 은이 글을 쓰는 실험적인 기능을 가지고 있으며, 이는 사용자가 기대하는 것과 비슷한 것을 제공합니다. Perl 's 서브 루틴 서명 시간 인수 계산, 가변 할당 및 기본 설정을 실행합니다.
use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);
animals( 'Buster', 'Nikki', 'Godzilla' );
sub animals ($cat, $dog, $lizard = 'Default reptile') {
say "The cat is $cat";
say "The dog is $dog";
say "The lizard is $lizard";
}
프로토 타입을 고려할 경우 원하는 기능입니다.