[perl] Perl 5의 기능 프로토 타입이 왜 나쁜가요?

다른 Stack Overflow 질문에서 Leon Timmermans는 다음과 같이 주장했습니다.

프로토 타입을 사용하지 말라고 조언합니다. 그들은 그들의 용도가 있지만 대부분의 경우는 아니며 확실히 이것에는 없습니다.

왜 이것이 사실일까요? 나는 거의 항상 내 Perl 기능을위한 프로토 타입을 제공하고 있으며, 다른 사람이 그것들을 사용하는 것에 대해 나쁜 말을하는 것을 본 적이 없습니다.



답변

프로토 타입은 올바르게 사용하면 나쁘지 않습니다. 어려움은 Perl의 프로토 타입이 사람들이 종종 기대하는 방식으로 작동하지 않는다는 것입니다. 다른 프로그래밍 언어에 대한 배경 지식이있는 사람들은 프로토 타입이 함수 호출이 올바른지 확인하는 메커니즘을 제공하기를 기대하는 경향이 있습니다. 즉, 올바른 수와 유형의 인수가 있는지 확인합니다. Perl의 프로토 타입은이 작업에 적합하지 않습니다. 그것은의 오용 나쁜. Perl의 프로토 타입은 매우 다른 목적을 가지고 있습니다.

프로토 타입을 사용하면 내장 함수처럼 작동하는 함수를 정의 할 수 있습니다.

  • 괄호는 선택 사항입니다.
  • 컨텍스트는 인수에 부과됩니다.

예를 들어 다음과 같은 함수를 정의 할 수 있습니다.

sub mypush(\@@) { ... }

그리고 그것을

mypush @array, 1, 2, 3;

\배열에 대한 참조를 가져 오기 위해 를 쓸 필요가 없습니다 .

간단히 말해서 프로토 타입을 사용하면 고유 한 구문 설탕을 만들 수 있습니다. 예를 들어 Moose 프레임 워크는이를 사용하여보다 일반적인 OO 구문을 에뮬레이트합니다.

이것은 매우 유용하지만 프로토 타입은 매우 제한적입니다.

  • 컴파일 타임에 표시되어야합니다.
  • 우회 할 수 있습니다.
  • 컨텍스트를 인수로 전파하면 예기치 않은 동작이 발생할 수 있습니다.
  • 엄격하게 규정 된 형식 이외의 다른 것을 사용하여 함수를 호출하기 어렵게 만들 수 있습니다.

모든 세부 사항은 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에만 적용됩니다.


답변

위의 두 포스터에 동의합니다. 일반적으로 사용 $은 피해야합니다. 블록 인수 (사용시 원형에만 유용하다 &), globs와 ( *) 또는 기준 프로토 타입 ( \@, \$, \%, \*)


답변

Perl 서브 루틴 프로토 타입을보고있는 일부 사람들은 그것이 의미하지 않는 것을 의미한다고 생각합니다.

sub some_sub ($$) { ... }

Perl에게 이는 파서가 두 개의 인수를 예상한다는 것을 의미합니다. 그것은 Perl이 내장 된 것처럼 동작하는 서브 루틴을 생성 할 수 있도록하는 방법입니다.이 모든 것은 후속 코드에서 무엇을 기대할 수 있는지 알고 있습니다. perlsub 에서 프로토 타입에 대해 읽을 수 있습니다.

문서를 읽지 않고 사람들은 프로토 타입이 런타임 인수 검사 또는 다른 언어에서 본 것과 유사한 것을 참조한다고 추측합니다. 사람들이 Perl에 대해 추측하는 대부분의 것과 마찬가지로, 그들은 잘못된 것으로 밝혀졌습니다.

그러나 Perl v5.20부터 Perl에는 사용자가 기대하는 것과 유사한 것을 제공하는 실험적인 기능이 있습니다. Perl의 서브 루틴 서명 은 런타임 인수 계수, 변수 할당 및 기본 설정을 수행합니다.

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";
    }

이것은 프로토 타입을 고려하고 있다면 아마도 원하는 기능입니다.


답변