ブログトップ 記事一覧 ログイン 無料ブログ開設

サンプルコードによるPerl入門 - Perlプログラミングの基礎から応用まで

サンプルが豊富なPerlの入門サイトです。if文、for文、配列、ハッシュ、正規表現を、丁寧に解説。Webサイトの作成方法、便利なPerlの関数とモジュールの紹介もあり。さらに、C言語を使った、Perlの拡張モジュールを作成する講座もあり。初級から上級まで、Perlのすべてが学べます。Twitter登録で、最新のPerl情報が得られます。

2016-05-10

Perlの最新バージョン 5.24リリース - サブルーチンと数値計算の高速化、Unicode 8.0のサポート、文法機能強化

 Perlの最新バージョン5.24がリリースされました。今回のリリースでは、Perlのサブルーチンと数値計算の高速がなされています。また、機能面では、Unicode 8.0のサポートがなされました。文法的な強化として、前方デリファレンスの実験的なステータスがはずされています。その他、細かなバグフィックスがなされました。

 Perl 5.22に引き続きPerl 5.24では、Perlの内部コードの改善がなされています。パフォーマンスの改善という大きなメリットがありますが、いくつかの副作用もありますので、合わせて、解説します。

 自分が技術的に不慣れで、安定的なPerlを望むなら、今のところPerl 5.20がおすすめです。技術的に強く、パフォーマンスの改善や新しい機能にチャレンジしたい方は、Perl 5.24にトライしてみてください。

 以下で、Perl 5.24の変更点を解説します。

パフォーマンスの改善

 Perl 5.24の最大の変更点は、パフォーマンスの改善です。

サブルーチン呼び出しの高速化

 スコープ生成と終了のオーバーヘッドをできる限り減らしたので、ループとブロックが速くなりました。たとえば、以下の空のサブルーチンは、今までの約三倍の速さで実行できます。

sub f{} f();

 5.24の変更で、最もうれしいのはこれでしょう。Perlの問題点のひとつにサブルーチン呼び出しが遅いというものがありましたが、これによって、問題のひとつが改善されています。

大文字、小文字を扱う関数、正規表現のパフォーマンス改善

 中国語のように、大文字小文字の区別がない言語があります。このような言語については、ロジックをスキップすることによって、ucfirst関数や「qr//i」のパフォーマンスが上昇しました。

substrの高速化

 memchrがサポートされているプラットフォームにおいてsubstrが高速化されました。以下の処理が、7倍程度速くなっています。

$s = "a" x 1000 . "wxyz";
$s =~ /wxyz/ for 1..30000
足し算・引き算・掛け算の高速化

 Perl 5.8.0において、64bit整数をサポートするために、数値演算が遅くなっていましたが、この遅いロジックが改善さました。Perlは、数値演算が遅いといわれますが、少し改善されました。

インクリメント・デクリメントの性能の改善

 Perlのインクリメント・デクリメントの性能が改善されました。ループ処理などが、少し速くなります。

機能面の強化

Unicode 8.0のサポート

 Unicode 8.0がサポートされました。PerlはUnicodeサポートの対応が速いです

新しい正規表現 \b{lb}

 改行の区切りを表現する新しい正規表現「\b{lb}」が追加されました。

前方デリファレンスの実験的なステータスがとれました

 Perl 5.24では、前方デリファレンスが、最初から、有効になりました。このおかげで、リファレンスからの、配列スライス、ハッシュスライス、部分ハッシュ取得、部分配列取得の処理が、記述しやすくなっています。

# 前方デリファレンス
my $nums_ref = [1, 2, 3];
my @nums = $nums_ref->@*; # (1, 2, 3);

# 前方デリファレンスを使用した配列スライス
my @nums_part = $nums_ref->@[0, 2]; # (1, 3)

my $names_h_ref = {
  ken => 1,
  taro => 2,
  kimoto => 3
};

# 前方デリファレンスを使用したハッシュスライス
my @names_part = $names_h_ref->@{'ken', 'kimoto'}; # (1, 3)

# 前方デリファレンスを使用した部分ハッシュ取得
my %names_h_part = $names_h_ref->%{'ken', 'kimoto'}; # (ken => 1, kimoto => 3)

互換性のない変更

 今回のリリースでは、いくつかの実験的な機能が、削除されています。

