home ホーム search 検索 -  login ログイン  | help ヘルプ

find 検索

1231 - 1240 / 1320    [|<]  [|<]  [<]  121  122  123  124  125  126  127  128  129  130   [>]  [>|][>|]
タイトル/名前 更新者 更新日
Perl/codepiece/array_hash1 msakamoto-sf 2008-12-24 22:19:43
Perl/codepiece/static_vars1 msakamoto-sf 2008-12-24 22:11:19
Perl/codepiece/signal01 msakamoto-sf 2008-12-24 22:07:11
日記/2007/06/28/メモ msakamoto-sf 2008-12-23 23:40:31
日記/2007/07/23/メモ msakamoto-sf 2008-12-23 23:34:07
PHP/PokoX, pokopokoという黒歴史メモ msakamoto-sf 2008-12-23 16:25:00
日記/2007/02/25/findコマンドメモ msakamoto-sf 2008-12-23 15:13:01
技術/HTML/tableレイアウト(IE6とFirefox1.5) msakamoto-sf 2008-12-23 15:00:48
画像/reports_2006052101_03ff15.jpg msakamoto-sf 2008-12-23 14:52:02
画像/reports_2006052101_03ie6.jpg msakamoto-sf 2008-12-23 14:51:25
ソート項目 / ソート順     1ページ 件ずつ表示

Perl/codepiece/array_hash1  

所有者: msakamoto-sf    作成日: 2007-03-12 22:12:10
カテゴリ: Perl 

配列とハッシュの基本的な作成・アクセス方法を確認する。


参考リンク

配列

コードピース01 : 配列の実体コンストラクタ"(", ")"

  • コードピース
use strict;
use warnings;
use Data::Dumper;

my @ary1 = (1, 2, 3, (4, 5, 6), (7, (8, 9), ), );
print @ary1, "\n";
print Dumper(@ary1), "\n";
print $ary1[0], "\n";
print $ary1[@ary1-1], "\n";
  • 出力
123456789 # ← print @ary1
$VAR1 = 1;
$VAR2 = 2;
$VAR3 = 3;
$VAR4 = 4;
$VAR5 = 5;
$VAR6 = 6;
$VAR7 = 7;
$VAR8 = 8;
$VAR9 = 9;
#(ここまでがDumper(@ary1)の出力)
1 # ← print $ary1[0]
9 # ← print $ary1[@ary1-1]

配列作成時の"(...)"は、配列の実体*1を作成するコンストラクタ。
従って、変数の"ary1"は、常にリストとして"@"でアクセスする必要がある。

print Dumper($ary1), "\n";

は、

Global symbol "$ary1" requires explicit package name at hoge.pl line 7.
Execution of hoge.pl aborted due to compilation errors.

となる。すなわちスカラーとしての"ary1"をシンボルテーブルから探そうとしてしまう。

次の記法にも注意。

print $ary1[@ary1-1], "\n";

要するに配列の最大要素数-1により、配列の末尾にアクセスしている。ここで@ary1 を -1 することで、

  1. 無理矢理スカラーコンテキストで評価
  2. → @ary1はスカラーコンテキストでは配列の要素数を表す
  3. → -1 することで0始まりの配列の末尾INDEXになる。

ということで、配列の末尾要素にアクセスできている。

コードピース02 : 配列のリファレンスコンストラクタ"[", "]"

  • コードピース
my $ary2 = [ 1, 2, 3, (4, 5, 6), [7, 8, 9] ];
print $ary2, "\n";
print Dumper($ary2), "\n";

print $ary2->[0], "\n";
print $ary2->[6], "\n";
print $ary2->[6][0], "\n";

my $ary_buf = $ary2->[6];
print $ary_buf->[0], "\n";
print $ary_buf->[@$ary_buf - 1], "\n";
  • 出力
ARRAY(0x18c35ac) # ← print $ary2
$VAR1 = [
          1,
          2,
          3,
          4,
          5,
          6,
          [
            7,
            8,
            9
          ]
        ];

1 # ← print $ary2->[0]
ARRAY(0x274e6c) # ← print $ary2->[6]
7 # ← print $ary2->[6][0]

7 # ← print $ary_buf->[0]
9 # ← print $ary_buf->[@$ary_buf - 1]

"[", "]"は''名無し配列コンストラクタ''(Effective Perl)であり、その返すものはリファレンスである。従って、リファレンス全般で要素アクセスに使われる"->"を用いて各インデックスの値にアクセスできる。

前掲のコードピースでは名無し配列を多段に組んでいる。この場合、入れ子になった配列のリファレンスを取り出し、$ary_bufとしてアクセスできている。

$ary2->[6][0]

も、

$ary_buf->[0]

も、両方同じ"7"を取得できている。

コードピース03 : ループアクセス(for, foreach)

  • コードピース
my @ary3 = (1, 2, 3);
print join(" ", @ary3), "\n";          # ... (a)

for(my $i = 0; $i < @ary3; $i++) {
	$ary3[$i]++;
}
print join(" ", @ary3), "\n";          # ... (b)

foreach my $e (@ary3) {
	$e++;
}
print join(" ", @ary3), "\n";          # ... (c)

foreach (@ary3) {
	$_++;
}
print join(" ", @ary3), "\n";          # ... (d)

for my $i (@ary3) {
	$i++;
}
print join(" ", @ary3), "\n";          # ... (e)

for (@ary3) {
	$_++;
}
print join(" ", @ary3), "\n";          # ... (f)
  • 出力
1 2 3 # (a)
2 3 4 # (b)
3 4 5 # (c)
4 5 6 # (d)
5 6 7 # (e)
6 7 8 # (f)

(a)は基本中の基本であるが、よりエレガントに見える書き方は (d) や (f) であろう。いずれにせよ、どの書き方も正しく配列の要素を+1できている。

