6

G'Day、

私は現在、多くの小さなハッシュから大きなハッシュを作成することに取り組んでいます。これらの小さなハッシュがそれぞれファイルで定義され、大きなハッシュに含めることができるとしましょう。

たとえば、いくつかの小さなハッシュを見てみましょう

ファイルpersoncontact.pl

   return {
            \'firstname\' => {
                \'__type\' => \'String\'
            },
        \'lastname\' =>  {
            \'__type\' => \'String\'
            },
        %{include("/tmp/address.pl")}
    }

ファイルaddress.pl

return {
        \'address\' => {
        \'street\' => {
            \'__type\' => \'String\'
            },
        \'unit\' => {
            \'__type\' => \'String\',
            \'__validation_function\' => {
                \'is_a_number\' => \'\'
            },
            \'__schema_constraints\' => {
                \'is_not_null\' => \'\'
            }
        },
        \'suburb\' => {
            \'__type\' => \'String\'
        },
        \'__type\' => \'ARRAY\'
        }
    } 

そして、私はこれらのかなりの数を持っています...

ハッシュを再作成しようとしている方法はinclude、次のようなサブルーチンを使用することです。

 sub include {
my ($filename) = @_;
my $file; 
open(my $fh, "<", $filename) or die ("FILEOPEN: $!");
while(my $line = <$fh>) { $file .= $line; }
my $result = eval $file;
die("EVAL: $@") if $@;
close($fh) or die("FILECLOSE: $!");
return $result;
 }

私は何か間違ったことをしているに違いないことは知っていますが、何が起こっているのかわかりません。Useless use of a variable in void context at (eval 11) line 4, <SCHEMAFILE> line 6またはのようなエラーが発生し続けOdd number of elements in anonymous hash at (eval 11) line 5, <SCHEMAFILE> line 6ます。(eval 11)4-3行目、6行目を見つける方法がわかりません。Perlデバッガーの使用に関する提案や、私が間違っている可能性のある場所に関する指針をいただければ幸いです。

ありがとう!

4

1 に答える 1

11

パールへようこそ。楽しく学んで使っていただければ幸いです。

ビジネスを開始するには、どこから始めますか? ここで言いたいことがたくさんあります。

まず、ファイルを評価してデータをロードすることは、不必要に危険です。データをシリアライズしたいだけなら、JSON::XSまたはYAML、あるいはStorableを試してください。構成ファイルが必要な場合は、CPAN にこのタスクを支援する非常に多くのモジュールがあります。Config::Anyを確認してください。

eval を介してロードするデータ構造を作成したい場合 (これはあまり良い考えではありません)、Data::Dumperは、フィードするデータ構造を作成するために必要な perl コードを生成します。私が言及した主な理由は、シリアライザーよりもデバッグ支援としてはるかに便利だからです。

ファイルを読み込んで評価したい場合 (ほとんどの場合、最善の方法ではありません)、doまたはrequireを参照する必要あります。

my $stuff = do 'address.pl';

しかし、そうしないでください。文字列evalは、通常は使用しないでおくのが最善のツールです。99% の確率で、string eval の使用を計画している場合は、停止して問題を解決する別の方法を考えてください。Do は暗黙の eval であるため、これもカウントされます。

Perl には、危険で強力な魔法を行うためのツールがたくさんあります。熟練した Perl プログラミングになるための大部分は、何が危険で、なぜ、いつそれらを使用するのが理にかなっているのかを理解することにあります。Perl があなたを安全に保つためにフェンスやゲートを用意してくれると期待しないでください。真剣に、 Effective Perl ProgrammingまたはPerl Best Practicesのコピーを入手することを検討してください。初心者として、初めて読むときは多くのことが頭を悩ませますが、成長して学習するにつれて、どちらの本も優れたリファレンスになる可能性があります。

次のトピックでは、エスケープされたすべての引用符を使用して、いったい何を達成しようとしているのでしょうか? そういうの見ると頭が痛くなる!Perl には、リテラル文字列で引用符をエスケープする手間を省くために使用できる、非常に優れた引用演算子があります。

または太いコンマは=>、英数字のみであるかのように、左側 (LHS) を自動的に引用します。しかし、すべての引用符とエスケープを入れると、物事は本当に危険になります.

と言うと\'address\' => {}、Perl はこれ\を、文字列リテラルに適用された「参照の取得」演算子として認識します。'この場合、最初の後にエスケープされていないものを提供しないため、終了していない文字列リテラルです。