自動デリファレンスの削除

 廃止警告が出されていた、実験的な自動デリファレンスが削除されました。たとえば、以下の処理が動かなくなります。push, pop, shift, unshift, splice, keys, values, eachに、リファレンスを渡すことはできません。

レキシカルな$_が廃止されました。

 C<my $_>が、Perl 5.10で、実験的に追加されましたが、これが廃止されます。

ネストされた宣言が許可されなくなった

 ネストされた宣言は許可されなくなりました。以下の記述はコンパイルエラーになります。

my ($x, my($y));
our (my $x);
chdir('')は、ホームディレクトに移動できなくなりました

 chdir('')は、ホームディレクトリに移動できなくなりました。chdir()を使ってください。

知られている問題

 Perl 5.24では、内部的な改善のために、保証されない実装を利用している、いくつかのモジュールが、動かなくなっています。これは、現在Perlのコアチームで、議論されているので、経過を見守りましょう。

  • Algorithm::Permute
  • Coro
  • Data::Alias
  • RPerl
  • Scope::Upper
  • TryCatch
  • lexical::underscore

 最近のPerlは、内部改善が多く行われているので、内部APIに依存した、文法変化形のモジュールに依存することは、リスクが伴っています。

所見

 Perlのパフォーマンスが上がることはうれしい変更です。この方向性は、間違ってはいないと思います。このために、内部改善が必要ですが、そのために、いくつかの文法変化形のモジュールが、壊れるという状況になっています。

 特に、議論の的としては、Coroの話題が大きいようです。将来的には、コルーチンをPerlコアのほうで、サポートするのがよいと感じました。文法変化形のモジュールが、外部のモジュールとして実装されると、常に壊れる可能性がでてくるからです。

2016-05-07

GitPrep 2.0 リリース - プルリクエストのサポートなど、大幅に機能が強化

 GitHubのポータブルなクローンGitPrep 2.0を、2016年5月7日にリリースしました。GitPrepは、CGIと組み込みサーバーで起動でき、GitPrep 2.0は、GitPrepのメジャーバージョンアップです。待望のプルリクエスト機能が追加されました。その他、多くの機能強化が含まれています。

GitPrep

  • メールアドレスのサポート。ユーザーをメールアドレスで識別できるようになりました。
  • ユーザーIDに加えて、ユーザー名を設定できるようになりました。
  • データベースのテーブルの大幅な内部改善が行われており、一貫性が増しました。
  • プロジェクト単位で、エンコーディングの設定、diffの結果で、空白を無視するのオプションの設定が可能になりました。設定ファイルに指定している場合は、各プロジェクトで設定してください。
  • リバースプロキスのために利用されるヘッダは、X-Forwarded-HTTPSからX-Forwarded-Protoに変更されました。
  • 必要な一時ファイルは、gitprep内のディレクトリに作成されるようになりました。/tmpに依存しません。

GitPrepのイメージとサンプル

 GitPrepのイメージです。

f:id:perlcodesample:20160507145758p:image

 GitPrepのサンプルURLです。これは、さくらレンタルサーバーにおいてCGIで実行しているものです。アクセスすると、GitPrepの使い心地を試してみることができます。SSLにも対応しています。

GitPrepのサンプル

互換性のない変更

 GitPrepの、必要なPerlのバージョンが5.8.7から5.10.1にあがりました。最新版のMojoliciousを利用するようにしているので、古いMojoliciousが、潜在的に抱えていたセキュリティ問題も、解決されています。

 cygwinの公式なサポートを落としました。理論的には利用可能ですが、公式に動作をチェックすることはしなくなります。近い将来Windows10において、bash上でperlがサポートされますので、こちらでの利用を勧めていきたいと思います。

GitPrep 1.0からのアップロードする場合

 Perlのバージョンが5.8の場合は、perlbrewを使って、新しいバージョンのPerlをインストールしてください。

curl -L http://install.perlbrew.pl | bash
echo "source ~/perl5/perlbrew/etc/bashrc" >> ~/.bash_profile
source ~/.bash_profile

perlbrew install perl-5.16.3
perlbrew switch perl-5.16.3
perl -v

 クリーンインストールを行うために、一度extlibディレクトリを削除してください。

cd gitprep
rm -rf extlib

