2011-03-01 2 views
11

해시 참조가 기호 테이블을 참조하는지 여부를 알 수있는 방법이 있습니까? 그것은 오히려기호 테이블을 일반 해시 변수와 구별하는 방법은 무엇입니까?

foo(\%main) 

보다

foo(\%main::) 

로 호출되었다 여부

, 어떻게

sub foo { 
    my ($hashref) = @_; 
    ... 
} 

함수는 알 수 있을까?

이 응용 프로그램은 가끔 tie의 해시 변수이지만, 기호 테이블을 연결하지 않으려 고하는 기능입니다.

답변

7

HvNAME을 사용하는 C API에서 이렇게 할 수 있습니다. 마리화나가 마리화나가 아닌 경우

가 숨겨 놓은, 또는 NULL의 패키지 명을 돌려줍니다

HvNAME 다음은 perlapi에서입니다. SvSTASH, CvSTASH 을 참조하십시오.

  1. 문자는 * HvNAME (HV의 * 숨김)
+2

필자는'perl -MDevel :: Peek -e '덤프 (\ % a : :), 덤프 (\ % a)''를 실행하여 이것을 추론하기 시작했습니다. 링크를 가져 주셔서 감사 드리며 적은화물 이송을 할 수 있습니다. XS가 없다면 여전히 $ is_a_symtable = do {$ sv = B :: svref_2object ($ hashref); ref ($ sv) eq 'B :: HV'&& $ sv-> NAME} – mob

3

'::'로 끝나는 키를 찾을 수 있습니다.이 키는 다른 패키지를 가지고 있거나 모든 값이 기호 심판임을 나타냅니다.

  • 물론 여기서도 기호를 저장하는 해시 (해시)를 말할 필요가 없습니다. 나는 B::svref_2object으로 주위를 샅샅이 조사하고 있었지만, 일반 해시에 저장된 stash의 기호조차도 $sym->can('STASH')에 대해 뭔가를 반환합니다.

당신이 할 수있는 일은 기호 테이블을 통해 하강하고 똑같은 메모리 위치에 숨김이 있는지 확인하는 것입니다. 이 같은의

종류 :

use Scalar::Util qw<refaddr>; 
my %seen; 

sub _descend_symtable { 
    $calls++; 
    my ($cand, $stash_name) = @_; 
    my $stash = do { no strict 'refs'; \%{ $stash_name }; }; 
    return if $seen{ refaddr($stash) }++; 
    return $stash_name if $cand == $stash; 

    my $result; 
    foreach my $s (grep { m/::$/ } keys %$stash) { 
     $result = _descend_symtable($cand, "$stash_name$s") 
      and return $result; 
    } 
    return; 
} 

sub find_in_symtable { 
    my $needle = shift; 
    %seen  =(); 
    return _descend_symtable($needle, 'main::'); 
} 

이 성능은 끔찍한하지 않았다.

+0

이 좋은 출발이며, 나에게이 길의 95 %를 얻을 것입니다, 나는 생각한다. 이 테스트는 빈 패키지 ('foo (\ % empty :: package) '와'foo ({})')가 모호 할 수 있으며, 잘못된 판정을하기 위해 스푸핑 될 수 있습니다.'foo ({'abc :: '=> * main :: abc ::})'또는 false negative ('$ emptypkg :: { "def"} = "xyz"; foo (\ % emptypkg : :)'). 뭐라구? – mob

관련 문제