スキップしてメイン コンテンツに移動

Perl 5 to 6 - クォートと構文解析

これはMoritz Lenz氏のWebサイトPerlgeek.deで公開されているブログ記事"Perl 5 to 6" Lesson 23 - Quoting and Parsingの日本語訳です。

原文はCreative Commons Attribution 3.0 Germanyに基づいて公開されています。

本エントリにはCreative Commons Attribution 3.0 Unportedを適用します。

Original text: Copyright© 2008-2010 Moritz Lenz

Japanese translation: Copyright© 2011 SATOH Koichi

NAME

"Perl 5 to 6" Lesson 23 - クォートと構文解析

SYNOPSIS

my @animals = <dog cat tiger>
# or
my @animals = qw/dog cat tiger/;
# or 

my $interface = q{eth0};
my $ips = q :s :x /ifconfig $interface/;

# -----------

sub if {
    warn "if() calls a sub\n";
}
if();

DESCRIPTION

クォート

Perl6には強力な文字列クォート機構があり、文字列のあらゆる機能を完全に制御できます。

Perl5にはシングルクォート、ダブルクォートそしてqw(...)(空白で分割するシングルクォート文字列リスト)があり、さらにq(...)qq(...)がそれぞれシングルクォートとダブルクォートの同義語になっていました。

一方のPerl6にはQというクォート演算子が定義されていて、様々な修飾子を取ります。 :b(バックスラッシュ)修飾子はバックスラッシュによる\nのようなエスケープシーケンスの展開を許し、:s修飾子はスカラ変数の展開を許し、:cはクロージャ("1 + 2 = { 1 + 2 }")の展開を許す、などなど。また:wqw/.../が行うように単語を分割します。

これらの修飾子は自由に組み合わせることができます。例えばスカラだけ展開し、他は展開しないqw/.../を作りたくはないでしょうか。まったく問題在りません:

my $stuff = "honey";
my @list = Q :w :s/milk toast $stuff with\tfunny\nescapes/;
say @list[*-1];                     # with\nfunny\nescapesと表示

利用できる修飾子のリストを示します。これはS02からほとんどそのまま盗んできました。 これらはすべて長い名前も持ちますが、ここでは省略します。

機能
    :q          \\と\q及び\'を展開する
    :b          その他の\nや\tのようなエスケープシーケンスも展開する
演算
    :x          シェルコマンドとして実行し、結果を返す
    :w          空白で分割する
    :ww         同上。クォートで囲まれた部分は分割しない
文字列展開
    :s          スカラを展開する     ($stuff)
    :a          配列を展開する       (@stuff[])
    :h          ハッシュを展開する   (%stuff{})
    :f          関数を展開する       (&stuff())
その他
    :c          クロージャを展開する ({code})
    :qq         :s、:a、:h、:f、:c、:bを展開する
    :regex      正規表現として解釈する

簡単のためにいくつか短い形式があります:

q       Q:q
qq      Q:qq
m       Q:regex

修飾子が短い形式の場合、:も省略して1語として書くことができます:

シンボル     元の形
qw          q:w
Qw          Q:w
qx          q:x
Qc          Q:c
# などなど

ただし、Perl5プログラマが見落としそうな動作しない形式が1つあります: Perl6では小カッコを使ってqw(...)と書くことはできません。これはサブルーチンqwの呼び出しとして解釈されます。

構文解析

これが構文解析の起点です: すべてのidentifier(...)という形式はサブルーチン呼び出しとして解釈されます。そう、全部です。

if($x<3)

はサブルーチンifの呼び出しと解釈されます。空白を使って曖昧性を解消できます:

if ($x < 3) { say '<3' }

あるいは単にカッコを取り去って:

if $x < 3 { say '<3' }

これはつまりPerl6にはキーワードがないということです。正確に言えばuseとかifのようなキーワードがありますが、これらは特別の構文の中で使われたときだけ特別扱いされます。

MOTIVATION

クォート修飾子の様々な組み合わせは既に内部的に使われています。例えば<...>を解析するq:wm/.../を解析する:regexです。 これらをユーザにも解放して柔軟性を向上させ、使いたいクォートの省略記法を提供するマクロを簡単に書けるようにすることは道理にかなっています。

またキーワードの特別性を制限することで、「キーワード」の定義を書き換えたい時に後方互換性の問題を大幅に減らすことができます。

SEE ALSO

http://perlcabal.org/syn/S02.html#Literals

コメント

このブログの人気の投稿

Perl 5 to 6 - コンテキスト

2011-02-27: コメント欄で既に改訂された仕様の指摘がありました ので一部補足しました。 id:uasi に感謝します。 これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 06 - Contexts の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 06 - コンテキスト SYNOPSIS my @a = <a b c> my $x = @a; say $x[2]; # c say (~2).WHAT # Str() say +@a; # 3 if @a < 10 { say "short array"; } DESCRIPTION 次のように書いたとき、 $x = @a Perl5では $x は @a より少ない情報—— @a の要素数だけ——しか持ちません。 すべての情報を保存しておくためには明示的にリファレンスを取る必要があります: $x = \@a Perl6ではこれらは反対になります: デフォルトでは何も失うことなく、スカラ変数は配列を単に格納します。 これは一般要素コンテキスト(Perl5で scalar と呼ばれていたもの)及びより特化された数値、整数、文字列コンテキストの導入によって可能となりました。無効コンテキストとリストコンテキストは変更されていません。 特別な構文でコンテキストを強制できます。 構文 コンテキスト ~stuff 文字列 ?stuff 真理値 +stuff ...

