2017-11-17 2 views
1

필자는 함수를 호출하는 Perl 프로그램 (이 경우 ref)을 사용하고 결과를 확인합니다. 특히 변수가 해시 참조 인 지 테스트하고 있습니다. 이 경우 ref'HASH'을 반환합니다. 나는 그것을 테스트했고 효과가 있었다.함수에서 반환 한 값을 연결하여 인쇄 할 수없는 이유는 무엇입니까?

그런 다음 동일한 호출 결과를 표시하는 print을 추가하여 기록하기로 결정했으나 제대로 작동하지 않았습니다. 여기에 감소 된 버전입니다 :

ref $book_ref is a Program is over 

그리고에도 불구하고

은 어느 오류도 경고가 있었다 strictwarnings를 사용하여 :

use strict; 
use warnings; 

my $book_ref = {}; 
$book_ref->{'title'} = 'The Lord of the Rings'; 

if (ref $book_ref eq 'HASH') { 
    print "ref \$book_ref is a " . ref $book_ref . "\n"; 
} 

print "Program is over\n"; 

놀랍게도,이 출력되었다.
ref에 대한 호출은 똑같습니다 (복사하여 붙여 넣기입니다). 그러나 if 조건에서 올바르게 작동하지만, print은 아무 것도 표시하지 않고 줄 바꿈 문자가 명확하게 건너 뛰므로 실제로는 중단 된 것처럼 보입니다. 왜 행동이 바뀌 었습니까?

답변

7

그 이유는 괄호없이 함수 ref이 호출되어이 행이 잘못 구문 분석되기 때문입니다. refif 내부이라고

  • , 조건은 명확하게 ref는 인수가 무엇인지 완벽하게 잘 알고 있다는 것을 의미하는 괄호로 구분된다 $book_ref. 애매 모호하지 않습니다.

    1. 첫째는 $book_ref"\n" 연결할 것 : 결과를 인쇄 할 때
    2. 대신, 괄호의 부족은 펄이 의도하지 않은 방법으로 라인을 구문 분석하는 것을 의미합니다. '' : 스칼라 문맥에서, $book_ref 따라서 결과는 문자열 그런 다음, ref이 문자열 "HASH(0x1cbef70)\n"에 호출됩니다 "HASH(0x1cbef70)\n"
    3. , producing as output an empty string는, HASH(0x1cbef70) 같은 문자열로 평가합니다.
    4. 이 시점에서 print은 빈 문자열 즉 아무 것도 인쇄하지 않고 멈 춥니 다. 줄 바꿈 문자 \n은 이미 ref에 의해 소비되었으므로 건너 뜁니다. 따라서 print은 보이지 않습니다. 그리고 오류가 없습니다.

이 모든 Perl's operator precedence에서 하강 : 표에서 "함수 호출이"A "라는 단항 연산자"(단항 연산자 ref 인) 실제로

(...) 

8. left   + - . 
9. left   << >> 
10. nonassoc  named unary operators 
11. nonassoc  < > <= >= lt gt le ge 
12. nonassoc  == != <=> eq ne cmp ~~ 

(...) 

한다. 따라서 8 번째 줄의 . 연산자가 10 번째 줄의 함수 호출보다 우선 순위가 높습니다. 따라서 print의 결과는 예상 된 결과가 아닙니다. 반면에 함수 호출은 eq (12 행)보다 우선 순위가 높으므로 if 내부가 예상대로 작동합니다.

우선 순위 문제에 대한 해결책은 사용하는 것입니다.

  • 가능성이 함수 호출 강조하기 위해 괄호를 사용하는 것입니다

    print "ref \$book_ref is a " . ref($book_ref) . "\n"; 
    
  • 또 하나, 내가 덜 좋아하지만 그럼에도 불구하고 작동 연결될 수 있어야 문자열을 분리하기 위해 괄호를 사용하는 것입니다 바로 ref 전에 여는 괄호를 넣어 :

    print "ref \$book_ref is a " . (ref $book_ref) . "\n"; 
    
  • 또 다른 가능한 방법은 COMME에 zdim에 의해 제안 NT, 쉼표를 사용하는 것입니다

    print "ref \$book_ref is a ", ref $book_ref, "\n"; 
    

내가 먼저 내가 코드를 더 읽기 쉽게하기 위해 괄호를 피하기로 결정 if를 작성합니다. 그 다음 나는 그것을 복사했고 그 문제를 알아 채지 못했습니다. 나는 벌레를 발견하기 위해 2 시간을 낭비하는 것을 끝내었다.

가장 좋은 해결책은 다른 장소 (다른 print처럼)에 복사하면 문제를 방지하는 괄호도 복사 할 수 있기 때문입니다. 두 번째로 나는 괄호가 얼마나 중요한지 깨닫지 못하고 복사하지 않을 것입니다. 그리고 세 번째 것은 쉼표 만 사용하고 점은 사용하지 않아야한다는 것을 기억한다면 명확하고 따라서 오류가 발생하기 쉽지 않습니다. 그래서, 그들이 일하는, 나는 그들을 덜 안전하다고 생각합니다.

다른 의견도 printf을 사용하는 것이 좋습니다. 형식 지정자 또는 표현 보간법이 필요합니다 (예 : print "ref \$book_ref is a ${\ ref $book_ref }\n";). 읽기가 어렵습니다.

하단 : 항상 괄호을 사용하십시오.

+1

[인쇄 목록] (https://perldoc.perl.org/functions/print.html)의 쉼표를 사용하여 'print'값은 ", (코드)" "\ n"' – zdim

+1

또는' printf' – toolic

+0

또는 표현식 보간법을 사용하십시오 :'print "ref \ $ book_ref는 $ {\ ref $ book_ref} \ n" – mwp

관련 문제