GitPrepのインストール

 ここからは、始めて利用する方も、アップグレードする方もほぼ同じ手順になります。

 モジュールのセットアップを行います。

./setup_module

 モジュールが正しくインストールされているかチェックします。

prove t

 次にGitPrepを1.0からバージョンアップする方は、データベースのアップグレード作業を行う必要があります。

# 安全のために、gitprepのディレクトリをバックアップ
cd ..
cp -rp gitprep gitprep.bak

# データベースのアップグレード
cd gitprep
mv data/gitprep.db data/gitprep_v1bak.db
./setup_database
old/copy_database_v1_to_v2 data/gitprep_v1bak.db data/gitprep.db

 GitPrep 2.0を始めて使う方は、次のコマンドを実行します。

./setup_database

 GitPrepの利用にはgitがインストールされていることが必要です。もし、ローカルのディレクトリに自分でgitをインストールしている場合は、gitprep.confでgitの場所を指定する必要があります。

[basic]
;;; Git command path
git_bin=/home/yourname/local/bin/git

 GitPrepを利用するための手順はこれだけです。インストールがとても簡単にできるように工夫されています。

GitPrepの開始と終了

 次のコマンドでGitPrepを開始することができます。

./gitprep

次のURLでGitPrepにアクセスすることができます。

http://localhost:10020

 次のコマンドでGitPrepを終了することができます。

./gitprep --stop

GitPrepプロジェクトからのお願い

 GitPrepは、オープンソースのプロジェクトです。GitHubと同等の機能を、オープンソース上で実現することを目指して開発が続けられています。もし今GitPrepを使っておられる方がおられましたら、ぜひGitPrep2.0のリリースを、知り合いの方に、お知らせしてほしいです。企業や、コミュニティ、学校の知り合いなどで、GitHubの機能を簡単にインストールして、自前のサーバーで運用したいという方がおられましたら、GitPrepの情報を一度お伝えください。

 オープンソースの作者にとっては、作成した作品を多くの人に使っていただけるのが、ひとつの喜びです。賛同いただけましたら、Twitterでの紹介や、はてなブックマークなども、よろしくお願いします。

 今後は、1年以内に、イシューのシステムとWikiのシステムを追加することが目標です。GitHub上で、スターをつけていただけるとありがたいです。ご支援お願いします。

GitPrep

2016-03-28

opcode.h - オペレーションに関する情報 | Perl言語研究

 opcode.hには、それぞれのオペレーションに関する情報が記載されている。Perl言語研究では、「OP型」のデータのことを、オペレーションと呼ぶことにしています。Perlは、構文解析が終わると、構文木に変換されますが、このそれぞれのノードは「OP型」になっています。

 オペレーションは、オペレーションコードによって、分類され、それぞれが情報を持ちます。その情報が記述されています。

オペレーションの名前

 たとえば、オペレーションの名前が記述されています。

EXTCONST char* const PL_op_name[] = {
  "null",
  "stub",
  "scalar",
  "pushmark",
  "wantarray",
  "const",
  "gvsv",
  ...
};

続きを読む

2016-03-26

opnames.h - オペレーションコードの一覧 | Perl言語研究

 opnames.hには、オペレーションコードが記述されています。

/* opname.h */
typedef enum opcode {
  OP_NULL    = 0,
  OP_STUB    = 1,
  OP_SCALAR  = 2,
  OP_PUSHMARK  = 3,
  OP_WANTARRAY   = 4,
  OP_CONST   = 5,
  OP_GVSV    = 6,
  ...
};

 Perlは、構文解析が行われた後に、コードが、構文木として表現されるのですが、構文木のひとつひとつのノードは、オペレーションと呼ばれます。これは「OP型」として表現されます。たとえば「pushする」とか「ハッシュのキーの存在を確かめる」とか「サブルーチンを実行する」とか「スカラを表現する」とか、そういうPerlのプログラミング上での操作が、オペレーションによって表現されます。

 オペレーションの種類を表すのが、オペレーションコードです。これは、列挙型です。

 「opnames.h」には、オペレーションコードが書かれていますが、それが、何を表すのかという解説がありません。解説を見たい場合は、「opcode.h」の「PL_op_desc」を参照するのがよいでしょう。

