Perl 변수에 어떤 유형의 값이 있는지 어떻게 알 수 있습니까?
Perl 변수에 어떤 유형의 값이 있는지 어떻게 알 수 있습니까?
$x
스칼라, 배열에 대한 참조 또는 해시에 대한 참조 (또는 다른 것) 일 수 있습니다.
ref () :
Perl은
ref()
참조를 역 참조하기 전에 참조 유형을 확인할 수 있도록 함수를 제공합니다 .
ref()
함수를 사용하면 잘못된 참조 유형을 사용할 때 변수를 역 참조하는 프로그램 코드가 오류를 생성하지 않도록 보호 할 수 있습니다.
$x
항상 스칼라입니다. 힌트는시길입니다 $
.로 시작하는 모든 변수 (또는 다른 유형의 역 참조) $
는 스칼라입니다. ( 데이터 유형에 대한 자세한 내용은 perldoc perldata 를 참조하십시오 .)
참조는 특정 유형의 스칼라입니다. 내장 함수 ref
는 그것이 어떤 종류의 참조인지 알려줍니다. 반면에 축복받은 참조가있는 경우 ref
데이터의 실제 핵심 유형이 아닌 참조가 축복받은 패키지 이름 만 알려줍니다 (축복 참조는 해시 참조, 배열 참조 또는 기타 항목 일 수 있음). 당신이 사용할 수있는 스칼라 :: 백분율 의는 reftype
그것이 참조 어떤 종류의 당신을 말할 것이다 :
use Scalar::Util qw(reftype);
my $x = bless {}, 'My::Foo';
my $y = { };
print "type of x: " . ref($x) . "\n";
print "type of y: " . ref($y) . "\n";
print "base type of x: " . reftype($x) . "\n";
print "base type of y: " . reftype($y) . "\n";
... 출력을 생성합니다.
type of x: My::Foo
type of y: HASH
base type of x: HASH
base type of y: HASH
다른 유형의 참조 (예 : coderef, arrayref 등)에 대한 자세한 내용은 다음 질문을 참조하십시오. Perl의 ref () 함수를 사용하여 REF, IO 및 LVALUE를 반환하려면 어떻게해야합니까? 및 perldoc perlref .
참고 : 축복 된 객체 (예 :)로 코드 분기를 구현 하는 데를 사용 해서는 안됩니다 . 변수 유형에 따라 결정을 내려야하는 경우 (예 : 또는 )를 사용하십시오. 다형성을 참조하십시오 .ref
$ref($a) eq "My::Foo" ? say "is a Foo object" : say "foo not defined";
isa
if ($a->isa("My::Foo") { ...
if ($a->can("foo") { ...
스칼라는 항상 단일 요소를 보유합니다. 스칼라 변수에있는 것은 항상 스칼라입니다. 참조는 스칼라 값입니다.
참조인지 알고 싶다면 ref
. 참조 유형을 알고 싶다면 Scalar :: Util 의 reftype
루틴을 사용할 수 있습니다 .
객체인지 알고 싶다면 Scalar :: Util 의 blessed
루틴을 사용할 수 있습니다 . 하지만 축복받은 패키지가 무엇인지 신경 쓰지 말아야합니다. 객체에 대해 알려주는 몇 가지 메소드가 있습니다 . 호출하려는 메소드가 있는지 확인하려면 ; 무언가에서 상속되는지 확인하려면 ; 객체가 역할을 처리하는 것을 보려면을 사용하십시오 .UNIVERSAL
can
isa
DOES
해당 스칼라가 실제로 스칼라처럼 작동하지만 클래스에 연결되어 있는지 알고 싶다면 tied
. 물건을 받으면 계속 확인하십시오.
숫자처럼 보이는지 알고 싶다면 Scalar :: Utillooks_like_number
에서 사용할 수 있습니다 . 숫자처럼 보이지 않고 참조가 아니라면 문자열입니다. 그러나 모든 단순 값은 문자열이 될 수 있습니다.
좀 더 멋진 일을해야한다면 Params :: Validate 와 같은 모듈을 사용할 수 있습니다 .
수동으로 무언가를 확인하는 대신 다형성을 좋아합니다.
use MooseX::Declare;
class Foo {
use MooseX::MultiMethods;
multi method foo (ArrayRef $arg){ say "arg is an array" }
multi method foo (HashRef $arg) { say "arg is a hash" }
multi method foo (Any $arg) { say "arg is something else" }
}
Foo->new->foo([]); # arg is an array
Foo->new->foo(40); # arg is something else
다른 유형 제약과 마찬가지로 "검사"를 재사용 할 수 있으므로 수동 검사보다 훨씬 강력합니다. 즉, 배열, 해시 및 42보다 작은 짝수를 처리하려면 "42보다 작은 짝수"에 대한 제약 조건을 작성하고 해당 경우에 대한 새로운 다중 메서드를 추가하면됩니다. "호출 코드"는 영향을받지 않습니다.
형식 라이브러리 :
package MyApp::Types;
use MooseX::Types -declare => ['EvenNumberLessThan42'];
use MooseX::Types::Moose qw(Num);
subtype EvenNumberLessThan42, as Num, where { $_ < 42 && $_ % 2 == 0 };
Then make Foo support this (in that class definition):
class Foo {
use MyApp::Types qw(EvenNumberLessThan42);
multi method foo (EvenNumberLessThan42 $arg) { say "arg is an even number less than 42" }
}
Then Foo->new->foo(40)
prints arg is an even number less than 42
instead of arg is something else
.
Maintainable.
At some point I read a reasonably convincing argument on Perlmonks that testing the type of a scalar with ref
or reftype
is a bad idea. I don't recall who put the idea forward, or the link. Sorry.
The point was that in Perl there are many mechanisms that make it possible to make a given scalar act like just about anything you want. If you tie
a filehandle so that it acts like a hash, the testing with reftype
will tell you that you have a filehanle. It won't tell you that you need to use it like a hash.
So, the argument went, it is better to use duck typing to find out what a variable is.
Instead of:
sub foo {
my $var = shift;
my $type = reftype $var;
my $result;
if( $type eq 'HASH' ) {
$result = $var->{foo};
}
elsif( $type eq 'ARRAY' ) {
$result = $var->[3];
}
else {
$result = 'foo';
}
return $result;
}
You should do something like this:
sub foo {
my $var = shift;
my $type = reftype $var;
my $result;
eval {
$result = $var->{foo};
1; # guarantee a true result if code works.
}
or eval {
$result = $var->[3];
1;
}
or do {
$result = 'foo';
}
return $result;
}
For the most part I don't actually do this, but in some cases I have. I'm still making my mind up as to when this approach is appropriate. I thought I'd throw the concept out for further discussion. I'd love to see comments.
Update
I realized I should put forward my thoughts on this approach.
This method has the advantage of handling anything you throw at it.
It has the disadvantage of being cumbersome, and somewhat strange. Stumbling upon this in some code would make me issue a big fat 'WTF'.
I like the idea of testing whether a scalar acts like a hash-ref, rather that whether it is a hash ref.
I don't like this implementation.
ReferenceURL : https://stackoverflow.com/questions/1731333/how-do-i-tell-what-type-of-value-is-in-a-perl-variable
'IT story' 카테고리의 다른 글
Enum을 가져 오는 방법 (0) | 2020.12.29 |
---|---|
HTML에 PowerPoint 프레젠테이션 포함 (0) | 2020.12.29 |
더 이상 사용되지 않는 의미? (0) | 2020.12.29 |
Django의 DateTimeField를 선택적으로 만드는 방법은 무엇입니까? (0) | 2020.12.29 |
Windows에서 setup.py를 통해 Python 모듈을 설치하는 방법은 무엇입니까? (0) | 2020.12.29 |