Perl: и дают ли результаты разные ответы? - PullRequest
1 голос
/ 24 января 2011

У меня есть файл со следующими утверждениями:

    {
        %{do '/tmp/personcontact.pl'},
        %{do '/tmp/address.pl'}
    }

Теперь временные файлы выглядят следующим образом: Personcontact.pl:

            {
        'firstname' => {
            '__type' => 'String'
            },
        'lastname' =>  {
            '__type' => 'String'
            }
    }

Address.pl:

     {
        'address' => {
            'street' => {
                '__type' => 'String'
                },
            'unit' => {
                '__type' => 'String',
            },
            'suburb' => {
                '__type' => 'String'
            },
            '__type' => 'HASH'
        }
    }

Теперь, когда я это сделаю:

    open(SCHEMAFILE, "<", $schema) or return undef; 
my $schemafile;     
while(my $line = <SCHEMAFILE>) { $schemafile .= $line;}
my $tempref = eval $schemafile;
print Dumper $tempref;

Результат $VAR1 = '1/8'

И когда я это сделаю:

    print Dumper do "/tmp/schemawithinschema.pl";

Результат

                    $VAR1 = 'firstname';
        $VAR2 = {
            '__type' => 'String'
            };
        $VAR3 = 'address';
        $VAR4 = {
            'suburb' => {
                    '__type' => 'String'
                },
            'unit' => {
                '__type' => 'String'
                },
            'street' => {
                    '__type' => 'String'
                },
            '__type' => 'ARRAY'
            };
        $VAR5 = 'lastname';
        $VAR6 = {
            '__type' => 'String'
            };

Что здесь не так? Спасибо!

Ответы [ 3 ]

9 голосов
/ 24 января 2011

Хорошо, чтобы не навсегда это сохранить, вот решение на основе модулей для вас:

Foo.pm:

package Foo;

use strict;
use warnings;

BEGIN {
    require Exporter;
    our @ISA = qw( Exporter );
    our @EXPORT_OK = qw( get_person get_address get_all );
    our $VERSION = '0.01';
}

my %person = (
    firstname => {
        __type => 'String',
    },
    lastname => {
        __type => 'String',
    },
);

my %address = (
    address => {
        street => {
            __type => 'String',
        },
        unit => {
            __type => 'String',
        },
        suburb => {
            __type => 'String',
        },
        __type => 'HASH',
    },
);

sub get_person
{
    return \%person;
}

sub get_address
{
    return \%address;
}

sub get_all
{
    return( { %person, %address } );
}

1;

__END__

bar.pl:

#!/usr/bin/perl

use Data::Dumper;
use strict;
use warnings;
use lib '.';
use Foo qw( get_person get_address get_all );

my $junk = get_all();

print Dumper $junk;

Но на самом деле , ради вашего программиста по обслуживанию (часто вы сами через 6 месяцев), используйте JSON или YAML (или быстрее YAML :: XS ), так что данные могут поддерживаться в виде простого текстового файла, а не серии вложенных ссылок на данные, замаскированные под код.

Цитировать Perl Best Practices (не уверен, изначально ли это был Дамиан):

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


РЕДАКТИРОВАТЬ : Для полноты вот эквивалентное решение с использованием YAML (из CPAN):

data.yml:

---
firstname:
  __type: String
lastname:
  __type: String
address:
  __type: HASH
  street:
    __type: String
  suburb:
    __type: String
  unit:
    __type: String

baz.pl:

#!/usr/bin/perl

use YAML qw( Load Dump LoadFile DumpFile );
use Data::Dumper;
use strict;
use warnings;

my $data = LoadFile( 'data.yml' );
print Dumper $data;
5 голосов
/ 25 января 2011

Хотя смысл вопроса заставляет меня плакать, разница между вашими двумя фрагментами кода не имеет ничего общего с do или eval и не имеет никакого отношения к контексту.И поскольку это законная тема Perl, я кратко на нее отвечу.

В

my $tempref = eval $schemafile;

, eval происходит в скалярном контексте (навязывается присваиванием $tempref).Однако $schemafile содержит хэш, созданный оператором разыменования ссылки на хэш %{}.Когда этот хэш оценивается как скаляр, он создает 1/8, нормальное поведение для хеша.

В

print Dumper do "/tmp/schemawithinschema.pl";

, do происходит в контексте списка, наложенногоDumper вызов (который в свою очередь находится в контексте списка print).do создает тот же хеш, что и eval, но теперь он оценивается в контексте списка, фактически как список аргументов Dumper.Хэш верхнего уровня сведен в список из Label => HashRef пар, но этого недостаточно, чтобы Dumper не смог показать вам нечто, очень похожее на хэш, который вы пытались создать.

Для справки в будущем, когда вы пытаетесь определить странную разницу в поведении, полезно представить один и тот же вызов в обоих случаях.Чем больше переменных между двумя тестовыми примерами, тем больше вещей, которые вы не ожидали иметь значения, в конечном итоге будут иметь значение и сбить вас с толку.

Все это говорит о реальном ответе на вопрос "Что здесь не так?"остается «Попытка сделать это вообще».

4 голосов
/ 24 января 2011

Один маленький указатель.Это «1/8» - это то, что вы получаете, когда оцениваете хеш в скалярном контексте.8 - это количество сегментов, назначенных хешу, а 1 - количество используемых сегментов.

Обычно это бесполезно, кроме как признак того, что вы делаете что-то не так.

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