PerlとPHPにおける「リスト」概念の違い
$list->push('foo');
$list->push('bar','buz');
一瞬、「なんて美しい!」と思いました。
と同時に、「なんてPerl的な!」とも思いました。
「これじゃまるでPerlじゃないか」と。
私ならこういうインターフェイスにすると思います。
$list->push('foo');
$list->push(array('foo','bar'));
少し冗長ですが、こっちの方がPHPとしてしっくりきます(私にとっては)。
実際にはpush(array('foo','bar'))などとリテラルを渡すことはあまりなくて、push($hoge)とかpush($this->hoge())などと書くことになるでしょう。
この違いを突き詰めていくと、「PerlとPHPにおけるリストの考え方が違うんだ」という面白い事実を発見しました。
PHPプログラマとPerlプログラマのものの見方の違い
func('foo', 'bar');
このコードを見たとき、
PHPプログラマは「関数に2つの値を渡している」と考えます。
一方、
Perlプログラマも「関数に2つの値を渡している」と考えますが、
同時に「関数に1つのリストを渡している」とも考えます。
Perlにおいて、下記の2つのfunc呼び出しは同じ意味です。
func(1,2,3);
my @list = (1,2,3);
func(@list);
ところがPHPにおいては、下記の2つのfunc呼び出しは意味が異なります。
func(1,2,3);
$list = array(1,2,3);
func($list);
サンプルコード
Perl
use strict;
use Data::Dumper;
func(1,2,3);
my @list = (1,2,3);
func(@list);
sub func() {
print Dumper \@_;
}
---結果---
$VAR1 = [
1,
2,
3
];
$VAR1 = [
1,
2,
3
];
PHP
<?php
func(1,2,3);
$list = array(1,2,3);
func($list);
function func() {
$args = func_get_args();
print_r($args);
}
---結果---
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
)
)
もちろん、func_get_argsの戻り値に応じてif文で分岐すればPerlと同じ振る舞いをさせることはできます。しかしそこまでやってしまうとPHPらしくない気がします。
何故かというと、PHPの配列関数(array_*系の組込み関数)はPerlのような「引数のリスト渡し」をサポートしていないからです。
参考:Perlにおける配列とリストの違い
リストとは、スカラーの集合に順序を付けて並べたものです。PHPでも「array型のデータ」と「arra型の変数」は異なる概念です。
配列とは、リストを保持する変数のことです。
リストはデータであり、配列は変数であるという違いがあります。
--- 「初めてのPerl」3章 リストと配列
しかし「スカラーを並べたものをリストと呼ぶ」という考え方はない気がします。
結論
- PHPに「リスト」というものはない。ただarray型のデータとarray型の変数があるのみ。
- func_get_argsは@_の代わりにはならない。
「PHPらしい、らしくない」はあくまで私の主観です。
ご意見、ツッコミあればお願いします。