제3 장 펄 언어 (5) - 가방, 인용, 복잡 한 데이터

11868 단어
싸다.
Perl 에 있 는 가방 은 단일 이름 공간 에 있 는 코드 집합 입 니 다.가방 과 이름 공간의 차 이 는 가방 의 관심 사 는 소스 코드 이다.이름 공간 은 Perl 이 코드 를 조직 하고 관리 하 는 내부 데이터 구조 이다.패키지 로 가방 과 이름 공간 을 설명 합 니 다. (가방 을 만 들 면 이름 공간 을 만 듭 니 다)
package MyCode;
our @boxes;
sub add_box { ... }

성명 후 다음 에 정 의 된 모든 변수 와 함 수 는 MyCode 의 이름 공간 에 있 습 니 다.이 패키지 성명 의 관할 범 위 는 다음 패키지 성명 을 만 나 거나 파일 이 끝 날 때 까지 지속 되 는 것 입 니 다.또한 블록 을 사용 하여 성명 범 위 를 지정 할 수 있 습 니 다.
package Pinball::Wizard
{
our $VERSION = 1969;
}


가방 설명 이 없 으 면 기본 값 은 main 가방 에 있 습 니 다.이전에 우 리 는 다른 가방 (이름 공간) 안의 변수 와 함 수 를 방문 하려 면 완전히 한 정 된 이름 을 사용 해 야 한다 고 말 한 적 이 있다.예 를 들 어 main 패키지 에서 @MyCode::boxes 를 사용 하여 MyCode 의 boxes 배열 을 방문 합 니 다.
가방 에는 이름 외 에 버 전 번호 와 세 가지 함수 가 있 습 니 다. import (), unimport (), VERSION ().함수 VERSION () 은 가방 의 버 전 번호, 즉 가방 에 있 는 $VERSION 의 값 을 되 돌려 줍 니 다.Perl 은 버 전 번호 에 대해 격식 적 인 요구 가 있 습 니 다. 알파벳 v 로 시작 하고 최소 세 개 는 점 (.) 으로 정 수 를 구분 합 니 다.
package MyCode v1.2.1;

package Pinball::Wizard v1969.3.7 { ... }

#   ,        
package MyCode;
our $VERSION = 1.21;

모든 가방 은 UNIVERSAL 클래스 에서 VERSION () 함 수 를 계승 합 니 다.
my $version = Some::Plugin->VERSION;
#  $VERSION  

         (   )  ,                 ,       :
# require at least 2.1
Some::Plugin->VERSION( 2.1 );
die "Your plugin $version is too old" unless $version > 2;


가방 과 이름 공간
컴 파일 기간 과 실행 시 가방 의 내용 을 어디서 든 방문 하거나 수정 할 수 있 지만 코드 를 읽 기 어 려 울 수 있 습 니 다.많은 항목 들 이 자신의 최상 위 이름 공간 을 만 듭 니 다. 그러면 전체 변수 충돌 가능성 을 줄 이 고 더 좋 은 조직 코드 도 만 들 수 있 습 니 다. 예 를 들 어:
• StrangeMonkey      
• StrangeMonkey::UI       
• StrangeMonkey::Persistence       
• StrangeMonkey::Test     

이것 은 약속 일 뿐 강제 적 인 것 은 아니 지만, 이런 약속 은 매우 통용 된다.
인용 하 다.
먼저 예 를 들 어:
sub reverse_greeting
{
my $name = reverse shift;
return "Hello, $name!";
}

my $name = 'Chuck';
say reverse_greeting( $name );
say $name;

우 리 는 하나의 함 수 를 통 해 반전 기능 을 실현 하 기 를 기대한다.그러나 예 에서 코드 는 이렇게 작 동 합 니 다. 변수 값 을 함수 에 전달 하고 함수 내부 에서 반전 합 니 다.그러나 완성 후 함수 가 나 왔 지만 변수 값 은 변 하지 않 았 습 니 다 (아니면 Chuck).
한 가지 상황 을 다시 고려 해 보 세 요. 한 가지 값 이 있 습 니 다. 다른 곳 에서 여러 부 를 복 사 했 습 니 다. 지금 이 값 을 수정 해 야 합 니 다. 그러면 모든 곳 에서 고 치 려 고 합 니까?한 가지 수정 을 실현 할 수 있 는 메커니즘 이 있 습 니까?네, 인용 에 쓰 겠 습 니 다.
스칼라 참조
역 슬 래 쉬 를 사용 하여 인용 을 만 듭 니 다.스칼라 언어 환경 에서 하나의 인용 을 만 듭 니 다.목록 언어 환경 에서 일련의 인용 을 만 듭 니 다.인용 에 기호 ($) 를 추가 하면 인용 한 값 에 접근 할 수 있 습 니 다. 이것 이 바로 인용 을 푸 는 것 입 니 다.
my $name = 'Larry';
my $name_ref = \$name;

