PHP 5.4 の配列Tips

PHP5.4 Advent Calendar 2011 4日目です。3日目@ooharabucyouさんでした。

2日目@yohgakiさんの記事で紹介されたように、PHP 5.4から [] で配列を定義できるようになります。大変めでたいですね。

この記事ではその他の配列まわりの変更を紹介したいと思います。


Array Dereferencingの採用

RFC: Function Array Dereferencing が取り込まれました。

これまでは配列を返す関数の返り値の一部だけが欲しいときでも、その値を一度変数に格納してから $foo[0] や $bar['baz'] としてアクセスする必要がありました。

Array Dereferencingによって、関数呼び出しの後ろに [] 演算子で配列の要素に直接アクセスできるようになります。

サンプル1

function foo($value)
{
    return [0 => 'bar', 'baz' => $value];
}

$obj = new stdClass;
$obj->qux = 'quux';
var_dump(foo($obj)[0]);
var_dump(foo($obj)['baz']->qux);
var_dump(explode(' ', 'The quick brown fox jumps over the lazy dog')[3]);

出力

string(3) "bar"
string(4) "quux"
string(3) "fox"

array_combine()が空の配列を受け付けるようになった

Changed array_combine() to return empty array instead of FALSE when both parameter arrays are empty. FR #34857

リンク先にあるコメントのように、何らかの解析結果から連想配列を作成したいといったケースで、リストが空かどうかのチェックをする必要がなくなります。


(クラス,メソッド)または(オブジェクト,メソッド)のペアからなる配列変数の後ろに()を付けて呼び出せるようになった

Added indirect method call through array. FR #47160

is_callable()に与えてtrueを返す変数は全て後ろに()を付けて呼び出せるようになったとも言えます。

これによって、コールバック関数を受ける関数をスマートに書けたりします。

サンプル2 冗長な記述

function hoge($callback, $arg1, $arg2)
{
    if (is_array($callback)) {
        list($object_or_classname, $method) = $callback;
        if (is_object($object_or_classname)) {
            return $object_or_classname->$method($arg1, $arg2);
        } else {
            return $object_or_classname::$method($arg1, $arg2);
        }
    }
    return $callback($arg1, $arg2);
}

サンプル3 call_user_func()

function hoge($callback, $arg1, $arg2)
{
    return call_user_func($callback, $arg1, $arg2);
}

サンプル4 コードが明瞭に

function hoge($callback, $arg1, $arg2)
{
    return $callback($arg1, $arg2);
}

配列をソートする関数のオプションに SORT_NATURAL と SORT_FLAG_CASE が加わった

Added support for SORT_NATURAL and SORT_FLAG_CASE in array sort functions (sort, rsort, ksort, krsort, asort, arsort and array_multisort). FR#55158

array_multisort()でもnatsort()natcasesort()相当の比較をしたいということで実装されました。

まずは特にフラグをつけずにarray_multisortにかけてみましょう。

サンプル5

$jojo = ['Jonathan', 'Joseph', 'Jotaro', 'Josuke', 'Jorno', 'Jolyne', 'Joshu'];
$php = ['PHP 5.3.7', 'PHP 5.2.7', 'PHP 5.2.17', 'PHP 5.3.9alpha1', 'PHP 5.4.0RC2', 'PHP 5.3.9RC2', 'PHP 5.4.0beta1'];

array_multisort($php, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Jotaro] => PHP 5.2.17
    [Joseph] => PHP 5.2.7
    [Jonathan] => PHP 5.3.7
    [Jolyne] => PHP 5.3.9RC2
    [Josuke] => PHP 5.3.9alpha1
    [Jorno] => PHP 5.4.0RC2
    [Joshu] => PHP 5.4.0beta1
)

普通に$phpを文字列として比較した結果が返ってきていますね。

次にSORT_NATURALをセットしてみましょう。

サンプル6

array_multisort($php, SORT_NATURAL, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Joseph] => PHP 5.2.7
    [Jotaro] => PHP 5.2.17
    [Jonathan] => PHP 5.3.7
    [Jolyne] => PHP 5.3.9RC2
    [Josuke] => PHP 5.3.9alpha1
    [Jorno] => PHP 5.4.0RC2
    [Joshu] => PHP 5.4.0beta1
)

数字が人にとって自然な順にソートされました。

さらにSORT_FLAG_CASEも加えてみましょう。

サンプル7

array_multisort($php, SORT_NATURAL | SORT_FLAG_CASE, $jojo);
print_r(array_combine($jojo, $php));

出力

Array
(
    [Joseph] => PHP 5.2.7
    [Jotaro] => PHP 5.2.17
    [Jonathan] => PHP 5.3.7
    [Josuke] => PHP 5.3.9alpha1
    [Jolyne] => PHP 5.3.9RC2
    [Joshu] => PHP 5.4.0beta1
    [Jorno] => PHP 5.4.0RC2
)

