Подтвердить что ты не робот

Как я могу исключить объект в Perl?

От perldoc -f bless:

bless REF,CLASSNAME

Эта функция сообщает thingy, на которую ссылается REF, что теперь она         объект в пакете CLASSNAME.

Есть ли какой-либо способ получить безболезненную структуру без ненужного копирования?

4b9b3361

Ответ 1

Data::Structure::Util

unbless($ref)

Удалите благословение от любых объектов, найденных в переданной структуре данных.

#!/usr/bin/perl

use strict; use warnings;

use Scalar::Util qw( refaddr );
use Data::Structure::Util qw( unbless );

my $x = bless { a => 1, b => 2 } => 'My';

printf "%s : %s\n", ref $x, refaddr $x;

unbless $x;

printf "%s : %s\n", ref $x, refaddr $x;

Вывод:

My : 237356
HASH : 237356

Ответ 2

Data:: Structure:: Util имеет функцию unbless, которая сделает это за вас. Как отмечает Эрик, JSON::XS обычно не принимает благословенные ссылки (хотя я бы хотел, чтобы это просто проигнорировало это и касалось структуры данных), В этом случае нет никакого пути.

Но подумайте, почему вы считаете, что вам нужно его беспуть. Вы делаете это для одного из своих классов или другого класса? Это звучит подозрительно, как The Wrong Thing To Do. Возможно, лучший способ.

У вас такая же проблема, как и разрыв инкапсуляции, потому что вы должны предположить, что знаете, что такое внутренняя структура ссылки. Если вы собираетесь это сделать, вы можете просто игнорировать объектно-ориентированные вещи и напрямую обращаться к структуре.

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

Вы упомянули в последующем комментарии, что вы можете сделать это, чтобы обойти некоторые действия с шаблоном Toolkit. У меня была эта ситуация двумя способами в зависимости от ситуации:

  • Передавайте только те данные, которые вам нужны, вместо всего объекта.
  • Добавьте методы к объекту, чтобы получить нужные данные в шаблоне.

Perl - это DWIM, но TT - это даже DWIMmier, что иногда бывает неудачным.


Вот быстрый хак, где я определяю TO_JSON в UNIVERSAL, поэтому он применим ко всем объектам. Он делает глубокую копию, не разбивает ее и возвращает структуру данных.

#!perl
use v5.10;

sub UNIVERSAL::TO_JSON {
    my( $self ) = shift;

    use Storable qw(dclone);
    use Data::Structure::Util qw(unbless);

    my $clone = unbless( dclone( $self ) );

    $clone;
    }

my $data = bless {
    foo => bless( [], 'Local::Array' ),
    quack => bless( {
        map { $_ => bless [$_, $_**2], 'Local::Array' } 
            grep { is_prime } 1 .. 10
        }, 'Local::Hash' ),
    }, 'Local::Hash';

use JSON::XS;
my $jsonner = JSON::XS->new->pretty->convert_blessed(1);
say $jsonner->encode( $data );

Ответ 3

Если вы знаете, что поддерживает ваш объект, вы можете сделать это без использования пакетов.

Хэш

$obj = bless {}, 'Obj';
print ref $obj, "\n";
$obj = { %$obj };
print ref $obj, "\n";

Массив

$obj = bless [], 'Obj';
print ref $obj , "\n";
$obj = [ @$obj ];
print ref $obj, "\n";

Скалярное

$obj = bless \$a, "Obj";
print ref $obj, "\n";
$obj = \${ $$obj };
print ref $obj, "\n";

Ответ 4

Acme::Curse:)

Обновление: Спасибо, Иван! Я перепутал модули. На самом деле я хотел дать ссылку на Acme::Damn:))

Р. S. См. Также Acme::Sneeze:)

Р. P. S. Он не имеет реального использования, поэтому он Acme::. См. Сообщение Брайана.