、引用符、およびすべてをハッシュキーとして使用することが目的の場合は'address'、次のようにすることができます。

my %foo = ( "'address'" => 'blah' );

はるかに一般的な使用例と思われる引用符が必要ない場合は、次のようにします。

my %foo = ( address => 'blah' );

あなたが得ていたエラーメッセージに!Perl には、それらの意味を理解すれば、非常に優れたエラー メッセージがいくつかあります。それまでは、その重要性を理解するのは少し難しいかもしれません。幸いなことに、Perl には というスクリプトが付属していますsplain。これは、エラー メッセージをより詳細に説明する便利で便利なツールです。診断モジュールを使用して、同じ拡張エラー メッセージを自動的に取得することもできます。

今、私がこれを書いていたら、次の行に沿って何かをします:

gen_schema_files.pl - JSON スキーマ ファイルを書き込むためのファイル。必要に応じて、スキーマを手動で編集できます。読みやすさを向上させたい場合は、出力をよりきれいに構成することもできます。

#!/usr/bin/perl

use JSON::XS;
use File::Spec;

use constant BASEDIR => '.';

# Key is the file name, value is the data to put into the file.
my %schemata = (
    'address.json' => {
        address => {
            street => { __type => 'String' },
            unit => {
                __type => 'String',
                __validation_function => { is_a_number => '' },
                __schema_constraints  => { is_not_null => ''  }
            },
            suburb => { __type => 'String' },
            __type => 'ARRAY'
        },
    },

    'person_contact.json' => {
         firstname => { __type => 'String' },
         lastname =>  { __type => 'String' },

         # Use a special key to indicate that additional files should be 
         # loaded into this hash.
         INCLUDE  => [qw( address.json )], 
     },

     # And so forth
);

for my $schema ( keys %schemata ) {
    my $path = File::Spec->catfile( BASEDIR, $schema );

    open my $fh, '>', $path
        or die "Error opening '$path' for writing - $!\n";

    print $fh encode_json $schemata{$schema};
}

load_schemas.pl - これは、スキーマをロードして処理を行うコードです。私のはロードされるだけです。データで何をしているのかわかりません...

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

use JSON::XS;
use File::Spec;

use constant BASEDIR => '.';


my $schema = load_schema( 'person_contact.json' );

print Dumper $schema;


sub load_schema {
    my $file = shift;

    my $path = File::Spec->catfile( BASEDIR, $file );

    open my $fh, '<', $path
        or die "Error opening file '$path' - $!\n";

    my $json = join '', <$fh>; # reads a list of lines and cats them into one string.
                               # One way to slurp out of many.

    my $schema = decode_json( $json );

    # Handle the inclusion stuff:

    if( exists $schema->{INCLUDE} ) {
        # Copy the files to load into an array.
        my @loadme = @{$schema->{INCLUDE}};
        # delete the magic special include key.
        delete $schema->{INCLUDE};

        # Load each file and copy it into the schema hash.
        for my $load ( @loadme ) {
            my $loaded = load_schema( $load );

            # This is a bit of weird syntax.
            # We are using a hash slice assignment to copy the loaded data into the existing hash.
            # keys and values are guaranteed to come out in the same (random) order as each other.
            # the @{$foo}{blahbhal} is how you dereference a hash reference as a slice.
            @{$schema}{keys %$loaded} = values %$loaded;
        }
    }

    return $schema;
}

いくつかのことをざっと説明しましたが、有益な検索ができるように、十分な用語 (必要に応じて語彙または専門用語) をコメントに残そうとしました。

上記のコードにはいくつかの欠陥があります。循環的な包含のチェックは行いません (長時間実行され、最終的にメモリがいっぱいになり、クラッシュします。あまり良くありません)。魔法の鍵の選択が良くないかもしれません。そして、おそらく私がまだ考えていないこともあるでしょう。

Perldoc は素晴らしいリソースですが、あまりにも多くのリソースがあるため、何かを見つけるのに時間がかかります。Perl Data Structures CookbookArrays of Arrays チュートリアルをご覧ください。初心者として、 perlfunc のカテゴリ別の Perl 関数セクションが非常に役立つことがわかりました。

普通の人を盲目にするのに十分なテキストを書いたので、やめようと思います。この論文がお役に立てば幸いです。ようこそ、もう一度、こんばんは (この応答を見つけたら、現地時間に合わせて調整してください)。

于 2011-01-24T06:14:08.390 に答える