9

私は、引数が渡されていない場合と、引数が0として渡されている場合を、Perlで区別するための最良の方法を見つけようとしています。なぜなら、それらは私にとって異なることを意味するからです。

(通常、あいまいさが好きですが、この場合はSQLを生成しているので、未定義の引数をNULLに置き換えたいのですが、0は0のままにしておきます。)

したがって、これはあいまいさです。

sub mysub {
  my $arg1 = shift;
  if ($arg1){
    print "arg1 could have been 0 or it could have not been passed.";
  }
}

そしてこれまでのところ、これが私の最善の解決策です...しかし、それは少し醜いと思います。あなたがよりクリーンな方法を考えることができるかどうか、またはこれがあなたにとって大丈夫に見えるかどうか疑問に思っています:

sub mysub {
  my $arg1 = (defined shift) || "NULL";
  if ($arg1 ne "NULL"){
    print "arg1 came in as a defined value.";
  }
  else {
    print "arg1 came in as an undefined value (or we were passed the string 'NULL')";
  }
}
4

5 に答える 5

17

考えられるすべてのケースを処理する方法の例を次に示します。

sub mysub {
    my ($arg1) = @_;
    if (@_ < 1) {
        print "arg1 wasn't passed at all.\n";
    } elsif (!defined $arg1) {
        print "arg1 was passed as undef.\n";
    } elsif (!$arg1) {
        print "arg1 was passed as a defined but false value (empty string or 0)\n";
    } else {
        print "arg1 is a defined, non-false value: $arg1\n";
    }
}

@_は関数の引数の配列です。ここと比較すると1、配列内の要素の数がカウントされます。shift変更されるため、元のサイズをどこか@_に保存する必要があるため、意図的に回避しています。)@_

于 2011-11-28T17:28:00.287 に答える
3

どうですか:

sub mysub {
    my ( $arg ) = @_;

    if ( @_ == 0 ) {
        print "arg did not come in at all\n";
    } elsif ( defined $arg ) {
        print "arg came in as a defined value.\n";
    } else {
        print "arg came in as an undefined value\n";
    }
}

mysub ();
mysub ( undef );
mysub ( 1 );

更新:何かが渡されたかどうかのチェックを追加しました。ただし、これは、単一のパラメーターを期待している場合にのみ役立ちます。複数のパラメーターを取得したい場合で、未定義のパラメーターと省略されたパラメーターを区別する必要がある場合は、ハッシュを使用してください。

sub mysub_with_multiple_params {
    my %args_hash = @_;

    for my $expected_arg ( qw( one two ) ) {
        if ( exists $args_hash{ $expected_arg } ) {
            if ( defined $args_hash{ $expected_arg } ) {
                print "arg '$expected_arg' came in as '$args_hash{ $expected_arg }'\n";
            } else {
                print "arg '$expected_arg' came in as undefined value\n";
            }
        } else {
            print "arg '$expected_arg' did not come in at all\n";
        }
    }
}

mysub_with_multiple_params ();
mysub_with_multiple_params ( 'one' => undef, 'two' => undef );
mysub_with_multiple_params ( 'one' => 1, 'two' => 2 );

そしてところで:パラメータをサニタイズするために何らかの手順を実行する必要がある場合は、自分で実行しないでください。cpan、特にParams::Validateをご覧ください

于 2011-11-28T17:27:58.337 に答える
1

確認する唯一の方法は、の長さを調べて@_、そのスロットに引数があったかどうかを確認することです。必須の引数もある場合、これは少し複雑に見えるかもしれませんが、そうである必要はありません。多くのオブジェクトアクセサで使用されるパターンは次のとおりです。

package Foo;

sub undef_or_unset {
    my ($self, @arg) = @_;

    return 'unset' unless @arg;
    my ($val) = @arg;

    return 'undef' unless defined $val;
    return 'defined';
}

package main;
use Test::More tests => 3;

my $foo = bless {} => 'Foo';

is($foo->undef_or_unset(), 'unset');
is($foo->undef_or_unset(undef), 'undef');
is($foo->undef_or_unset('bluh'), 'defined');
于 2013-01-29T17:20:41.483 に答える
1

個人的には、NULLを表現し続けるのが好きですundef。これは、DBIプレースホルダー/ DBIx :: Class / SQL :: Abstractのすべての機能と一致します。文字列に設定する場合のリスクは、文字列自体"NULL"ではなく、誤って文字列を挿入することです。NULL

最近のバージョンのPerl(5.10以降)を使用している場合は、「defined-or」演算子//を確認してください//=。これは、引数の処理に特に便利です。

SQLに関しては、SQL文字列を生成する場合は、次のようになります。

sub mysub {
  my ($args) = @_;
  my @fields = qw/ field1 field2 field3 /;
  my $sql = "INSERT INTO mytable (field1,field2,field3) VALUES (" .
   join(',', map { ("'".$args->{$_}."'") // 'NULL' ) } )
    .")";
  return $sql;
}

編集(NULLとundefに関するビットに答えるため):

プレースホルダーでのDBIハンドルの使用:

my $sth = $dbh->prepare('INSERT INTO mytable (field1,field2,field3) '.
                        'VALUES (?,?,?)');

# undef will set a NULL value for field3 here:
$sth->execute( "VAL1", "VAL2", undef );

DBIx :: Class

DBIx :: Class-同じ原則-undef値を渡してNULL、データベースにを作成します。

my $rs = My::Schema->resultset('MyTable');
my $obj = $rs->create({
   field1 => 'VAL1',
   field2 => 'VAL2',
   field3 => undef,    # will set a `NULL` value for field3 here
});
于 2011-11-28T17:57:47.173 に答える
0

地図はあなたの友達です。これを試して:

function("joe",undef); # should print "joe" and "NULL"
function("max",38);    # should print "max" and "38"
function("sue",0);     # should print "sue" and "0"   

sub function {
    my($person,$age) = map { $_ // "NULL" } @_;
    print "person: $person\n";
    print "age:    $age\n";
}

もう少し色を追加するために、コードを明確にするための引数としてハッシュを使用し、arugmentの順序を覚えておくことの重要性を取り除くことが好きになりました。したがって、書き直すと次のようになります。

function2(person=>"joe",age=>undef); # should print "joe" and "NULL"
function2(person=>"max",age=>38);    # should print "max" and "38"

sub function2 {
    my(%args) = map { $_ // "NULL" } @_;
    print "person: $args{person}\n";
    print "age:    $args{age}\n";
}

(更新:0を正しく処理してから、//演算子を使用するようになりました。)

于 2011-11-28T17:33:25.007 に答える