Что значит делать "$ var = * $ self -> {class_var};" - PullRequest
10 голосов
/ 11 февраля 2011

Я пытался найти это, но ничего не нашел.

Мне просто любопытно, почему можно поставить звездочку в следующем сценарии:

$var = *$self->{class_var};

Что * делает в этой ситуации?

Обновление

Я взял вышесказанное из модуля Net :: Telnet и просто пытаюсь понять это.

Фактический код:

$s = *$self->{net_telnet};

Интересно, а net_telnet - это имя пакета?

Ответы [ 5 ]

8 голосов
/ 11 февраля 2011
%main::some_hash = (class_var => 'xyz');

my $self = *main::some_hash;

print *$self->{class_var}, "\n";   # prints 'xyz'

Короче говоря, это устаревший способ передачи ссылки на хеш в таблице символов.Значение * перед $self разыменовывает значение в $self как типоблок.->{class_var} затем разыменовывает этот глобальный тип как хеш и ищет ключ class_var.

Обновление:

Копание иерархии классов показывает, что объект создается в IO::Handle с:

sub new {
    my $class = ref($_[0]) || $_[0] || "IO::Handle";
    @_ == 1 or croak "usage: new $class";
    my $io = gensym;
    bless $io, $class;
}

Symbol::gensym возвращает полный типглоб, из которого в основном используется слот IO.Однако, поскольку это полный типоблок, субмодули используют этот факт и хранят свои данные в различных других полях глобуса, а именно в части HASH.

6 голосов
/ 11 февраля 2011

Из короткого кода, который у вас есть, я предполагаю, что $self содержит типоглоб.Вы можете получить доступ к подэлементам явным образом, как упоминает Евгений, или неявно, используя любой стандартный синтаксис разыменования для typeglob.

#!/usr/bin/perl

use strict;
use warnings;

our %test = ( class_var => "test class_var" );
our @test = qw(one four nine);

my $self = \*test;
print "Self is '$self'\n";

my $var1 = *{$self}{HASH}{class_var};
print "Var1 is '$var1'\n";

my $var2 = *$self->{class_var};
print "Var2 is '$var2'\n";

my $var3 = ${*{$self}}{class_var};
print "Var3 is '$var3'\n";

my $var4 = ${*$self}{class_var};
print "Var4 is '$var4'\n";

my $x_scale = *$self{ARRAY}[0];
print "x_scale is '$x_scale'\n";

my $y_scale = *$self->[1];
print "y_scale is '$y_scale'\n";

my $z_scale = ${*$self}[2];
print "z_scale is '$z_scale'\n";

Ссылка на Typeglob (вне псевдонимов символов) чаще всего используется для слота IO, которыйпозволяет использовать объект в качестве дескриптора файла, но поскольку глобус типа содержит один из переменных каждого типа, другие слоты переменных могут использоваться для хранения дополнительных данных состояния.

Глобус типа не обязательно должен быть глобальным, Symbol::gensym может создать глобальный тип, который в основном анонимный.

3 голосов
/ 11 февраля 2011

Вероятно, это имеет дело с объектом файлового дескриптора. Сам дескриптор файла хранится в слоте fh глобуса, но метаданные о дескрипторе файла хранятся в слоте хэша глобуса.

Так что это говорит

$var = *{$self}{class_var}

т.е. разыменовывать $ self как typeglob, а затем использовать его как хеш.

Вы не можете использовать $ self -> {class_var}, потому что это не ссылка на HASH, это ссылка на GLOB.

use strict;

my $fh;    

my $self = \*fh;

*$self->{val} = 'foo';

Я использовал $fh в качестве примера, но на самом деле IO :: Handle (вероятно) будет использовать другой способ создания ссылки на глобус. Но с этим фрагментом кода вы должны увидеть, что

print ref $self;

говорит GLOB, но вы все равно можете

print *$self->{val};

чтобы получить foo.

Далее читайте здесь: http://perldoc.perl.org/perldata.html#Typeglobs-and-Filehandles

3 голосов
/ 11 февраля 2011
Синтаксис

*$var дает вам доступ к набору глобальных переменных по имени.Например, $foo, @foo, %foo и *foo:

package main;
no strict;
$foo = 'bar';     # global variable!
@main::foo = qw(an array);
%foo = ('hash' => 'table');
open foo, '>', '/tmp/foo';

$self = 'foo';

print "\$$self is ${*$self}\n";   # $foo
print "\@$self is @{*$self}\n";   # @foo 
print "\%$self is {",
  (map {$_, " => ", *$self->{$_}, ","} keys %{*$self}),
  "}\n";
print "Performing operations on the $self filehandle:\n";
print {*$self} "hello world\n";
close *$self;

open X, '<', '/tmp/foo'; 
print <X>; 
close X;

$foo is bar
@foo is an array
%foo is {hash => table,}
Performing operations on the foo filehandle:
hello world

Конечно, в наше современное время со ссылками и лексическими переменными что-нибудь сделанос таким кодом, вероятно, можно было бы сделать лучше.

2 голосов
/ 11 февраля 2011

похоже на случай, когда кто-то что-то делает с typeglobs; например * $ self может быть подклассом, реализующим дескриптор файла
@ Дейв Шерохман, взгляни на источник IO :: Pipe . он содержит несколько забавных кодов, которые много играют с typeglobs, немного в вопросе

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...