Perl Study #6

[ 함수 (subroutine) ]

 

정의

perl에서는 함수를 일반적으로 subroutine이라고 부르며, 사용 시에는 함수 명 앞에 sub를 붙여준다.

->  sub subname{

statement 1;

statement 2;

}

* $fred, @fred, %fred와 서브루틴 fred 는 함께 존재할 수 있다

 

사용

①       Perl에서는 서브루틴을 파일의 끝부분에 두는 것을 선호한다

②       서브루틴 내에서 전역변수 접근이나 값 할당이 가능하다

③       서브루틴 이름과 뒤에 오는 괄호로써 서브루틴을 호출한다

④       서브루틴은 다른 서브루틴을 호출할 수 있다

->  say_hello();              # 간단한 표현식

$a = 3 + say_hello();     # 더 긴 표현식의 일부

for ($x = start_value(); $x < end_value(); $x += increment()){

…      # 값을 얻기 위해 3개의 서브루틴을 호출

}

 

리턴 값

①       return으로 서브루틴의 호출 값을 되돌릴 수 있다

->  sub sum_of_a_and_b{

return $a + $b;

}

$a = 3; $b = 4;

$c = sum_of_a_and_b();       # $c 는 7

②       리스트 구문이 사용될 때는 값의 리스트를 리턴할 수 있다

->  sub list_of_a_and_b{

return($a, $b);

}

$a = 5; $b = 6;

@c = list_of_a_and_b();       # @c 는 (5, 6)

 

인수(arguments)

perl에서 서브루틴 호출은 괄호 내에 리스트가 뒤따르는데, 그 리스트는 서브루틴의 기간동안 자동으로 @_라는 특수한 변수에 할당된다. 서브루틴에서 이 변수에 접근하기 위해서는 $_[0], $_[1], $_[2] 과 같이 사용한다

->  sub say_hello_to {

print “hello, $_[0]! ”;     # 첫번째 매개변수가 목표

}

say_hello_to(“world”);          #  hello를 world에게

$x = “somebody”;

say_hello_to($x);               #  hello를 somebody에게

say_hello_to(“me”) + say_hello_to(“you”);    # 그리고 me와 you에게

* 마지막 행에서 리턴 값은 실제로 사용되지 않았지만, 합을 계산하기 위해서 perl은

그것의 모든 부분을 계산해야 하므로 서브루틴을 두번 호출했다

->  sub say{

print “$_[0], $_[1]! ”;

}

say(“hello”, “world”);       # 하나 이상의 인수를 사용하는 예

* 초과하거나 부족한 인수는 무시된다 (undef 값)

* $_[] 과 $_ 은 비슷하지만 아무런 관련이 없으므로 혼동하지 말 것!

 

함수 내의 사설 변수

my를 이용하여 동일하게 동작하는 사용자 자신의 스칼라, 배열, 해시 변수를 만들 수 있다

->  sub add{

my (%sum);             # $sum 지역 변수로 만듦

$sum = 0;               # sum을 초기화

foreach $_ (@_) {

$sum += $_;        # 각 요소를 더함

}

return $sum;            # 계산되는 마지막 식: 모든 요소의 합

}

* 전역변수 sum이 존재하더라도 add 서브루틴에서는 지역변수 sum을 쓸 수 있다

* 많은 중첩된 지역 변수 버전을 가질 수 있지만 한 순간에 오직 하나만 접근된다

->  sub bigger_than {

my($n, @values);          # 몇몇 지역 변수를 생성

($n, @values) = @_;        # args를 한계와 값으로 분리

my(@result);              # return 값을 담을 임시 공간

foreach $_ (@values) {     # args 리스트에 하나하나 적용

if ($_ > $n) {           # 조건을 만족하는가?

push(@result, $);   # 추가하라

}

}

return @result;            # 마지막 결과를 리턴

}

@new = bigger_than(100, @list);    # @new는 모든 @list > 100을 얻음

@this = bigger_than(5, 1, 5, 15, 30); # @this는 (15, 30)가 됨

my의 결과는 할당 가능한 리스트로 이것의 의미는 배열 할당 연산자의 왼쪽 편에 사용될 수 있다는 것이다. 이 리스트는 새로이 생성된 변수의 각각에 대해 초기값을 줄 수 있다.

->  my($n, @values);

($n, @values) = @_;    # args를 한계와 값으로 분리

