[첫화면으로]Perl/Typeglob

마지막으로 [b]

1. Symbol Table, Typeglob - aero님의 강좌
1.1. Symbol Table과 Identifier
1.2. Perl의 Symbol table
1.3. Symbol table에 접근하기
1.4. Symbol table의 내의 값에 접근
1.5. 레퍼런스
1.6. 타입글로브와 레퍼런스 1
1.7. 타입글로브와 레퍼런스 2
1.8. 모듈의 import
2. Comments

1. Symbol Table, Typeglob - aero님의 강좌

1.1. Symbol Table과 Identifier

Symbol table : 컴퓨터 언어에서 컴파일러가 Identifier(식별자)를 관리하는 저장장소이다.

Identifier :

1.2. Perl의 Symbol table

심볼테이블  심볼이름      타입       변수
 
 main::      c         SCALAR    $c
                       ARRAY     @c
                       HASH      %c
                       CODE      &c
                       IO        파일 혹은 디렉토리 핸들
                          GLOB      *c
                       FORMAT    포멧이름
                          NAME
                       PACKAGE 

일반적인 프로그램에서 스칼라 변수 $c를 선언(패키지 변수)했다면, main:: 이라는 심볼테이블의 c라는 심볼이름 내에 SCALAR 타입에 그 값이 들어가게 된다.

1.3. Symbol table에 접근하기

main 패키지의 심볼 덤프하기

> perl -e 'print join,"\n", keys %main::'

심볼생성 확인

> perl -e 'print join "\n", keys %main::' | grep abc
없음

> perl -e '$abc=1;print join "\n", keys %main::' | grep abc
abc
있음

1.4. Symbol table의 내의 값에 접근

Symbol table 접근은 심볼이름(identfier)앞에 "*"가 붙은 Typeglob를 통해서 한다.

*main::c          # c라는 심볼이름을 가지는 모든 타입에 대한 레퍼런스를 가르킴
*main::c{SCALAR}  # $c 의 레퍼런스를 가르킴
*main::c{ARRAY}   # @c 의 레퍼런스를 가르킴
#같은 패키지 안이면 심볼테이블명(main::) 생략가능
*c
*c{SCALAR}
*c{ARRAY}

$c = 2;   # use strict를 쓰지 않고 바로 변수를 쓰면 패키지변수
print $c, "\n";                  # 그냥 접근 (보통의 경우)
print $main::c, "\n";            # 패키지를 명시적으로 지정하여 접근

print ${*main::c{SCALAR}}, "\n"; # 타입글로브에 타입을 지정하여 접근
print ${*c{SCALAR}}, "\n";       # 같은 패키지 안이므로 패키지이름 생략가능
print ${*main::c}, "\n";         # 디레퍼런스 타입을 지정했으므로 타입 생략가능
print ${*c}, "\n";               # 같은 패키지 안이므로 모두생략 가능 
모두 2가 찍힘

1.5. 레퍼런스

레퍼런스의 종류

$c=5;
$sym = "c";  # 심볼릭레퍼런스(symbolic reference)
$ref = \$c;  # 하드레퍼런스(hard reference)
print ${$sym},$$sym,"\n"; # $sym을 디레퍼런스해서 찍음
print ${$ref},$$ref,"\n"; # $ref을 디레퍼런스해서 찍음

$c=5;
@c=(1,2);
$sr = \$c;   #레퍼런스(스칼라 타입)에 $c의 주소를 저장
$ar = \@c;   #레퍼런스(스칼라 타입)에 @c의 주소를 저장
print ${$sr},$$sr,"\n";  # $sr을 디레퍼런스해서 찍음
print @{$ar},@$ar,"\n";  # $ar을 디레퍼런스해서 찍음

1.6. 타입글로브와 레퍼런스 1

#!/usr/bin/perl
use strict;
our $c=5;
our @c=(1,2);
our ($d,@d);
our ($e,@e);

*d=*c;         # 이제 c의 모든 타입은 d의 모든 타입과 연결된다.
*e=*c{SCALAR}; # c의 스칼라 값만 연결된다. *e=\$c; 과 같은 의미
                 # \$e = \$c; 는 동작하지 않는다.

print "$d\n";  # $c에서 지정한 값이 찍힌다. 
print "@d\n";  # @c에서 지정한 값이 찍힌다.
print "$e\n";  # $c에서 지정한 값이 찍힌다.
print "@e\n";  # 아무것도 안 찍힌다.

1.7. 타입글로브와 레퍼런스 2

#!/usr/bin/perl
use strict;
our $c=5;
our @c=(1,2);
our ($ref1,$ref2);

$ref1 = *c;   # 심볼이름 c의 모든 타입의 레퍼런스가 된다.

print "$$ref1 @$ref1\n";

$ref2 = \$c;  # $c에 대한 레퍼런스가 된다.
print "$$ref2\n";

1.8. 모듈의 import

/모듈을 use 하면 모듈의 코드를 require하는 과정과 import하는 과정이 동시에 일어나게 된다. 이 import 과정에서 심볼테이블과 타입글로브가 쓰인다.

# My.pm

package My;
use strict;
use warnings;

#보통의 경우 import는 Exporter 모듈에서 알아서 처리해주나 여기서는 직접구현
sub import {
    my $caller = caller(); # caller 함수는 호출한 쪽의 패키지이름을 넘겨준다.
    {
        no strict 'refs';
        *{$caller."::hello"} = *hello;    # 서로 다른 네임스페이스의 심볼을 연결
        # *{$caller."::hello"} = \&hello;  # 명시적으로 함수만 연결할 때
    }
}

sub hello {
    print "hello\n";
}

1;

#!/usr/bin/perl
use strict;
use warnings;
use My;  # BEGIN { require My; My->import; } 와 같은의미

My::hello();  # require만 됐다면 이렇게 호출해야 한다.
hello();      # import되었으므로 바로 호출가능

2. Comments

이름:  
Homepage:
내용:
 


컴퓨터분류

마지막 편집일: 2019-6-26 4:02 pm (변경사항 [d])
3052 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기