/* opcode.h */
EXTCONST char* const PL_op_desc[] = {
  "null operation",
  "stub",
  "scalar",
  "pushmark",
  "wantarray",
  "constant item",
  "glob value",
  ...
};


Perl言語研究

2016-03-25

embedvar.h - インタープリタ変数、グローバル変数の抽象化 | Perl言語研究

 embedvar.hは、インタープリタ変数、グローバル変数の抽象化のためのヘッダです。

インタープリタ変数の抽象化

 インタープリタ変数の抽象化のロジックは以下のようになっています。

#if defined(MULTIPLICITY)
/* cases 2 and 3 above */

#  if defined(PERL_IMPLICIT_CONTEXT)
#    define vTHX	aTHX
#  else
#    define vTHX	PERL_GET_INTERP
#  endif

#define PL_AboveLatin1		(vTHX->IAboveLatin1)
#define PL_Argv			(vTHX->IArgv)
#define PL_Cmd			(vTHX->ICmd)
#define PL_DBcontrol	(vTHX->IDBcontrol)

#endif

 まず「MULTIPLICITY」が定義されている場合というのは、複数のインタープリタが利用できる状態であるということです。そのような場合は、インタープリタごとの変数にアクセスする必要があります。

 次に、「PERL_IMPLICIT_CONTEXT」とは、暗黙のコンテキストが想定するという意味で、「Perl_」で始まる関数の第一引数に、インタープリタが渡されるということを意味します。

 一般的には「MULTIPLICITY」が定義されていれば「PERL_IMPLICIT_CONTEXT」が定義されていると考えてください。

 「aTHX」は次のように定義されています。

/* perl.h */
#ifdef PERL_IMPLICIT_CONTEXT
#  define aTHX	my_perl
#end

 my_perlは、グローバル変数であり、インタープリタを表しています。

/* perlmain.c */
static PerlInterpreter *my_perl;

 次に「PERL_IMPLICIT_CONTEXT」が定義されていない場合ですが、「PERL_GET_INTERP」は、次のように定義されていて、現在のインタープリタです。これは、グローバル変数です。

/* perl.h */
#  define PERL_GET_INTERP              (PL_curinterp)
/* perlvar.h */
PERLVARI(G, curinterp,	PerlInterpreter *, NULL)
					/* currently running interpreter
					 * (initial parent interpreter under
					 * useithreads) */

 「PERL_IMPLICT_CONTEXT」が定義されている場合は「vTHX」は「my_perl」として展開され、そうでない場合は「Gcurinterp」として展開されます。。

 そして、インタープリタ変数へのアクセスですが以下のように定義されています。

#define PL_AboveLatin1		(vTHX->IAboveLatin1)

グローバル変数の抽象化

 次にグローバル変数の抽象化のコードが書かれています。「PERL_GLOBAL_STRUCT」が、定義されている場合は、グローバル変数全体が、ひとつの構造体として存在しています、定義されていない場合は、通常のグローバル変数として存在しています。その二つの場合のどちらでも「PL_appctx」によって、変数にアクセスすることができます。

#if defined(PERL_GLOBAL_STRUCT)

#define PL_appctx		(my_vars->Gappctx)
#define PL_Gappctx		(my_vars->Gappctx)
#endif
/* perlmain.c */
struct perl_vars *my_vars = init_global_struct();


Perl言語研究

2016-03-22

perlvars.h - Perlのグローバル変数

 perlvars.hには、Perlのグローバル変数が定義されています。

/* perlvars.h */

/* global state */
#if defined(USE_ITHREADS)
PERLVAR(G, op_mutex,	perl_mutex)	/* Mutex for op refcounting */
#endif
PERLVARI(G, curinterp,	PerlInterpreter *, NULL)
					/* currently running interpreter
					 * (initial parent interpreter under
					 * useithreads) */
#if defined(USE_ITHREADS)
PERLVAR(G, thr_key,	perl_key)	/* key to retrieve per-thread struct */
#endif

 Perlには、インタープリタごとに持つインタープリタ変数がありますが、それとは別にグローバル変数も存在します。たとえば、現在実行しているインタープリタ、スレッドの競合を制御するためのミューテックスなどは、グローバル変数として定義されています。

 グローバル変数の宣言は、「PERLVAR」「PERLVARI」というマクロを使って記述されていま。これは「perl.h」で定義されています。

続きを読む