大文字/小文字を無視してソートされていますね。 この例だとuasort($ary, 'version_compare')でもいいじゃないかというツッコミは却下します。


まとめ

ここで紹介した新機能はPHPプログラムをシンプルに記述する上でちょっと役に立つと思います。

必ずしも短く書けるといいということではありませんが、プログラムの意図をより明確にできるのは良いことですね。

明日は@chobi_eさんです。

まだ枠はありますので、参加者も絶賛募集中です!

Lion / CS4 問題私的まとめ

自分に関係ありそうな箇所をAdobe公式の Mac OS X 10.7 Lion で確認されている問題 より一部引用。

B-6. Fireworks

Fireworks CS4 : カンバスで選択したカラーが、カラーピッカーに反映されません。

FireworksだけはCS5をピンでライセンス持ってるのでOK。

B-11. Illustrator

Illustrator CS3, CS4 : 印刷すると強制終了する場合があります。過去にそのシステムにはAcrobat 8.xがインストールされていました。

TechNoteの Mac OS X 10.7 Lionで印刷すると強制終了する にあるとおりに /Library/Printers/PPDs/contents/Resources/*.lproj を始末すればよい。

というかAcrobat 8.xをインストールしたことがないので問題なし。

B-14. Photoshop

Photoshop CS4 では、レイヤーパネル内でレイヤーをドラッグすると強制終了します。

Photoshop CS4 のレイヤーパネルでレイヤーをドラッグして移動すると強制終了する に解決方法が書かれている。

MacBook ProGPUの自動切り替えを有効にしているとアウトらしい。Mac miniMacBook Airでは問題ないのだろうか?

結論

自分が使う範囲ではなんとかなりそうなので、Photoshop / Illustrator CS4だけインストールしてみよう。

番外編

B-10. Flash Professional

Flash CS4 Professional は Mac OS X 10.7 で動作しません。Mac OS X 10.7 用 アップデーターの提供予定はありません。Mac OS X 10.7 環境では使用しないことを推奨します。

ノーコメント。

KQ on PHP

祭りレポートを書く前に@nvsoftsさんプログラミング言語KQPHP版を作ったので紹介してみようと思う。(→GitHub

KQ自体がBrainf*ckの方言なので、オリジナルの移植ではなくて以前に作ったBF処理系の焼き直し。ただしトークンをすげ替えただけでなくて、中身もちょっと整理している。

<?php
namespace KQ;

class Driver
{
    const DOOR_WILL_CLOSE = 'ダァシエリイェス';
    //snip.

とか、

$kq = new KQ\Driver();
echo $kq->doorWillClose(/*snip.*/);

とか、しょうもないネタを仕込んではいるけど、中身は方言をオリジナルBrainf*ckに変換、さらに実行コードに変換、簡易VMで実行と、BF処理系としての完成度はそれなりに高いと自負している。

ひとつ反省点を挙げるとすれば、方言とBFの変換部とBFコアは別クラスにすべきだった。あとは気が向いたら連続する+-をまとめる最適化を施してみたいが、たぶんずっとしない。

MTKit: TinyMT for Objectve-C

Tiny Mersenne Twister (TinyMT)Objective-Cラッパーを作った。→GitHub

TinyMTのAPIはすごくシンプルで特にラップしなくても容易に使えるのだが、Mac OS X / iOS向けにC標準の型でなくNSUIntegerやCGFloatを返すように作った。

特にiOSではコンパクトで質の良い疑似乱数生成器として有用だと考えている。

TinyMT.hをインポートして下記のように使う。

NSUInteger seed = 4649;
TinyMT *random = [[TinyMT alloc] initWithSeed:seed]
NSUInteger u = [random generate]; // [0..NSUIntegerMax]
CGFloat f = [random generateFloat]; // [0.0...1.0)
[random release];

名前だけ見るとフレームワークとして使えそうなのだけど、僕がXcodeでのライブラリ作りを習得していないせいもあって、今のところTinyMT.h, TinyMT.m, tinymt32.h, tinymt32.c, tinymt64.h, tinymt64.c をプロジェクトにコピーして使ってほしい。(iOSで使う場合は tinymt64.* は不要)

注意してほしいことがひとつ。ILP32環境では32bit版TinyMTを、LP64環境では64bit版TinyMTを使っており、32bit/64bitで同じ値をseedにしても生成される結果が異なる。32bit/64bit双方で同じ乱数系列を使いたい場合はTinyMTのC APIを直接使うべし。

TinyMT本体のライセンスはNew BSD Lisenceで、MTKitはMIT License。