2015-08-07 2 views
1

Как правильно определить анонимный скаляр ref в Perl?Как определить анонимный скаляр в Perl?

my $scalar_ref = ?;

my $array_ref = [];

my $hash_ref = {};

+0

Вы можете инициализировать его до нуля: Perl -E «$ а = \ 0; скажем $ a; say $$ a 'so '$ a' теперь является скалярной ссылкой, а содержимое ссылки является скаляром 0. –

+0

См. мой обновленный rant. – simbabque

ответ

4

Обычно вы просто объявлять и не инициализировать его.

my $foo; # will be undef. 

Вы должны учитывать, что пустой хэш-реффикты и пустой массив refs указывают на структуру данных, которая имеет представление. Оба они, когда разыменовываются, дают вам пустой список.

perldata говорит (курсив мой):

Есть на самом деле две разновидности нулевых строк (иногда называют как «пустые» строки), определенный один и не определен один. Определенная версия - это всего лишь строка с нулевой длиной, например «". Неопределенная версия - это значение, указывающее, что для чего-либо не существует реального значения, например, когда произошла ошибка или в конце файла, или когда вы ссылаетесь на неинициализированную переменную или элемент массива или хэша. Хотя в ранних версиях Perl неопределенный скаляр мог быть определен при первом использовании в месте, ожидающем определенного значения, это больше не происходит, за исключением редких случаев автовивитации, как описано в perlref. Вы можете использовать определенный() оператор, чтобы определить, определено ли скалярное значение (это не имеет значения для массивов или хэшей), и для оператора undef() для получения неопределенного значения.

Так пустой скалярная (который на самом деле не сказать) будет undef. Если вы хотите, чтобы это была ссылка, сделайте ее одной.

use strict; 
use warnings; 
use Data::Printer; 

my $scalar_ref = \undef; 
my $scalar = $$scalar_ref; 

p $scalar_ref; 
p $scalar; 

Этот выход будет:

\ undef 
undef 

Однако as ikegami pointed out, он будет доступен только для чтения, потому что это не является переменной. LeoNerd provides a better approach for this in his answer.


Во всяком случае, моя точка, пустой хэш ссылок и пустой массив ссылок, когда разыменовываются оба содержат пустой список (). И это не undef но ничего. Но нет ничего как скалярное значение, потому что все, что есть не ничего - скалярное значение.

my $a = []; 

say ref $r;  # ARRAY 
say scalar @$r; # 0 
say "'@$r'"; # '' 

Так что нет никакого реального способа инициализации с ничего. Вы можете только не инициализировать. Но Moose превратит его в undef в любом случае.

Что вы можете сделать, это сделать его Возможно скаляр ref.

use strict; 
use warnings; 
use Data::Printer; 

{ 
    package Foo; 
    use Moose; 

    has bar => ( 
     is => 'rw', 
     isa => 'Maybe[ScalarRef]', 
     predicate => 'has_bar' 
    ); 
} 

my $foo = Foo->new; 

p $foo->has_bar; 
p $foo; 

say $foo->bar; 

Выход:

"" 

Foo { 
    Parents  Moose::Object 
    public methods (3) : bar, has_bar, meta 
    private methods (0) 
    internals: {} 
} 
Use of uninitialized value in say at scratch.pl line 268. 

predicate дает значение, которое не верно (пустая строка ""). undef также не соответствует действительности. Люди, которые заставили Муса решили пойти с этим, но это действительно не имеет значения.

Возможно, что вы хотите, не имеет значения по умолчанию, а просто сделайте его ScalarRef a required.


Обратите внимание, что perlref ничего об инициализации пустого скалярного рефа либо не говорит.

+1

Это определяет пустой скаляр, который я могу создать ссылку, но как я могу определить его анонимно? – tjwrona1992

+0

Зачем вам это нужно? Скалярный ref является скаляром. – Sobrique

+0

Я создаю объект 'Moose', который имеет атрибут типа« ScalarRef », и я хочу определить для него значение по умолчанию. – tjwrona1992

2

Я не совсем уверен, почему вам нужно, но я хотел бы предложить:

my $ref = \undef; 
print ref $ref; 

Или возможно:

my $ref = \0; 
+0

Спасибо, что работает :) – tjwrona1992

+2

Создают ссылки на скаляры только для чтения. – ikegami

7

Если вы хотите ссылку на какой-то изменяемым хранения, нет особенно аккуратный прямой синтаксис для него. О лучшем случае вы можете управлять является

my $var; 
my $sref = \$var; 

Или аккуратнее

my $sref = \my $var; 

Или, если вы не хотите, сама переменная находиться в области видимости больше, вы можете использовать делать блок:

my $sref = do { \my $tmp }; 

На этом этапе вы можете пройти $sref по значению, а любые мутации к скаляру, на которые ссылаются, будут видны другими.

Этот метод, конечно, работает так же хорошо для массива или хеш-ссылок, только что есть аккуратнее синтаксис делать это с [] и {}:

my $aref = do { \my @tmp }; ## same as my $aref = []; 

my $href = do { \my %tmp }; ## same as my $href = {};