Project Euler - Problem 27

問題 しばらく止まってましたが今日から再開。 原文 Considering quadratics of the form: n 2 + an + b, where |a| < 1000 and |b| < 1000 Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n = 0. 日本語訳 |a| < 1000, |b| < 1000 として以下の二次式を考える (ここで|a|は絶対値): n 2 + an + b n=0から始めて連続する整数で素数を生成したときに最長の長さとなる上の二次式の, 係数a, bの積を答えよ. 解答 最大探索範囲は-999 <= a <= 999、-999 <= b <= 999なので、およそ4,000,000通りの係数の組合せを試すことになります。組合せ毎に数列を生成して、それが素数か判定するわけですからたまりません。簡単な検討を加えて範囲を絞りましょう。 与えられた二次式をf(n)とおくと、f(0) = b、f(1) = a + b + 1です。 f(n)が長さ2以上の素数列を生成するならこれらは素数ですから、次のことがいえます: bは素数である a + b + 1は素数である b = 2のとき、aは偶数である それ以外のとき、aは奇数である 素数判定関数 is_prime には同じ引数が与えられることがよくあるのでメモ化しています。 #!/usr/bin/perl use strict; use warnings; use feature qw/say/; sub prime_seq_len($$) { my ($coeff_a, $coeff_b) = @_; my $len = 0; my $n = 0; $len++, $n++ while is_prime($n * ($n + $coeff_a) ...

Project Euler - Problem 18

問題 原文 Find the maximum total from top to bottom of the triangle 日本語訳 三角形を頂点から下まで移動するとき、その最大の合計値を求めよ。 解答 動的計画法 を使ってボトムアップで簡単に解くことができる問題です。 簡単のため、小さい三角形で考えることにします: 0: j 1: h i 2: e f g 3: a b c d 2行目の各点を頂点として、2行の小さい三角形が作れることが分かります。 上の例で言えば、(e, a, b)と(f, b, c)、(g, c, d)の3つです。 (e, a, b)の頂点eから末端(a、b、c、dのいずれか)に移動したとき、その数値の合計は最大でe + max(a, b)となります(maxは最大値を選ぶ関数)。同様に他の2つもf + max(b, c)、g + max(c, d)と表せます。 これらをE、F、Gとおくことにして、例を次のように書き換えます: 0: j 1: h i 2: E F G (h, E, F)からなる三角形の最大値はH = h + max(E, F)、(i, F, G)からなる三角形のそれはI = i + max(F, G)です。 Eは「頂点eから末端に至る経路の最大値」で、FやGも同様ですから、HとIは「頂点h(やi)から末端に至る経路の最大値」となります。 これを先ほどと同様に置き換えて: 0: j 1: H I 頂点jから末端に至る経路の最大値はJ = j + max(H, I)となり、これが解です。 #!/usr/bin/perl use strict; use warnings; use feature qw/say/; use List::Util qw/max/; my @rows = map { [ split /\s+/ ] } <DATA>; until (@rows == 1) { my $curr_row = $rows[-2]; my $bigger_branch; for (my $i = 0; $i < @$curr_row; $i++) { $bigger_branch = ma...

Perl 5 to 6 - サブルーチンとシグネチャ

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 04 - Subroutines and Signatures の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 04 - サブルーチンとシグネチャ SYNOPSIS # シグネチャなしのサブルーチン——Perl5風 sub print_arguments { say "Arguments:"; for @_ { say "\t$_"; } } # 固定引数の型指定付きシグネチャ sub distance(Int $x1, Int $y1, Int $x2, Int $y2) { return sqrt ($x2-$x1)**2 + ($y2-$y1)**2; } say distance(3, 5, 0, 1); # デフォルト引数 sub logarithm($num, $base = 2.7183) { return log($num) / log($base) } say logarithm(4); # 第2引数はデフォルトを利用 say logarithm(4, 2); # 明示的な第2引数 # 名前付き引数 sub doit(:$when, :$what) { say "doing $what at $when"; } doit(what => 'stuff', when => 'once'); # ...

Perl 5 to 6 - ツイジル

これはMoritz Lenz氏のWebサイト Perlgeek.de で公開されているブログ記事 "Perl 5 to 6" Lesson 15 - Twigils の日本語訳です。 原文は Creative Commons Attribution 3.0 Germany に基づいて公開されています。 本エントリには Creative Commons Attribution 3.0 Unported を適用します。 Original text: Copyright© 2008-2010 Moritz Lenz Japanese translation: Copyright© 2011 SATOH Koichi NAME "Perl 5 to 6" Lesson 15 - ツイジル SYNOPSIS class Foo { has $.bar; has $!baz; } my @stuff = sort { $^b[1] <=> $^a[1]}, [1, 2], [0, 3], [4, 8]; my $block = { say "This is the named 'foo' parameter: $:foo" }; $block(:foo<bar>); say "This is file $?FILE on line $?LINE" say "A CGI script" if %*ENV.exists('DOCUMENT_ROOT'); DESCRIPTION いくつかの変数にはツイジルという第2のシジルがあります。これは基本的にはその変数が「普通」ではないということです。違いはいくつかあり、例えばスコープの違いなどです。 オブジェクトのパブリックな属性とプライベートな属性がそれぞれ . と ! というツイジルを持つことは既に紹介しました; それらは通常の変数ではなく self に結びつけられています。 ツイジル ^ はPerl5で例外的に扱われていたケースを一般化します。次のように書けます # 注意: Perl5のコードです sort ...