Perl의 특수한 + unary operator(단항연산자)

Perl에서 대표적인 연산자 형태를 보면 다음과 같은 것들을 들 수 있다.

! $x                # a unary operator (단항연산자)
$x + $y             # a binary operator (이항연산자)
$x ? $y : $z        # a trinary operator (삼항연산자)
print $x, $y, $z    # a list operator (리스트연산자)

그런데 Perl에서 두 값을 더하는 +는 이항연산자로 쓰이는 것 외에 단항연산자로 쓰이는 특별한 경우가 있다.

print (1+3),5; 의결과는 어떻게 될까?

print 4,5;는 4와 5가 모두 찍히는 데 반해 4만 찍힌다. 이 둘이 어떻게 다른 것인지를 알려면 일단 Perl에서 함수가 작동하는 방식을 이해할 필요가 있다. Perl에서 함수를 호출할 때는 print(1,2);처럼 인자를 ()로 싸서 호출할 수도 있고 print 1,2; 처럼 ()를 싸지 않고 호출할 수 있는데 Perldocperlop문서를 보면 알겠지만 Perl에서는 가장 높은 연산자우선순위를 가지는 것은 Terms 과 리스트연산자(좌측)이며 TERM은 변수, 인용, 유사인용 연산자를 포함하며, 괄호안의 수식, 인자를 괄호로 묶은 함수를 포함한다. 실제적으로 이런 의미에서는 함수란 없으며 단지 함수처럼 쓰이는 리스트 연산자와 단항 연산자가 있을 뿐이기 때문에 이 둘 사이는 차이점이 없다.

예를 든 print 함수는 여기서 문법상 정의가 print LIST;로 LIST를 받는 리스트연산자로 작동하며 다른 예로 배열에서 하나의 요소를 꺼내는 pop은 문법상 정의가 pop ARRAY; 이며 ARRAY 하나를 받는 단항연산자처럼 작동한다.

함수명 바로 다음에 (가 나오면 함수는 )가 나올 때 까지를 인자로 인식하기 때문에 print (1+3),5;에서 print는 1+3=4 하나를 인자로 인식하고 4만 찍고 끝내버리고 ,5 는 void context(결과가 어디에도 저장되지 않고 어떤 다른 용도로도 사용되지 않는 문맥)로 무시된다. 이것은 use warnings; pragma를 쓰면 경고를 해준다.

이런 문제를 해결하려면 명시적으로 ()로 묶어서 print( (1+3),5 ); 이렇게 호출하면 된다. 여기서 또 다르게 함수명 다음에 처음 만나는 (가 함수의 인자를 묶는 괄호가 아니라는 의미로 + 단항연산자를 사용하여 print +(1+3),5; 이렇게 해도 4와 5가 모두 찍힌다. 여기서 +는 아무런 부가동작도 하지 않으며 단지 의미상으로 단지 함수가 받는 인자(들)중 하나의 표현식을 묶는 괄호임을 얘기해주는 것이다. 다른 예를 들면 @ans = sort +(5 + 5)*10, -4; 이런 식으로도 사용가능하다.

그리고 + 단항연산자는 문법적으로 혼돈의 여지가 있을 때 {}가 코드블럭이 아니라 익명해쉬를 뜻하는 것이라는것을 명시적으로 나타내는데도 다음과 같은 용도들로 쓰인다.

my @expect=map +{ key => $_, dirty => 0, },1..5;

return +{ name=>'Tom', number=>1 };


그러면 함수를 호출할 때 어떨 때 ()를 묶어서 호출하고 어떨 땐 없이 호출해야 할까?

Perl 코딩규약을 다루는 책인 Perl Best Practices에서는 다음과 같은 가이드라인을 제시하고 있다.

Perl builtins(내장함수)나 honorary(Carp,List::Util 등 Core module에 포함된 함수 - 언어 자체에 포함되어야 할 것 같은 함수인데 모듈로서 지원하는 것들)를 호출 할 때는 기본적으로 필요없는 괄호를 붙이지 않고 사용하여 이것들과 여타 모듈함수들 및 서브루틴호출(은 명시적으로 괄호를 묶어서 호출)이 시각적으로 구분되게 하고 위에서 예를 든 print같은 경우처럼 해석상에 혼돈이 있을경우 명시적으로 ()를 붙여주긴 하는데 for, while 같은 control keyword 같이 보이지 않도록 함수명과 (사이는 공백없이 붙여써라.

print ($value1 + $value2), " is the sum of $value1 and $value2 \n";  # 원하는 결과가 안나옴
print +($value1 + $value2), " is the sum of $value1 and $value2 \n";   # +단항연산자로 해결
print( ($value1 + $value2), " is the sum of $value1 and $value2 \n");  #  명시적으로 괄호를 묶어 해결(권고사항)
print ( ($value1 + $value2), " is the sum of $value1 and $value2 \n");  # 권하지 않는 형태


0 TrackBacks

Listed below are links to blogs that reference this entry: Perl의 특수한 + unary operator(단항연산자).

TrackBack URL for this entry: http://aero.sarang.net/cgi-bin/mt/mt-tb.cgi/52

1 Comments

Raymundo said:

잘 읽었습니다 ^^ 저거 볼 때마다 헷갈리는 문제이긴 하더군요.

Leave a comment

About this Entry

This page contains a single entry by aero published on January 30, 2008 9:03 AM.

까려면 제대로 알고 까자. - Perl에 대한 오해 was the previous entry in this blog.

경품추첨용 Perl코드 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Creative Commons License
This weblog is licensed under a Creative Commons License.
Powered by Movable Type 4.21-en