なお、前掲のコードピースは配列の実体を対象にしてのコードだった。下記に、同じ出力結果になる、名無し配列リファレンスを使用した場合のコードを示す。

my $ary3b = [1, 2, 3];
print join(" ", @$ary3b), "\n";
for(my $i = 0; $i < @$ary3b; $i++) {
	$ary3b->[$i]++;
}
print join(" ", @$ary3b), "\n";
foreach my $e (@$ary3b) {
	$e++;
}
print join(" ", @$ary3b), "\n";
foreach (@$ary3b) {
	$_++;
}
print join(" ", @$ary3b), "\n";
for my $i (@$ary3b) {
	$i++;
}
print join(" ", @$ary3b), "\n";
for (@$ary3b) {
	$_++;
}
print join(" ", @$ary3b), "\n";

コードピース04 : 間違いやすい配列のスライスについて($ary[x]と@ary[x]の違い)

print するだけのミニマムテストでは分かりづらいが、

print $ary[0]


print @ary[0]

は異なる。

前者は"$"が付いている為スカラーコンテキストで評価され、配列の要素としてアクセスされる。後者は"@"が付いている為、配列、すなわち''スライス''としてアクセスされる。

  • コードピース
my @ary4 = ("abc", "def", "ghi", "jkl", "mno");
print $ary4[0], "\n";
print @ary4[0], "\n"; # ← (a)
print $ary4[1, 2], "\n"; # ← (b)
print join(" ", @ary4[1, 2]), "\n";
print join(" ", @ary4[1 ... 4]), "\n";
print join(" ", @ary4[1 ... 5]), "\n"; # ← (c)
  • 出力
Scalar value @ary4[0] better written as $ary4[0] at ... (a)
Multidimensional syntax $ary4[1, 2] not supported at ... (b)
abc # ← print $ary4[0]
abc # ← print @ary4[0] ... (a)
ghi # ← print $ary4[1, 2] ... (b)
def ghi # ← print join(" ", @ary4[1, 2])
def ghi jkl mno # ← print join(" ", @ary4[1 ... 4])
Use of uninitialized value in join or string at ... (c)
def ghi jkl mno

(a), (b) のようにスカラーが予想される値を"@"としてアクセス(a)したり、スライスが予想される値を"$"としてアクセス(b)すると、警告が発せられる。
またスライスでも、要素INDEXを越えてアクセスしようとすると(c)のように警告が発せられる。

書いている本人自身も実は何回も間違えているように、Perl初学者にとってはとにかく間違いやすい。 Perlにおいてはコンテキストが重要であり、変数がどのコンテキストで評価されるのかは、その冒頭に付く文字($, @, %, *)で判断される (それに加えて、前後のコードも関係する)。これについて、人間側で感情的な割り切りを行えれば、大分Perlの学習と理解も進むのかも知れない。

コードピース05 : ( 先頭 | 末尾 ) 要素の追加削除

  • コードピース
my @ary5 = ("abc", "def", "ghi", "jkl", "mno");
#--------------------- (a) : 末尾要素を削除
my $buf = pop @ary5;
print join(" ", @ary5), "\n";
print $buf, "\n";
#--------------------- (b) : 末尾要素に追加
$buf = push(@ary5, 7);
print join(" ", @ary5), "\n";
print $buf, "\n";
#--------------------- (c) : 先頭要素を削除
$buf = shift @ary5;
print join(" ", @ary5), "\n";
print $buf, "\n";
#--------------------- (d) : 先頭要素に追加
$buf = unshift(@ary5, "xyz");
print join(" ", @ary5), "\n";
print $buf, "\n";
#--------------------- (e) : スカラーコンテキストで評価
print scalar(@ary5), "\n";
  • 出力
#--------------------- (a) : 末尾要素を削除
abc def ghi jkl
mno # 削除された要素の値
#--------------------- (b) : 末尾要素に追加
abc def ghi jkl 7
5 # 追加後の配列の要素数
#--------------------- (c) : 先頭要素を削除
def ghi jkl 7
abc # 削除された要素の値
#--------------------- (d) : 先頭要素に追加
xyz def ghi jkl 7
5 # 追加後の配列の要素数
#--------------------- (e) : スカラーコンテキストで評価
5

コードピース06 : 配列へのundefの代入と、空リストの判別

undef代入の幾つかのパターンと、空のリストで有ることをどうやって判別を示す。

  • コードピース
#--------------------- (a)
my @ary6 = ();
if(@ary6) {
	print Dumper @ary6, "\n";
} else {
	print "ary6 is not defined.(a)\n";
}
#--------------------- (b)
@ary6 = undef;
if(@ary6) {
	print Dumper @ary6, "\n";
} else {
	print "ary6 is not defined.(b)\n";
}
#--------------------- (c)
@ary6 = 1 .. 5;
@ary6[2, 4] = undef;
print Dumper @ary6, "\n";
#--------------------- (d)
undef @ary6;
if(@ary6) {
	print Dumper @ary6, "\n";
} else {
	print "ary6 is not defined.(d)\n";
}
  • 出力
#--------------------- (a)
ary6 is not defined.(a)
#--------------------- (b)
$VAR1 = undef;
$VAR2 = '
';
#--------------------- (c)
$VAR1 = 1;
$VAR2 = 2;
$VAR3 = undef;
$VAR4 = 4;
$VAR5 = undef;
$VAR6 = '
';
#--------------------- (d)
ary6 is not defined.(d)
  • (a) : 空のリスト"()"で初期化した直後の配列は、if()のスカラーコンテキストでは要素数が"0"、すなわち偽として評価される。
  • (b) : その後、undefを代入してみると、興味深いことに要素数が2で末尾の要素が空になる。
  • (c) : また、配列のスライスを利用してundefを代入すると、該当要素のみundefになっている。
  • (d) : undef動詞*2を使用すると、if()のスカラーコンテキストで偽として評価される。

