2

map関数を使用している Perl プログラムで奇妙な構文エラーが発生しました。私には単純な回避策 (一見不必要な括弧を追加する) があるので、これは重要ではありませんが、Perl が元のコードで構文エラーを報告した理由、または括弧を追加することでエラーが修正された理由はわかりません。

1それぞれ「-」で始まる一連の短い文字列を値(基本的にはセット データ構造)にマップするハッシュを作成したかったのです。私の最初の試みはこれに似ていました:

my %hash = map { "-$_"  => 1 } qw(foo bar);

これは、次と同等であると思います。

my %hash = ( "-foo" => 1, "-bar" => 1 );

Perl が構文エラーを報告しました。"-$_"一重引用符または二重引用符で囲まれた文字列リテラルで置き換えると、構文エラーが発生します。に置き換える"-$_"("-$_")、構文エラーがなくなり、コードが正しく機能します。

Perl 5.10.1、5.16.2、および 5.20.0 でも同様の結果が得られます。

問題を示す自己完結型のスクリプトを次に示します (-関連性がないように思われるため、接頭辞を削除しました)。

#!/usr/bin/perl

use strict;
use warnings;

my %h0 = map {   $_   => 1 } qw(foo bar);  # ok
my %h1 = map { ("$_") => 1 } qw(foo bar);  # ok
my %h2 = map {  "$_"  => 1 } qw(foo bar);  # line 8, syntax error
my %h3 = map { 'FOO'  => 1 } qw(foo bar);  # line 9, syntax error
my %h4 = map { "FOO"  => 1 } qw(foo bar);  # line 10, syntax error

Perl 5.20.0 を使用して実行しようとしたときの出力:

syntax error at map-bug line 8, near "} qw(foo bar)"
syntax error at map-bug line 9, near "} qw(foo bar)"
syntax error at map-bug line 10, near "} qw(foo bar)"
Execution of map-bug aborted due to compilation errors.

(Perl 5.10.1 および 5.16.2 では、8 行目の「マップの引数が不足しています」というメッセージも表示されます。)

他の 2 行をコメント アウトした場合でも、3 つの構文エラーはそれぞれ個別に発生することを確認したので、9 行目と 10 行目は 8 行目からのカスケード エラーではありません。

これは Perl のバグですか、それとも Perl 構文の微妙なところが欠けているのでしょうか?

4

1 に答える 1

4

perldoc -f map:

{ハッシュ参照とブロックの両方を開始するためmap { ...、マップ BLOCK LIST またはマップ EXPR、LIST の開始のいずれかになります。Perl は終了を先に見ていないため}{. }通常は正しく処理されますが、そうでない場合は、 に到達して欠落した (または予期しない) コンマに遭遇するまで、何かが間違っていることに気付きません。構文エラーは の近くで報告されますが、単項またはセミコロンを使用して Perl に助けを与えるなど、}の近くで何かを変更する必要があります。{+

    %hash = map {  "\L$_" => 1  } @array # perl guesses EXPR. wrong
    %hash = map { +"\L$_" => 1  } @array # perl guesses BLOCK. right
    %hash = map {; "\L$_" => 1  } @array # this also works
    %hash = map { ("\L$_" => 1) } @array # as does this
    %hash = map {  lc($_) => 1  } @array # and this.
    %hash = map +( lc($_) => 1 ), @array # this is EXPR and works!

    %hash = map  ( lc($_), 1 ),   @array # evaluates to (1, @array)

または anon ハッシュ コンストラクターの使用を強制するには、次のようにし+{ます。

    @hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs
                                           # comma at end

それぞれが1つのエントリのみを持つ匿名ハッシュのリストを取得します。

于 2015-07-29T23:17:04.927 に答える