#       
say $$name_ref;

위의 반전 예 를 인용 으로 구현 합 니 다.
sub reverse_in_place
{
my $name_ref = shift;
$$name_ref = reverse $$name_ref;  #      
}
my $name = 'Blabby';
reverse_in_place( \$name );
say $name;

매개 변수 @_ 는 매개 변수 변수의 별명 이기 때문에 똑 같은 효 과 를 실현 할 수 있 습 니 다.
sub reverse_value_in_place
{
$_[0] = reverse $_[0];
}
my $name = 'allizocohC';
reverse_value_in_place( $name );
say $name;

#        

함수 전달 인용 을 호출 하면 메모리 사용 을 줄 일 수 있 습 니 다.이것 은 이해 하기 쉽 습 니 다. 다음 에 전달 하 는 큰 문자열 을 매개 변수 로 하고 전달 문자열 의 인용 을 비교 합 니 다.
복잡 한 인용 은 괄호 로 나 쁜 의 미 를 없 애 야 할 수도 있 습 니 다. 이것 이 야 말로 완전한 문법 입 니 다. 다만 대부분 생략 했 을 뿐 입 니 다.
sub reverse_in_place
{
my $name_ref = shift;
${ $name_ref } = reverse ${ $name_ref };
}

사용 할 때 인용 을 알 아 보 는 것 을 잊 어 버 리 면 펄 은 언어 환경 에 따라 문자열 SCALAR (0x93339e 8) 또는 숫자 0x93339e 8 로 강제로 변환 합 니 다.(그러나 이것 은 반드시 변수의 실제 메모리 주소 가 아 닙 니 다.
배열 참조
배열 참조 에는 다음 과 같은 용도 가 있 습 니 다.
  • 함수 에서 편평 한 목록 이 아 닌 배열 을 전달 하고 되 돌려 줍 니 다
  • 다 차원 배열 구조 만 들 기
  • 불필요 한 배열 복사 피하 기
  • 익명 배열
  • 배열 참조 설명:
    my @cards = qw( K Q J 10 9 8 7 6 5 4 3 2 A );
    my $cards_ref = \@cards;
    

    $cards ref 를 참조 하여 수정 하면 배열 @ cards 를 직접 수정 합 니 다. 기호 @ 을 사용 하여 인용 을 풀 고 전체 배열 에 접근 할 수 있 습 니 다.
    my $card_count = @$cards_ref;
    my @card_copy = @$cards_ref;
    

    화살표 기호 (- >) 를 사용 하여 단일 요소 에 접근 하기:
    my $first_card = $cards_ref->[0];
    my $last_card = $cards_ref->[-1];
    

    이렇게 방문 할 수도 있 습 니 다.
    my $first_-card = $$cards_ref[0];
    #  !
    

    슬라이스:
    my @high_cards = @{ $cards_ref }[0 .. 2, -1];
    #         ,     
    
    

    익명 배열, 참조 로 만 접근 할 수 있 습 니 다.
    my $suits_ref = [qw( Monkeys Robots Dinos Cheese )];
    

    다음 두 가지 상황 구분:
    #  
    my @meals = qw( soup sandwiches pizza );
    my $sunday_ref = \@meals;
    my $monday_ref = \@meals;
    
    
    my @meals = qw( soup sandwiches pizza );
    my $sunday_ref = [ @meals ];
    my $monday_ref = [ @meals ];
    # 2        @meals  ,     。
    

    해시 인용
    해시 참조 만 들 기:
    my %colors = (
    blue => 'azul',
    gold => 'dorado',
    red => 'rojo',
    yellow => 'amarillo',
    purple => 'morado',
    );
    my $colors_ref = \%colors;
    

    인용 하기 전에 기호% 를 사용 하여 전체 해시 에 접근 하고 사용 합 니 다:
    my @english_colors = keys %$colors_ref;
    my @spanish_colors = values %$colors_ref;
    

    화살표 연산 자 (- >) 를 사용 하여 요소 에 접근 하기:
    sub translate_to_spanish
    {
    my $color = shift;
    return $colors_ref->{$color};
    # or return $$colors_ref{$color};
    }
    

    슬라이스:
    my @colors = qw( red blue green );
    my @colores = @{ $colors_ref }{@colors};
    

    괄호 로 익명 해시 만 들 기:
    my $food_ref = {
    'birthday cake' => 'la torta de cumpleaños',
    candy => 'dulces',
    cupcake => 'bizcochito',
    'ice cream' => 'helado',
    };
    

    함수 참조
    함수 이름 에 대해 서 는 인용 연산 자 와 & 기 호 를 사용 하여 함수 인용 을 만 듭 니 다.
    sub bake_cake { say 'Baking a wonderful cake!' };
    my $cake_ref = \&bake_cake;
    #  &          ,   &      ,        。
    

    키워드 sub 를 사용 하여 익명 함수 만 들 기:
    my $pie_ref = sub { say 'Making a delicious pie!' };
    

    인용 호출 함수:
    $cake_ref->();
    $pie_ref->();
    

    파일 핸들 참조
    open 과 opendir 연산 자 에서 품사 변 수 를 사용 할 때 이 변 수 는 파일 핸들 참조 입 니 다. 이 핸들 은 IO: File 대상 입 니 다. 대상 방법 을 직접 호출 할 수 있 습 니 다.
    use autodie 'open';
    open my $out_fh, '>', 'output_file.txt';
    $out_fh->say( 'Have some text!' );
    

    오래된 코드 는 IO:: Handle 대상 을 사용 할 수 있 고 더 오래된 코드 는 기호 참조 를 사용 할 수 있 습 니 다.
    local *FH;
    open FH, "> $file" or die "Can't write '$file': $!";
    my $fh = \*FH;
    

    이러한 방식 은 여전히 사용 할 수 있 지만, 우 리 는 최신 품사 변수 방식 을 건의 합 니 다.
    인용 계수
    Perl 은 인용 계수 방식 으로 메모 리 를 관리 합 니 다. 모든 Perl 변 수 는 하나의 카운터 가 있 습 니 다. 인용 을 추가 하면 Perl 은 계산 기 를 하나 더 하고 인용 을 줄 이면 하 나 를 줄 입 니 다. 카운터 가 0 일 때 Perl 은 이 변 수 를 안전하게 회수 할 수 있다 고 생각 합 니 다.
    다음 코드 고려:
    say 'file not open';
    {
    open my $fh, '>', 'inner_scope.txt';
    $fh->say( 'file open here' );
    }
    say 'file closed here';
    

    변수 $fh 의 역할 영역 은 블록 안에 있 습 니 다. 범 위 를 초과 할 때 변수 가 효력 을 잃 습 니 다. Perl 은 계산 을 하나 줄 이 고 0 으로 바 꾸 면 Perl 은 해당 하 는 메모 리 를 회수 합 니 다. 모든 기술 세부 사항 을 알 필요 가 없습니다. 인용 을 사용 할 때 Perl 의 메모리 관리 에 어떻게 영향 을 미 치 는 지 알 면 됩 니 다.
    인용 과 함수
    함수 에 인용 을 전달 할 때 조심해 야 합 니 다. 함수 에서 원래 의 값 을 수정 할 수 있 습 니 다. 이것 은 당신 이 원 하 는 것 이 아 닐 수도 있 습 니 다. 이 상황 을 피 하려 면 먼저 변수 값 을 새로운 변수 로 복사 해 야 합 니 다.
    my @new_array = @{ $array_ref };
    my %new_hash = %{ $hash_ref };
    
    #             ,           Storable dclone()  。
    

    내장 형 데이터 구조
    때때로 당신 은 다 차원 배열 을 만 들 고 싶 지만 다음 과 같은 방식 으로 원 하 는 것 을 얻 을 수 없습니다.
    my @counts = qw( eenie miney moe );
    my @ducks = qw( huey dewey louie );
    my @game = qw( duck duck goose );
    my @famous_triplets = (
    @counts, @ducks, @game
    );
    

    이것 은 모든 데 이 터 를 하나의 목록 으로 합 쳐 하나의 배열 에 값 을 부여 합 니 다. 다 차원 배열 이 아 닙 니 다.
    해결 방법 은 인용 이다.
    #          
    my @famous_triplets = (
    \@counts, \@ducks, \@game
    );
    
    
    #          :
    my @famous_triplets = (
    [qw( eenie miney moe )],
    [qw( huey dewey louie )],
    [qw( duck duck goose )],
    );
    
    #    
    my %meals = (
    breakfast => { entree => 'eggs',
    side => 'hash browns' },
    lunch => { entree => 'panini',
    side => 'apple' },
    dinner => { entree => 'steak',
    side => 'avocado salad' },
    );
    

    마지막 요소 항목 뒤의 쉼표 는 선택 할 수 있 습 니 다. 게다가 원 소 를 추가 하 는 것 이 편리 합 니 다.
    인용 접근 다 차원 데이터 구 조 를 사용 하면 화살 표 는 선택 할 수 있 습 니 다.
    #    
    my $nephew = $famous_triplets[1][2];
    my $meal = $meals{breakfast}{side};
    
    #             
    my $last_nephew = $famous_triplets[1]->[2];
    my $meal_side = $meals{breakfast}->{side};
    
    #              :
    $actions{generous}{buy_food}->( $nephew, $meal );
    

    포 함 된 데이터 구조의 내용 이 배열 과 해시 라면 괄호 를 통 해 가 독성 을 증가 합 니 다.
    my $nephew_count = @{ $famous_triplets[1] };
    my $dinner_courses = keys %{ $meals{dinner} };
    

    포 함 된 데이터 의 절편:
    my ($entree, $side) =
    @{ $meals{breakfast} }{ qw( entree side ) };
    
    
          :
    my $meal_ref = $meals{breakfast};
    my ($entree, $side) = @$meal_ref{qw( entree side )};
    
    my ($entree, $side) = @{ $_ }{qw( entree side )}
    for $meals{breakfast};
    

    perldoc perldsc 는 Perl 의 각종 데이터 구조의 사용 예 를 볼 수 있 습 니 다.
    자동 활성화
    포 함 된 데이터 구조의 일부분 을 쓸 때 Perl 은 중간 에 필요 한 과정 을 자동 으로 만 듭 니 다.
    my @aoaoaoa;
    $aoaoaoa[0][0][0][0] = 'nested deeply';
    

    Perl 은 이 4 차원 배열 을 자동 으로 만 듭 니 다. 각 배열 은 하나의 요 소 를 포함 하고 있 습 니 다. 유사 한 것 은 다음 절 에서 해시 의 하 시 를 자동 으로 만 듭 니 다.
    my %hohoh;
    $hohoh{Robot}{Santa} = 'mostly harmful';
    

    이 동작 을 자동 활성화 라 고 합 니 다. 편리 하지만 본의 아니 게 당신 의 의 도 를 오해 할 수도 있 습 니 다. (당신 이 잘못 썼 습 니 다) CPAN 에 autovification 의 컴 파일 명령 이 있 습 니 다. 이 기능 의 사용 과 범 위 를 제어 할 수 있 습 니 다.
    디버그 내장 데이터 구조
    모듈 Data: Dumper 는 데이터 구 조 를 표시 할 수 있 습 니 다.
    use Data::Dumper;
    
    my $complex_structure = {
    numbers => [ 1 .. 3 ];
    letters => [ 'a' .. 'c' ],
    objects => {
    breakfast => $continental,
    lunch => $late_tea,
    dinner => $banquet,
    },
    };
    
    print Dumper( $complex_structure );
    
    $VAR1 = {
    'numbers' => [
    1,
    2,
    3
    ],
    'letters' => [
    'a',
    'b',
    'c'
    ],
    'meals' => {
    'dinner' => bless({...}, 'Dinner'),
    'lunch' => bless({...}, 'Lunch'),
    'breakfast' => bless({...}, 'Breakfast'),
    },
    };
    

    물론 다른 모듈 도 이 일 을 할 수 있 습 니 다. YAML: XS 와 JSON 모듈 입 니 다. 개발 자 들 은 이 2 모듈 을 사용 하 는 경향 이 있 을 수 있 습 니 다. 이 2 모듈 은 Perl 코드 가 생기 지 않 고 출력 결과 가 더욱 뚜렷 합 니 다. Data: Dumper 는 매우 상세 하 게 표 시 됩 니 다.
    회로 참조
    회로 참조 (상호 참조) 가 존재 할 때 인용 기록 기 는 0 이 될 수 없고 Perl 도 메모 리 를 영원히 회수 할 수 없습니다.
    my $alice = { mother => '', father => '' };
    my $robin = { mother => '', father => '' };
    my $cianne = { mother => $alice, father => $robin };
    push @{ $alice->{children} }, $cianne;
    push @{ $robin->{children} }, $cianne;
    

    Scalar:: Util 's 의 weaken () 함수 (약 인용) 를 사용 할 수 있 습 니 다. 약 인용 을 사용 하면 인용 수 를 증가 하지 않 습 니 다.
    use Scalar::Util 'weaken';
    my $alice = { mother => '', father => '' };
    my $robin = { mother => '', father => '' };
    my $cianne = { mother => $alice, father => $robin };
    push @{ $alice->{children} }, $cianne;
    push @{ $robin->{children} }, $cianne;
    weaken( $cianne->{mother} );
    weaken( $cianne->{father} );
    

    물론 대부분의 정상 적 인 데이터 구 조 는 회로 인용 이 나타 나 지 않 고 약 한 인용 을 사용 할 필요 가 없다.
    대체 내장 데이터 구조
    Perl 에 게 는 상관 없습니다. 아무리 복잡 한 내장 데이터 결과 도 순조롭게 처리 할 수 있 지만 사람 이 안 됩 니 다. 2 층 이나 3 층 이 넘 으 면 이해 하기 어렵 습 니 다. 이 럴 때 는 클래스 와 대상 기술 을 사용 하여 코드 를 더욱 선명 하 게 하 는 것 을 고려 할 수 있 습 니 다.

    좋은 웹페이지 즐겨찾기