注意すべきは、 defined は Perl5.004以降、スカラー変数を対象とするようになり、配列やハッシュは非推奨になっている 点である。

このため、下記のコードはwarningを生成する。

if(defined(@ary6)) { ...
→
defined(@array) is deprecated at ...
       (Maybe you should just omit the defined()?)

では、厳密な意味で "@ary6" がundefなのか、空リストであるのか、をどうやって見分けるのか?については残念ながら現段階では調べ切れていない。%::などを用いて直接シンボルテーブルにアクセス・・・しても、lexical変数であればそれも無意味である。

とりあえず、

my @ary = ();
# or
undef @ary;

は偽になるが、

my @ary = undef;

は偽にならないという点に十分注意する。

ハッシュ

ハッシュについてはその基本操作の殆どが、冒頭でリンクとして挙げたPerl講座で網羅されている。ここでは実体のコンストラクタである"(", ")"と、リファレンスコンストラクタ"{", "}"の差異をメインに、ざっと流すに留める。*3

コードピース01 : ハッシュの実体コンストラクタ"(", ")" とループアクセス(while, each)

  • コードピース
my %h1 = ( abc => 123, "def" => 456, 'ghi' => 789 );
#--------------------- (a)
print Dumper(%h1), "\n";
#--------------------- (b)
print $h1{'abc'}, "\n";
#--------------------- (c)
while(my ($key, $val) = each(%h1)) {
	print "[$key] = $val\n";
}
  • 出力
#--------------------- (a)
$VAR1 = 'def';
$VAR2 = 456;
$VAR3 = 'abc';
$VAR4 = 123;
$VAR5 = 'ghi';
$VAR6 = 789;
#--------------------- (b)
123
#--------------------- (c)
[def] = 456
[abc] = 123
[ghi] = 789
  • (a) を見てみると、Dumperの出力上は通常の配列と何ら変わりないようにも見える。出典は失念したが、どこかのドキュメントにハッシュは内部的には配列の形で保持されていると書かれていたのをおぼえている。その記憶をこの出力は補強している。*4
  • (b) では、普通にキーを指定してスカラーコンテキストでアクセスする方法を示している。代入式の左辺(LVALUE)としても使える。
  • (c) では、whileとeachを組み合わせて、キーと値のペアをループでアクセスする方法を示している。
    • 但し、出力がそうであるように、while-eachの組み合わせではキー値のソートが保証されない。単純な"for $key (keys(%hash)) "でもそのようである。
    • キー値をソートして用いる場合は下記コードのようになる。詳しくはsmartのPerl講座を参照。
for my $key (sort(keys(%h1))) {
	print "[$key] = ", $h1{$key}, "\n";
}
→
[abc] = 123
[def] = 456
[ghi] = 789

コードピース02 : ハッシュのリファレンスコンストラクタ"{", "}"

"(", ")"を用いるとハッシュの実体を作成できた。続いて、 名無しハッシュ のコンストラクタである"{", "}"の使用例を示す。

  • コードピース
my $h2 = { abc => 123, "def" => (4, 5, 6), "ghi" => [7, 8, 9 ] };
#--------------------- (a)
print Dumper($h2), "\n";
#--------------------- (b)
print $h2->{'abc'}, "\n";
print $h2->{'def'}, "\n";
print $h2->{'ghi'}, "\n";
print $h2->{'ghi'}->[0], "\n";
print $h2->{'ghi'}->[1], "\n";
print $h2->{'5'}, "\n";
#--------------------- (c)
while(my ($key, $val) = each(%$h2)) {
	print "[$key] = $val\n";
}
  • 出力
#--------------------- (a)
$VAR1 = {
          'def' => 4,
          'abc' => 123,
          'ghi' => [
                     7,
                     8,
                     9
                   ],
          '5' => 6  # ← !!注意!!
        };
#--------------------- (b)
123             # $h2->{'abc'}
4               # $h2->{'def'}
ARRAY(0x275028) # $h2->{'ghi'}
7               # $h2->{'ghi'}->[0]
8               # $h2->{'ghi'}->[1]
6               # $h2->{'5'}
#--------------------- (c)
[def] = 4
[abc] = 123
[ghi] = ARRAY(0x275028)
[5] = 6  # ← !!注意!!
  • (a) : コンストラクタでリストを用いたり、名無し配列リファレンスを用いた例を示す。 リスト部分(4,5,6)が分割されてしまっている点に注意!!
  • (b) : ハッシュリファレンスを用いた一般的なアクセス例を示す。
  • (c) : ハッシュリファレンスのループ処理の例を示す。eachでは、明示的に'%'を頭に付けてハッシュコンテキストで評価させている点に注意。
  • この、(4, 5, 6)が展開されている箇所は、次のコードピースを見てみると実に興味深い。*5

コードピース03 : ハッシュのコンストラクタの亜種(配列風味)

実際のところ、"=>"を使用せずともハッシュは作れるようである。要は変数が"%"としてハッシュコンテキストで実体が代入されるか、"{", "}" で囲まれたリストとしてハッシュのリファレンスで代入されるか、どちらでもハッシュとして扱えるようである。

  • コードピース
my %h3 = ( "abc", 123, "def", 4, 5, 6, "ghi", [7, 8, 9] );
my $h4 = { "abc", 123, "def", 4, 5, 6, "ghi", [7, 8, 9] };
#--------------------- (a)
print Dumper(%h3), "\n";
print Dumper(%$h4), "\n";
#--------------------- (b)
print Dumper(\%h3), "\n";
print Dumper($h4), "\n";
  • 出力
#--------------------- (a)
# %h3
$VAR1 = 'def';
$VAR2 = 4;
$VAR3 = 'abc';
$VAR4 = 123;
$VAR5 = 'ghi';
$VAR6 = [
          7,
          8,
          9
        ];
$VAR7 = '5';
$VAR8 = 6;
# %$h4(ハッシュコンテキストで評価)
$VAR1 = 'def';
$VAR2 = 4;
$VAR3 = 'abc';
$VAR4 = 123;
$VAR5 = 'ghi';
$VAR6 = [
          7,
          8,
          9
        ];
$VAR7 = '5';
$VAR8 = 6;
#--------------------- (b)
# \%h3(リファレンス経由で評価)
$VAR1 = {
          'def' => 4,
          'abc' => 123,
          'ghi' => [
                     7,
                     8,
                     9
                   ],
          '5' => 6
        };
# $h4
$VAR1 = {
          'def' => 4,
          'abc' => 123,
          'ghi' => [
                     7,
                     8,
                     9
                   ],
          '5' => 6
        };

見ての通り、コンテキストさえ合わせればどちらも同じ形式で扱えるようである。

コードピース04 : ハッシュのスライスとundef

  • コードピース
my %h5 = ("abc" => 123, "def" => 456, "ghi" => 789);
my $h6 = {"abc" => 123, "def" => 456, "ghi" => 789};
#--------------------- (a)
print join(" ", @h5{"abc", "ghi"}), "\n";
print join(" ", @$h6{"def", "ghi"}), "\n";
#--------------------- (b)
@h5{"ghi", "abc"} = @h5{"abc", "ghi"};
@$h6{"def", "abc"} = @$h6{"abc", "def"};
for my $key (sort(keys(%h5))) {
	print "[$key] = ", $h5{$key}, "\n";
}
for my $key (sort(keys(%$h6))) {
	print "[$key] = ", $h6->{$key}, "\n";
}
#--------------------- (c)
@h5{"abc", "ghi"} = (undef, undef);
@$h6{"abc", "def"} = (undef, undef);
print Dumper(%h5), "\n";
print Dumper(%$h6), "\n";
#--------------------- (d)
my %h7 = ();
if(keys(%h7)) {
	print Dumper(%h7);
} else {
	print "%h7 is empty.\n";
}
  • 出力
#--------------------- (a)
123 789
456 789
#--------------------- (b)
# %h5
[abc] = 789
[def] = 456
[ghi] = 123
# $h6
[abc] = 456
[def] = 123
[ghi] = 789
#--------------------- (c)
# %h5
$VAR1 = 'def';
$VAR2 = 456;
$VAR3 = 'abc';
$VAR4 = undef;
$VAR5 = 'ghi';
$VAR6 = undef;
# $h6
$VAR1 = 'def';
$VAR2 = undef;
$VAR3 = 'abc';
$VAR4 = undef;
$VAR5 = 'ghi';
$VAR6 = 789;
#--------------------- (d)
%h7 is empty.
  • (a) : 任意のキーをつなげて、"@"によりスライスとして評価され、キーの値のリストが取得できている。
  • (b) : スライスを利用して、任意のキー間で値のswapを行える。
  • (c) : スライスに対しundefのリストを代入することで、undefを設定できる。(キー自体の削除は、deleteを使用する。)
例:delete @hash_slice{'keyA', 'keyC'};
  • (d) : キーが空の場合は、"keys"を使用して、空のハッシュを判別できる。

*1: "Effective Perl"上では"リストリテラル"と表記されているが・・・上手い日本語が分かりません。
*2: Effective Perlの訳書の表現
*3: というか正直、smartのPerl講座がわかりやすすぎて、自分で実験・検証する気力が無くなりました。やっぱり本職のドキュメントは素晴らしいです。
*4: おそらくEffective Perlの33項「名無しハッシュによってC言語スタイルの構造体を構築する」の"*5"の箇所と思われる。リファレンスを用いたアクセス($h->{hoge})は配列アクセスに最適化される、という箇所。
*5: けど、実際の内部処理の仕掛けはまだ未調査です・・・。

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-24 22:19:43
md5:8de452e30fcb8d6710451f8a7dea7c02
sha1:c3b561107ab3ae53b50fe0e943623e6e44425cb7

Perl/codepiece/static_vars1  

所有者: msakamoto-sf    作成日: 2007-02-25 22:09:00
カテゴリ: Perl 

  • Perlには、C/PHP にあるようなstatic変数(関数内部の局所変数で、かつ、関数を抜けた後も値が保持される性質の変数)は存在しない。
  • しかし、lexical変数は"{}"内のスコープを持っている為、これを利用して疑似static変数を使用できる。
  • Perl >= 5.0?
  • コードピース
#!/usr/bin/perl
#use strict; <<<< 末尾のprintを使用しなければ有効化して大丈夫。
package test;
{
	my $count;
	sub countup { $count++; $count; }
}
package main;
print &test::countup(), "\n";
print &test::countup(), "\n";
print &test::countup(), "\n";
print &test::countup(), "\n";

print '$count is not defined', "\n" if !defined($count);
print '$test::count is not defined', "\n" if !defined($test::count);
  • 出力
1
2
3
4
$count is not defined
$test::count is not defined

只の"{}"でsubを囲む。lexical変数の場合、本当の意味で"機械的に"スコーピングしてくれる為、只の"{}"といえど、その中のmyはその中で保持される。これにより、"staticに見える"状況を創り出している。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-24 22:11:19
md5:61eb9a0548ff64d43983cd45ad3347b2
sha1:8fca48ec5cecc5822b584fcb3ec6d69569fe145f

Perl/codepiece/signal01  

所有者: msakamoto-sf    作成日: 2007-03-14 21:59:42
カテゴリ: Perl 

シグナルは非常に扱いが難しいです。ここにまとめた文章は依然として「メモ」扱いです。より正確で厳密な記述に、将来書き換えられる可能性もありますし、あるいはそうした外部リソースのリンクが追記される可能性があります。つまり・・・あの、その、これ、まだ私的なメモの段階なので、あんまり信用されるとちょっとまずいです。という感じです。

簡単なように見えて面倒くさいシグナル処理

Inter Process Communication (IPC) でのシグナル(signal)は、非常に奥が深い。というのも

  1. マルチスレッドプログラミングにおいてどうなるのか?
  2. シグナルハンドラの処理中に、同じシグナルを受信して同じシグナルハンドラに入ってしまう、いわゆる"再突入問題"( re-entrant problem )をどう処理するか?
  3. シグナルハンドラ中で"re-entrant"でない*1関数を呼ぶとどうなるか?

などなど、"同時性"についてかなり面倒くさい考慮が必要になる機構だからだ。

Cから使えるAPIにしても、以下の二系統が存在する。

  1. 初期に作られた"signal(2)"システムコール
  2. POSIXで制定された"sigaction(2)"系のシステムコール

一般に関数のI/Fが簡便であるのはsignal(2)の方である。シグナルをブロックしたり、ブロック対象のシグナルを細かく制御したりする場合、また子プロセスの終了を緻密に検出したい場合などは、sigaction(2)系を用いると良いらしい。

シグナル関係のURL

Perlでのシグナル操作はCライブラリの signal(3) ベース

前掲のperlipcで"signal(3)"で検索すれば見つかるが、Perlでのシグナル処理は基本的にsignal(3)をベースにしている。そのため、sigprocmask(2)やsigsetopts(3)を経由したシグナルのブロッキングはそのままではできない。(POSIXを利用すれば別だが、そうすると次にメモした"Deferred"シグナル機構を迂回してしまう。)

シグナルのブロッキングについては、"local"を用いた巧妙な手法がperlipcに載っている。

sub sig_blocked {
    local $SIG{ALRM} = 'IGNORE';
    &blocked_routine;
}
sub blocked_routine {
    # SIGALRMについてブロック中である
}

"local"により、%SIGの元の値はスタックに積まれ、sig_blockedを抜けると戻される。blocked_routine()中はSIGALRMを受信しても無視されるようになる。

Perl 5.7.3 以降の"Deferred"シグナル機構(コード最適指向の遅延シグナル検出機構?)

perlipcに専用の節が設けられているほど重要である。

つまり、Perl 5.7.3 以降については、%SIGを用いる限り、 Perlの内部処理中にシグナルハンドラに飛ぶような事は無くなった と言うことらしい。
たとえIOを処理中であっても、Perlは内部で 適当に区切りの良いところで シグナルが受信されたかチェックしており、もしIO読み書き中でも、シグナルハンドラ処理後ちゃんと再開してくれるらしい。内部的には、Perlはopコードを順繰りに読み進めているわけだが、ちょうどopコードの切れ目のタイミングでシグナルをチェックしてくれているらしい*2
これにより、例えばopコードそれ自体の処理中(メモリIOが発生するタイミングなど)で突然シグナルハンドラに飛んでしまう、というような事はなくなり、全般的に安定性の向上につながっているようだ。

POSIX モジュールベースも利用可能(但し"Deffered"シグナルは意味無しに?)

sigaction(2)系を使用したい場合、POSIXモジュールからクラスや関数が提供されている。詳細はPOSIXモジュールのperldocを参照。

但し、perlipcの"Deferred"シグナルの節でもきっちり釘を刺されているが、POSIXを使用する場合、%SIGによる"Deferred"シグナル機構の恩恵を享受できなくなる。つまりPerl内部処理中にシグナルハンドラに入ることによるメモリ・IOの不具合が発生しうるという点に注意する必要がある。

結局詳細は"Perl Cookbook"待ち?

載ってるかなあ・・・。Amazonに注文はしてありますが、まだ届いてないです。


*1: プロセス中で同時に呼ばれることを想定せず、プロセスコンテキスト中でグローバル変数を裏側で持ってしまっている、標準関数など
*2: これも幾つかの"safe point"の一例であり、他にもPerlが"safe point"と認めているタイミングで、シグナルのフラグをチェックしているようである。

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-24 22:07:11
md5:f2ad4c87314e238664ab50eae2fc91cf
sha1:43a75d2ffa42478ac6f57f0cb285c97b16b383c3

日記/2007/06/28/メモ  

所有者: msakamoto-sf    作成日: 2007-06-28 23:39:51
カテゴリ:

・JSでXMLRPC調べてたら、こんなのがあった。

http://jamritas.sourceforge.net/

ちょっと小さいかな・・・。

・畜生!やられた!!PHP内部コードまで?バイナリアンを自称するだけある・・・。

https://www.codeblog.org/blog/moriyoshi/

・・・なんか、馬鹿らしくなってきたよ・・・。っつーか、HTTPSにしてる理由が分からないけど。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 23:40:31
md5:3165ba919d56c163b5ae0671c12b550f
sha1:92440be5046b473b7cb5e216f8ec017a5f692f5d

日記/2007/07/23/メモ  

所有者: msakamoto-sf    作成日: 2007-07-23 23:33:00
カテゴリ:

・おお!?大垣さんが、GIHYOでセキュリティ連載!?要チェック!
http://gihyo.jp/dev/serial/01/php-security

あら、こんなのも・・・。
「検索エンジンを作る」
http://gihyo.jp/dev/serial/01/make-findspot

はぁん・・・FINDSPOTね・・・。Hyper EstraierやSennaやLuceneは知ってたけど、これは知らない・・・。

で、Xhwlayではbcidやpage, eventがリクエストで来るわけだけど。一応これ、やばめ除去用のコードは入れてある。

preg_match("/^[0-9A-Za-z_\-,]+$/m")

なんだけど・・・
http://gihyo.jp/dev/serial/01/php-security/0005?page=3

!!げ!? "D"?mじゃなくて?
と思って確認してみたら、意味的にはmでも大丈夫な見たい。
http://jp.php.net/manual/ja/reference.pcre.pattern.modifiers.php

あー、よかった・・・。一応、\r\nや\r混じり、%00交じりをrawurldecodeさせたやつとかでも確認とってるから、大丈夫だとは思ってたんだけど・・・。
とはいえ、XHWLAY_VAR_NAMESPACE_REQUESTとかに入れるのはまずいかもしれない。XHWLAY_VAR_NAMESPACE_INTERNALみたいなの作って、それ使ったほうがイイかなあ・・・。

・「つくるぶ」。ここの「まとめ」、結構イカス。
http://www.tkrb.jp/


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 23:34:07
md5:e650a89bba13fe74a8e1cefb8785ab04
sha1:b4983e5f43e806da83262228c7ef719d4fbfc8fa

PHP/PokoX, pokopokoという黒歴史メモ  

所有者: msakamoto-sf    作成日: 2008-12-23 15:30:35
カテゴリ: PHP Web 

2005年頃、"PokoX"というWebアプリのフレームワークを作っていました。第5回PHP勉強会でオレオレフレームワークということで発表したりもしました。
過去のPukiWikiデータを整理していてPokoX関係のデータをこちらに移すか悩んでいたのですが、今更参照する事も無いと思いました。とはいえコンテンツから完全に消去するのも忍びないので、思い出と共にメモしておきます。

PokoX
SF.jp上は "pokopoko" というプロジェクト名で登録してあります。
http://sourceforge.jp/projects/pokopoko/

poko1時代 (2001 - 2003)

Linuxサーバ管理のバイトで、PHP+PostgreSQLのプログラミングを勉強がてら始めた時代に作ったリリース。
当時はDBのマスタ管理画面を作る事が多くて、それをパターン化したもの。
まだ PHP3 の時代で、セッション管理などは PHPLIB とかいうライブラリで実装していた。
テンプレートエンジンの存在など知らない、デザパタも知らない、そんな時代に作成。
ページャ機能も無くて、DB抽象レイヤーも無い。

poko2時代 (2004)

ようやくSmartyとかADODBとかを知り、少しはまともなアプリが組めるようになり、PEARとかも使い始めた。
大学の卒業と就職の年。
poko1をSmarty/ADODB/PEARのページャ機能を使って作り直したのがpoko2。
とはいえ、poko2は実際に使う事は無かった。フレームワークという考え方にどっぷりはまってしまい、すぐPokoXの作成に移ってしまったから。

poko1, poko2 の作り

基本的にマスタ管理に特化した作りになっていて、DBのテーブル定義をPHPの連想配列で組んでおけば、基本的なマスタ管理画面を自動的に表示してくれる。
ベース部分の作り込みがクラスライブラリで提供されていて、画面やフォームを弄りたければ該当箇所のメソッドをオーバーライドしたクラスを用意する仕組み。
テンプレートの存在を知らないか、知っていても使いこなせていない時代だったので、HTMLの出力はPHP側でクラスのメソッドの中で行っていた。
ヘッダーやフッターもベース部分で全部ハードコードしていた為、HTMLをカスタマイズしようと思ったら相当の苦労が必要だった。

PokoX時代 (2005)

poko1, poko2 は確かにマスタ管理では役に立ったのだけれど、一般公開する表側の画面を作るのには向いていなかった。
ちょうどMojaviやEthnaなどPHPフレームワーク花盛りの頃で、「このままpokoシリーズを続けるか、Mojavi/Ethna/Mapleに転向するか」かなり悩んだ記憶がある。
仕事でPHPをメインとしているわけではなく、どちらかといえば趣味で続けていたため、オレオレフレームワークでも特別困る事が無かった。

悩んだ末に、poko1/2でのキモだったDB機能をごっそりと削り落とし、画面遷移の中核だけを取り出して組み直すことにしたのがPokoX。

PokoXはそれなりに使えて、実際に仕事でも何度か使った。作りが単純なのが幸いして、「フレームワーク側が勝手に処理してるので手を出せない」という事は無かった。使いやすいとは言えないが、決して「作りが悪い」訳ではなかった・・・というのは当然作者の自画自賛なわけだけど。

この「自由度を高くしてアプリ側の制御範囲をなるべく残しておく」という「マージン優先」思想はXhwlayにも受け継がれている。オレオレフレームワークは作者が自分一人の為、機能強化が難しい。ならばいっそのこと、アプリ毎に変動幅が大きい部分は一切タッチせず、コア部分だけを好き勝手弄りやすいようにしておこうというのがPokoX以来の自分なりのフレームワークのポリシー。

2008年時点ではsymfonyやCakePHPなどが台頭し、かなりFW側でがっちり組んでしまっているが、その分Webアプリの作り方がパターン化され、おおよそFW側で殆どカバーできるようになったからだろう。また実際にWebアプリの制作を本業としているプロ達が多数開発に関わっているのだから、FW側の機能も殆どの場合に満足できる質量になったのだろう。

その後(2005 - 2007)

PokoXが一通り落ち着いた後は、memoriesというWikiソフトに舵を切り替えた。
memoriesはYakiBikiの前身で、完成しなかったソフト。

PokoXをベースとして、ADODB抽象化レイヤー、Smartyテンプレートエンジン、log4phpによるロガーを組み込んだ。
ユーザ管理・グループ管理・カテゴリ管理・Blog的なコンテンツ管理のベース部分まで作り込んでいた。
Webアプリとしての「元ネタ」部分は一通り出来上がっていたので、FW的に幾つかのサイトで使った。
完成しなかったのは、やはりWikiエンジンとACLの部分に悩まされていたから。

2006-2007年にPiece Frameworkを知り、Xhwlayの作成に舵を転換。
2007年後半、実際にあるサイトのマスタ管理画面でXhwlayを適用して実用を確認。YakiBikiへ継承。

2007年はsymfonyやCakePHPが浸透した年と記憶している。
そして2008年の1-3月にWebベンチャーでアルバイトをして、symfony/CakePHP/Akelosとかを弄る。

結局、自分の技術ではとてもじゃないが本職が束になって開発したFWに勝てない。
オレオレフレームワークに実に数年に渡りプライベートタイムを費やしてきたが、成果としては実を結んでいないのが実情。まぁXhwlayとYakiBikiが作れたからいっか。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 16:25:00
md5:9d08799f8cf36c5ade66563737ef2e25
sha1:b54c65919ebf259368500b42fdf6f4a395ab6ae4

日記/2007/02/25/findコマンドメモ  

所有者: msakamoto-sf    作成日: 2007-02-25 15:11:06
カテゴリ: Linux 

ファイル検索コマンドであるfindは重宝するが、中々使うコツが掴みづらい。自分もコマンドを極めているわけではないが、日常よく使用する例に絞って取り上げる。

ちなみに、以下に紹介するfindの各オプションは、同時に組み合わせることも可能である。

  • ファイル名が完全に分かっている場合は "-name" オプション

/opt/php ディレクトリ以下で、ファイル名が完全に分かっている場合の例:

$ find /opt/php -name cls_dbmgr.php
  • ファイル名が.tar.gzで終わっているものを検索したい場合は "-regex" オプション

/opt/ 以下で、拡張子が.tar.gzのファイルを検索したい場合の例:

$ find /opt -regex ".*\.tar\.gz$"
                   ^^^^^^^^^^^^^^ 正規表現を使用できる。
  • ディレクトリの一覧を取得したい。 "-type"オプション

/opt/php 以下のディレクトリの一覧を取得したい場合の例:

$ find /opt/php/ -type d
/opt/php/
/opt/php/libs
/opt/php/libs/poko
...
/opt/php/logs

"-type"は検索ターゲットのオブジェクトの種類を指定できる。自分が使用しているLinuxのfind(findutilsパッケージ:4.1.20)においては、以下の種類が利用可能である。

b ブロックデバイスファイル
c キャラクタデバイスファイル
d ディレクトリ
p 名前付きパイプ(FIFO)
f 通常のファイル
l シンボリックリンク
s UNIXソケット

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 15:13:01
md5:7efb4fb570d11da63de4f15b7b24093a
sha1:201dfff67f72dc01763d62b2aba24dba58580bcf

技術/HTML/tableレイアウト(IE6とFirefox1.5)  

所有者: msakamoto-sf    作成日: 2006-05-22 14:52:56
カテゴリ: HTML 

Webデザインで今も昔も非常に重要な要素である、tableのレイアウトについて気になる点があったので調査しました。


目的

table用のスタイルシートである「table-layout」プロパティを調査し、カラムの幅を固定できるようにする。カラムの幅はem, ex, pt, pxのいずれかで決定できるようにする。

Webデザイン系、業務アプリケーション系を問わず、tableのカラム幅の設定は頭痛のタネである。中に表示するデータの文字数や文字種によって様々に変動してしまうtableに対して、どうやって列幅を固定するか。そのための具体的な手法を調査することで、今後の開発時におけるHTMLレイアウト修正作業を軽減する。

基礎知識

table関連のスタイルシートプロパティ

http://www.htmq.com/style/index.shtml#tab

今回調査対象としたもののみを挙げる。

table-layout

auto
テーブル(表)全体を読み込んでから、各縦列の幅を決定して表示する。デフォルト。
fixed
最初の横一行を読み込んだ時点で、各縦列の幅を決定して表示を開始する。

border-collapse

collapse
隣接するセルのボーダーを重ねて表示する。
separate
隣接するセルのボーダーを間隔をあけて表示する。デフォルト。

他に以下のプロパティがあるが、IEに対応していなかったり使用頻度が著しく低かったりするため今回の調査では対象外とした。

caption-side
テーブル(表)のキャプションの位置を指定する
border-spacing
セルのボーダーの間隔を指定する
empty-cells
空白セルのボーダーの表示・非表示を指定する

スタイルシートにおけるサイズ指定の単位

今回調査対象とした四つの単位についてまとめる。

em
ブラウザデフォルトにおける、文字"M"の 高さ を基準とする。
ex
ブラウザデフォルトにおける、文字"x"(小文字のエックス)の 高さ を基準とする。
px
PCの画面を構成する要素、"ドット"を基準とする。画面の論理サイズで"1024ピクセル"といえば、すなわち1024ドット。
pt
実世界上の単位で、 72pt(ポイント) = 1 inch となる長さ。PCが画面上で扱うためには、 DPI(dots per inch) を通して変換する。
em, ex 指定に関する誤認識について

em, ex指定は文字Mあるいはxの 高さ を基準にしているのであって、幅を基準にしているのではない点に十分注意する必要がある。

通常、サイズ指定を考えるときは「このセルの幅は何文字か」という具合に桁数ベースで考える。もしもこのとき、em/exを幅の単位と考えて使用してしまうと、想定していた幅通りにならない。 桁数ベースで幅を決定するなら、高さと幅が同一の(ように見える)全角文字の等幅フォントを使用するほかない。(文字種も全角文字のみとなる)

pt <> px 変換

pt <> px 変換の中心となるのが、DPIである。 DPIはOSによって異なり、例えばWindowsであれば72DPI, Macであれば96DPIとなっている。 これより、以下の計算式が成立する。*1

1pt = 1/72 inch
1px(dot) = 1/72 (win) 1/96 (mac) inch
->
(win) 1px = 1/72 inch * 72 px = 1 pt
(mac) 1px = 1/96 inch * 72 px = 3/4 pt
win : mac = 1 : 3/4 = 4 : 3

よって、 macでの1ptはwinでの4/3ptになる。 ちなみにこれをpx単位で考えると、逆にwinでの1pxはmacでの3/4pxに相当する。

実はこれまでの計算はOS内部における論理的な扱いである。これを実世界のデバイスであるディスプレイに表示する場合は、 PPI(pixels per inch) が関わってくる。これはディスプレイにより変わってくる。

以上見てきたように ユーザーのOSやディスプレイのより、1ピクセルの現実世界における表示サイズが変わってしまう 点に十分留意する必要がある。

実験

実験内容

数種類のバリエーションのtableを作成し、Firefox 1.5 と IE6 とで表示を比較する。実際に作成したファイルを次のリンクに示す。

http://www.glamenv-septzen.net/medias/reports_2006052101_01.html

作成するテーブルのバリエーションの観点を以下に示す。

  1. "border-collapse: collapse;" バリエーション
    1. cellspacing属性× + cellpadding属性×
    2. cellspacing属性○ + cellpadding属性○
  2. "border-collapse: separate;" バリエーション
    1. cellspacing属性× + cellpadding属性×
    2. cellspacing属性○ + cellpadding属性○
  3. "table-layout: fixed;" バリエーション
    1. (table)width属性× + (td)width属性○
    2. (table)width属性○ + (td)width属性○
      1. tableのwidth属性 > tdのwidth属性の合計値
      2. tableのwidth属性 < tdのwidth属性の合計値
    3. table/tdの幅をstyle="width: **em;"によりem単位で指定するバリエーション
      1. 半角のみ
      2. 全角のみ
      3. 想定文字数を超えた場合(widthプロパティでem指定時)
      4. 想定文字数を超えた場合(width属性指定時)
      5. 想定文字数を超えた場合 + tdタグにoverflowプロパティ

実験結果

幾つか注目に値するバリエーションについて、FF1.5およびIE6での結果を載せる。

  • "border-collapse: collapse;"
    • FF1.5 : 画像/reports_2006052101_01ff15.jpg
    • IE6 : 画像/reports_2006052101_01ie6.jpg

FF1.5ではtdタグのborderがtableタグのborderを上書きしているように見える。一方のIE6ではその逆のように見える。枠線と、その中のセルを区切る罫線についてはデザイン上重要な要素であるが、ここまで挙動に違いがあると、border-collapseだけでFF1.5/IE6で同じ見栄えにするのは難しい。

  • "border-collapse: collapse;" + cellspacing属性○ + cellpadding属性○
    • FF1.5 : 画像/reports_2006052101_02ff15.jpg
    • IE6 : 画像/reports_2006052101_02ie6.jpg

これもFF1.5とIE6では全く挙動が異なる。

  • "table-layout: fixed;" + 想定文字数を超えた場合(widthプロパティでem指定時)
    • FF1.5 : 画像/reports_2006052101_03ff15.jpg
    • IE6 : 画像/reports_2006052101_03ie6.jpg

tdの幅を超えた部分の文字列をどうするかで、中身の文字列の種類に応じ、FF1.5/IE6でそれぞれ挙動が異なる。まとめると、次のようになる。

文字列種類 FF1.5 IE6
連続文字列 はみ出して表示 切り捨て
全角英語・日本語混在の連続文字列 文字種の切れ目を適当に折り返し表示 文字種にかかわらず折り返し表示
空白混じり 折り返して表示 折り返して表示

特に注意が必要なのが連続文字列で、FF1.5だとデフォルトでははみ出して表示してしまう。他の周りのTRやTABLEの属性指定やスタイル指定の影響がどう出るのかは不明だが、いずれにせよこの差異を認識していないと、頭痛のタネになることは間違いない。

結論

  • 列幅を固定するには、"table-layout: fixed;"が有効である。
  • W3Cの仕様上、文字の"幅"を基準として各種のwidthを決定することはできない。
  • 文字の"幅"を基準としたい場合、テーブルの各セルに表示する文字種を全角を基本とすることで、文字の高さ=幅*2と見なし、CSSでemを単位にすることである程度は指定可能である。
  • FF1.5とIE6とでは、border-collapse周りの枠線表示および連続文字列表示における挙動がまるで異なるので、注意と対策を要する。

雑感

MS-DOS/Windowsクライアント系の画面と、HTMLの画面はそもそも制御方法がまるで異なると言うことを理解して欲しい。
その上で、真実、 文字の幅・桁数を基準にして幅を「精密に」指定することは、HTMLでは「技術的に不可能」 のようである。

ただし、emやexというのは恐らく、どんな文字でもこの幅を超えることはないという基準点なのではあるまいか?であれば、ぴったり○○文字の幅という制御はできなくとも、"最大"○○文字まで入る、という使い方は十分に出来るはずである。精密に幅を指定するのが不可能であっても、最大文字数幅で合わせておけば、少なくとも途中で情報が切れてしまうことは避けられる。恐らく対応を迫られた場合、その辺りが妥協点となるのではないだろうか。

参考リンク

*1: macというのはOS9までのmacを指す。MacOS X 以降のmacや、その他のUNIX, Linux系OSについては未調査
*2: 見た目上の話。実際には異なる

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 15:00:48
md5:66be45ea260b1c0392dcf04c1c00106b
sha1:4075dbc24bde15e4d16f7cdc0bf68b9ef7bec89e

画像/reports_2006052101_03ff15.jpg  

所有者: msakamoto-sf    作成日: 2006-05-22 14:51:45
カテゴリ: HTML 画像 
画像/reports_2006052101_03ff15.jpg
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 14:52:02
md5:659cdf7ad8a200ef030f56003e7f0169
sha1:b59df7483fe2b39d9ee1fd2b465df0893eb68367

画像/reports_2006052101_03ie6.jpg  

所有者: msakamoto-sf    作成日: 2006-05-22 14:51:04
カテゴリ: HTML 画像 
画像/reports_2006052101_03ie6.jpg
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-23 14:51:25
md5:66d9d8b69c9c21a2b07a8d87dbce3257
sha1:d9569ed7842ac0c5501efa1b3c423f49e4afc618