->  my($n, @values) = @_;  # 위의 두 문장을 하나로 결합해서 사용 가능

->  my($sum) = 0;         # 인수 없는 지역 변수를 초기화

*  my는 선언문처럼 보이지만 실제로는 실행 연산자임을 주의

*  my 연산자를 서브루틴 정의의 시작부분에 몰아 두는 것이 좋은 프로그래밍 방법이다

local을 이용한 준사설(semiprivate)변수

local변수는 그들 변수가 선언된 블록 내에서 호출 된 함수는 볼 수 있다

-> $value = “original”;

tellme(); spoof(); tellme();

sub spoof() {

local ($value) = “temporary”;

tellme();

}

sub tellme() {

print “Current value is $value ”;

}

출력 결과>

Current value is original        # local 대신 my가 사용되었을 경우 $value를 읽는

Current value is temporary     # 것은 spoof() 함수에서만 가능했을 것이다

Current value is original

파일레벨 my() 변수

use  strict;

를 파일의 시작부에 둔다면 my()를 이용해 변수선언을 강제 할 수 있으며, my()로 선언되지 않은  변수는 에러를 낸다

-> use strict;

my $a;                           # undef로 시작

my @b = qw(fred barney betty);  # 초기 값을 줌

push @b, qw(wilma);

@c = sort @b;                   # 컴파일되지 않는다

* 변수 선언을 강제하는 것의 이점 2가지

①       프로그램 실행이 빨라진다

(일반 변수보다 my로 생성된 변수가 좀 더 빨리 엑세스 된다)

②       $fred가 필요할 때, 더 이상 존재하지 않는 이름의 $fred를 참조하지 않아도 되므로 타이핑 상의 오류를 훨씬 빨리 잡을 수 있다.

* 파일레벨 my()변수선언은 지역변수와는 다르다

 

[기타 제어 구조]

 

last

last문은 C의 break문과 같은 역할을 한다. 가장 안쪽의 루프 블록에서 빠져 나와 그 블록 바로 뒤에 오는 문에서 실행을 계속 하도록 한다

-> while (something) {

something;

if (somecondition) {

somethingorother;

last;    # while 루프를 빠져나감

}

morethings;

}

# last는 이곳으로 옴

* last 문은 오직 루프 블록과 사용되며, 다른 문법 구조들을 만드는 데 필요한 다른 블록

들과는 사용되지 않는다. (if/else문은 고려 대상이 아님!)

 

next

next는 last와 비슷하지만, 블록을 마치지 않고 가장 안쪽 루프 블록의 나머지를 건너뛰어 실행하도록 한다.

->  while (something) {

firstpart;

if  (somecondition) {

somepart;

next;

}

otherpart;

# next는 이곳으로 온다

}

redo

redo는 현재 블록의 시작부로 건너뛰도록 한다

->  while (somecondition) {

# redo는 이곳으로 온다

something;

if (somecondition) {

somestuff;

redo;

}

morething;

}

 

라벨붙이기

라벨을 정한 후, 블록을 포함하는 문 바로 앞 뒤에 콜론을 붙여서 위치시킨다

-> SOMELABEL: while (condition) {

statement;

if (nuthercondition) {

last SOMELABEL;

}

}

 

표현식 수정자

“if this, then that” 과 같은 방식으로 if문을 사용했던 것 과는 달리 perl은 다음과 같은 형식을 지원한다

some_expression if control_expression;

이것은 다음 예제와 동일하다

 

if (control_expression) {

some_expression;

}

-> LINE: while (<STDIN>) {

last LINE if /^From: /;

}

* unless, while, until도 이와 비슷하게 사용 가능하다

-> exp2 unless exp1;     # unless (exp1) {exp2;} 와 유사

exp2 while exp1;      # while (exp1) {exp2;} 와 유사

exp2 until exp1;       # until (exp1) {exp2;} 와 유사

 

제어구조로서의 && 와 ||

다음과 같은 형식으로 제어구조로서 사용이 가능하다

*  this && that;     : if (this) {that};

-> this가 참이면, 여전히 전체 표현식의 값은 that에 의존하기 때문에 미정이다. 따라서

that이 계산되어야만 한다

-> this가 거짓이면, 이미 전체 표현식의 값은 거짓이 되므로 더 이상 that을 볼 필요가

없다. 따라서 that을 계산할 필요가 없으므로 이를 건너 뛴다

*  this || that;      : unless (this) {that};

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다