Perl Perl_1
Perl 「 論理演算子 」論理 OR を利用したデフォルト値の設定とその問題点 (0x8c)

目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その 0x8c 回。
Perl の論理演算子 ( logical operator ) の論理和 OR ( || ) の短絡を利用したデフォルト値の設定とその問題点について。
論理和 OR によるデフォルト値の設定
前回の「 Perl 「 論理演算子 」短絡演算子の値 (0x8b) 」では、論理演算が返す値と短絡の動作を利用して、ユーザのホームディレクトリを設定する方法を確認しました。
論理和 OR ( || ) を使えば、要するに、変数に対してデフォルトの値を設定出来るという訳ですが、問題点もあります。
問題点
「初めての Perl 第 6 版」の P.229 には次の様な例と、その問題点が提示されています。
my $last_name = $last_name{$someone} || '(No last name)';
この例では、もしハッシュ変数 %last_name に $someone のラストネームが登録されていれば $last_name{$someone} の値を $last_name に代入します。
もし登録がなければリテラルな「 (No last name) 」の文字列を $last_name に代入します。
通常ハッシュに登録がない場合は「 undef 」が返されるはずなので、このケースでは特に問題がない様に思えますが、ひとつ注意しなければならいことがあります。
それは、論理和 OR の「 || 」演算子は、対象が「 undef 」でない場合でも 偽 を返すということです。
例えば、ハッシュの value が数値の「 0 」だった場合です。論理演算子は、数値「 0 」が正しい値だったとしても、 偽 として評価します。
この問題は、数値「 0 」に限りません。論理演算子では、真 ではないあらゆる値 ( 例えば空文字等 ) が同様の問題を引き起こします。
問題の解決方法
つまり、前項で紹介したデフォルト値の設定方法は、問題を孕んだポンコツコードなのです。
こうした 真偽 値の問題を解消するには「 Perl 「 条件演算子 」?: (0x88) 」で確認した「 条件演算子 」と、「 Perl 「 defined 関数 」で undef を検知する (0x1a) 」で確認した「 defined 」関数を利用します。
「 defined 」関数は、対象の値が純粋な「 undef 」だった場合にのみ 偽 を返します。つまり、それが数値「 0 」や空文字だったとしても 真 を返します。
条件演算子「 ?: 」は、if then else 文の様に働く三項演算子です。
これらを利用して先のコードを修正すると次の様になります。
my $last_name = defined $last_name{$someone} ? $last_name{$someone} : '(No last name)';
処理内容は先のコードと同じですが、$last_name{$someone} に対するテスト方法が違いになっています。
デフォルト値を設定する Tips
ここまでで紹介したデフォルト値を設定する方法を利用すると、例えば未定義値を出力する場合に表示される「 Use of uninitialized value in ... 」の警告文を抑制することが出来ます。
printf "%s", defined $value ? $value : '';
この様に対象が未定義だった場合は、空文字を代わりに利用します。こうすることで warnings プラグマを利用しているプログラムの実行時に不要な警告を抑制出来るわけです。
僕は今、ある多量の情報を一括で処理をするための Perl プログラムを書いていますが、不要な警告文を抑制したいとちょうど悩んでいたところなので、とてもタイムリーな復習になりました。良かったです。
0x8c -> 0x8d へ
もしあなたが、Perl 5.10 以上をお使いであれば、「 defined-or 」演算子の利用が可能です。記号には「 // 」を使います。とてもスマートな演算子です。
詳しくは perl5100delta - perldoc.jp "Defined-or 演算子" の項目を確認してください。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
前回の「 Perl 「 論理演算子 」短絡演算子の値 (0x8b) 」では、論理演算が返す値と短絡の動作を利用して、ユーザのホームディレクトリを設定する方法を確認しました。
論理和 OR ( || ) を使えば、要するに、変数に対してデフォルトの値を設定出来るという訳ですが、問題点もあります。
問題点
「初めての Perl 第 6 版」の P.229 には次の様な例と、その問題点が提示されています。
my $last_name = $last_name{$someone} || '(No last name)';
この例では、もしハッシュ変数 %last_name に $someone のラストネームが登録されていれば $last_name{$someone} の値を $last_name に代入します。
もし登録がなければリテラルな「 (No last name) 」の文字列を $last_name に代入します。
通常ハッシュに登録がない場合は「 undef 」が返されるはずなので、このケースでは特に問題がない様に思えますが、ひとつ注意しなければならいことがあります。
それは、論理和 OR の「 || 」演算子は、対象が「 undef 」でない場合でも 偽 を返すということです。
例えば、ハッシュの value が数値の「 0 」だった場合です。論理演算子は、数値「 0 」が正しい値だったとしても、 偽 として評価します。
この問題は、数値「 0 」に限りません。論理演算子では、真 ではないあらゆる値 ( 例えば空文字等 ) が同様の問題を引き起こします。
問題の解決方法
つまり、前項で紹介したデフォルト値の設定方法は、問題を孕んだポンコツコードなのです。
こうした 真偽 値の問題を解消するには「 Perl 「 条件演算子 」?: (0x88) 」で確認した「 条件演算子 」と、「 Perl 「 defined 関数 」で undef を検知する (0x1a) 」で確認した「 defined 」関数を利用します。
「 defined 」関数は、対象の値が純粋な「 undef 」だった場合にのみ 偽 を返します。つまり、それが数値「 0 」や空文字だったとしても 真 を返します。
条件演算子「 ?: 」は、if then else 文の様に働く三項演算子です。
これらを利用して先のコードを修正すると次の様になります。
my $last_name = defined $last_name{$someone} ? $last_name{$someone} : '(No last name)';
処理内容は先のコードと同じですが、$last_name{$someone} に対するテスト方法が違いになっています。
デフォルト値を設定する Tips
ここまでで紹介したデフォルト値を設定する方法を利用すると、例えば未定義値を出力する場合に表示される「 Use of uninitialized value in ... 」の警告文を抑制することが出来ます。
printf "%s", defined $value ? $value : '';
この様に対象が未定義だった場合は、空文字を代わりに利用します。こうすることで warnings プラグマを利用しているプログラムの実行時に不要な警告を抑制出来るわけです。
僕は今、ある多量の情報を一括で処理をするための Perl プログラムを書いていますが、不要な警告文を抑制したいとちょうど悩んでいたところなので、とてもタイムリーな復習になりました。良かったです。
0x8c -> 0x8d へ
もしあなたが、Perl 5.10 以上をお使いであれば、「 defined-or 」演算子の利用が可能です。記号には「 // 」を使います。とてもスマートな演算子です。
詳しくは perl5100delta - perldoc.jp "Defined-or 演算子" の項目を確認してください。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
「初めての Perl 第 6 版」の P.229 には次の様な例と、その問題点が提示されています。
my $last_name = $last_name{$someone} || '(No last name)';
この例では、もしハッシュ変数 %last_name に $someone のラストネームが登録されていれば $last_name{$someone} の値を $last_name に代入します。
もし登録がなければリテラルな「 (No last name) 」の文字列を $last_name に代入します。
通常ハッシュに登録がない場合は「 undef 」が返されるはずなので、このケースでは特に問題がない様に思えますが、ひとつ注意しなければならいことがあります。
それは、論理和 OR の「 || 」演算子は、対象が「 undef 」でない場合でも 偽 を返すということです。
例えば、ハッシュの value が数値の「 0 」だった場合です。論理演算子は、数値「 0 」が正しい値だったとしても、 偽 として評価します。
この問題は、数値「 0 」に限りません。論理演算子では、真 ではないあらゆる値 ( 例えば空文字等 ) が同様の問題を引き起こします。
問題の解決方法
つまり、前項で紹介したデフォルト値の設定方法は、問題を孕んだポンコツコードなのです。
こうした 真偽 値の問題を解消するには「 Perl 「 条件演算子 」?: (0x88) 」で確認した「 条件演算子 」と、「 Perl 「 defined 関数 」で undef を検知する (0x1a) 」で確認した「 defined 」関数を利用します。
「 defined 」関数は、対象の値が純粋な「 undef 」だった場合にのみ 偽 を返します。つまり、それが数値「 0 」や空文字だったとしても 真 を返します。
条件演算子「 ?: 」は、if then else 文の様に働く三項演算子です。
これらを利用して先のコードを修正すると次の様になります。
my $last_name = defined $last_name{$someone} ? $last_name{$someone} : '(No last name)';
処理内容は先のコードと同じですが、$last_name{$someone} に対するテスト方法が違いになっています。
デフォルト値を設定する Tips
ここまでで紹介したデフォルト値を設定する方法を利用すると、例えば未定義値を出力する場合に表示される「 Use of uninitialized value in ... 」の警告文を抑制することが出来ます。
printf "%s", defined $value ? $value : '';
この様に対象が未定義だった場合は、空文字を代わりに利用します。こうすることで warnings プラグマを利用しているプログラムの実行時に不要な警告を抑制出来るわけです。
僕は今、ある多量の情報を一括で処理をするための Perl プログラムを書いていますが、不要な警告文を抑制したいとちょうど悩んでいたところなので、とてもタイムリーな復習になりました。良かったです。
0x8c -> 0x8d へ
もしあなたが、Perl 5.10 以上をお使いであれば、「 defined-or 」演算子の利用が可能です。記号には「 // 」を使います。とてもスマートな演算子です。
詳しくは perl5100delta - perldoc.jp "Defined-or 演算子" の項目を確認してください。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
つまり、前項で紹介したデフォルト値の設定方法は、問題を孕んだポンコツコードなのです。
こうした 真偽 値の問題を解消するには「 Perl 「 条件演算子 」?: (0x88) 」で確認した「 条件演算子 」と、「 Perl 「 defined 関数 」で undef を検知する (0x1a) 」で確認した「 defined 」関数を利用します。
「 defined 」関数は、対象の値が純粋な「 undef 」だった場合にのみ 偽 を返します。つまり、それが数値「 0 」や空文字だったとしても 真 を返します。
条件演算子「 ?: 」は、if then else 文の様に働く三項演算子です。
これらを利用して先のコードを修正すると次の様になります。
my $last_name = defined $last_name{$someone} ? $last_name{$someone} : '(No last name)';
処理内容は先のコードと同じですが、$last_name{$someone} に対するテスト方法が違いになっています。
デフォルト値を設定する Tips
ここまでで紹介したデフォルト値を設定する方法を利用すると、例えば未定義値を出力する場合に表示される「 Use of uninitialized value in ... 」の警告文を抑制することが出来ます。
printf "%s", defined $value ? $value : '';
この様に対象が未定義だった場合は、空文字を代わりに利用します。こうすることで warnings プラグマを利用しているプログラムの実行時に不要な警告を抑制出来るわけです。
僕は今、ある多量の情報を一括で処理をするための Perl プログラムを書いていますが、不要な警告文を抑制したいとちょうど悩んでいたところなので、とてもタイムリーな復習になりました。良かったです。
0x8c -> 0x8d へ
もしあなたが、Perl 5.10 以上をお使いであれば、「 defined-or 」演算子の利用が可能です。記号には「 // 」を使います。とてもスマートな演算子です。
詳しくは perl5100delta - perldoc.jp "Defined-or 演算子" の項目を確認してください。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
ここまでで紹介したデフォルト値を設定する方法を利用すると、例えば未定義値を出力する場合に表示される「 Use of uninitialized value in ... 」の警告文を抑制することが出来ます。
printf "%s", defined $value ? $value : '';
この様に対象が未定義だった場合は、空文字を代わりに利用します。こうすることで warnings プラグマを利用しているプログラムの実行時に不要な警告を抑制出来るわけです。
僕は今、ある多量の情報を一括で処理をするための Perl プログラムを書いていますが、不要な警告文を抑制したいとちょうど悩んでいたところなので、とてもタイムリーな復習になりました。良かったです。
0x8c -> 0x8d へ
もしあなたが、Perl 5.10 以上をお使いであれば、「 defined-or 」演算子の利用が可能です。記号には「 // 」を使います。とてもスマートな演算子です。
詳しくは perl5100delta - perldoc.jp "Defined-or 演算子" の項目を確認してください。
参考情報は書籍「 初めての Perl 第 6 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)