Hatena::ブログ(Diary)

hnwの日記 このページをアンテナに追加 RSSフィード

[プロフィール]
 

2015年5月25日(月) PHP7で変わること このエントリーを含むブックマーク このエントリーのブックマークコメント

次の土曜日5/30のPHPカンファレンス関西2015で基調講演(10:30-11:15)をさせて頂くことになりました。タイトルは「PHP7で変わること——言語仕様とエンジンの改善ポイント」です。チケットは既に売り切れているそうですが、参加者の方は早起きして来て頂けると幸いです。


このところQiitaに「PHP7調査」というシリーズを連投していたのも発表を意識してのことです。PHP7の新機能を一つずつ実際に試してみて、その結果を簡単にまとめていました。


今回は発表前の区切りとして、私の書いたPHP7関連の記事・プレゼン資料を一覧形式でまとめなおしてみます。PHPカンファレンス関西2015ではこれらの内容を踏まえつつ、気になる点を重点的にお伝えしたいと考えています。


内部実装のリファクタリング

PHP7の目玉と言える、速度改善に関わる内容がほとんどです。


後方互換性を崩すような変更・廃止

今回のPHP7はメジャーバージョンアップということで、PHP5までの挙動を変更するような内容がたくさん採用されています。個人的な見解としては正しく整理されたような箇所が多く、実コードへの影響は軽微だと考えています。とはいえ、実際のところは移行してみないとわかりませんね…。


新しい構文・演算子の実装

マイナーバージョンアップでも新たな構文が入ることはありますが、今回はやけに量が多い印象です。メジャーバージョンアップということで皆が張り切ったのかもしれません。他の言語の影響が見え隠れするのも面白いですね。


新しい関数の実装・オプショナル引数の追加

これらはマイナーバージョンアップでも入るレベルの変更だと言えます。個人的にはCSRPNG関数PHPコアで提供してくれるのが大きいですね。


まとめ

上のリストは多いように思われるかもしれませんが、これでもPHP7の全てを網羅しているわけではありません。PHPカンファレンス関西では記事にしていない内容もお話しする予定ですので、上の記事を全部読んだ方もそうでない方もご期待くださいませ。

トラックバック - http://d.hatena.ne.jp/hnw/20150525

2015年5月24日(日) PHPで巨大な整数をカンマ区切りするのにnumber_format関数は使えない このエントリーを含むブックマーク このエントリーのブックマークコメント

PHPには、数値を3桁区切りで表示するための組み込み関数としてnumber_format()が用意されています。


number_format — 数字を千位毎にグループ化してフォーマットする


string number_format ( float $number [, int $decimals = 0 ] )


http://php.net/manual/ja/function.number-format.php


この関数は金額を表示するような場合に便利です。


<?php
$money = 1000;
printf("財布の中に%s円あります。\n", number_format($money));
/*
財布の中に1,000円あります。
*/

このように金額がカンマ区切りで表示されていると見やすくていいですよね。


ところで、このnumber_format()の第一引数はfloat型ですから、float型以外の引数が渡された場合はfloat型にキャストされてから処理されます。そのため、float型の性質を知らないと意外に思える結果になることがあります。


<?php
$money = 9007199254740995; /* 2**53+3 */
printf("財布の中に%s円あります。\n%d円ですよ?\n", number_format($money), $money);
/*
財布の中に9,007,199,254,740,996円あります。
9007199254740995円ですよ?
*/

今度は$moneyを非常に大きい整数にしてみました。大きいといっても64bit整数の範囲内ですので、64bit環境では正しく表現できる数です。実際、出力結果の2行目では代入した数がそのまま表示できているのがわかります。


一方、number_format()を通した結果は1円多い金額になっています。これはnumber_format()のバグではなく、浮動小数点数の性質によるものです。IEEE754倍精度浮動小数点数では2の53乗(およそ9000兆)までの整数を正しく表現できますが、それより大きい整数をキャストすると精度が落ちることがあるのです。


まとめ

9000兆を超える金額を扱うシステムでnumber_format()を使うと危険ということがわかりました。お金持ちの人は要注意ですね!


number_format()はオプショナルな第2引数を指定することで小数点以下も表示できますので、第1引数がfloat型なのは自然なことだと言えます。とはいえ、PHPプログラムだけ見るとfloat型が関係するようには見えませんから、わかりにくいバグの元になりそうですよね。


呼び出す関数の型宣言によってはエッジケースで予想外の挙動になることがありますよ、というのが本稿でお伝えしたかったことです。number_format()の場合は冗談で済む程度の内容だと思いますし、他の場合もおそらく無害なことが多いはずですが、世界のどこかで大障害の原因になっているかもしれません。また、PHP7からはスカラ型のタイプヒントが導入されますので、このような問題が今よりクローズアップされるかもしれません。

トラックバック - http://d.hatena.ne.jp/hnw/20150524

2015年4月19日(日) PHPのJSONライセンス問題が一応決着 このエントリーを含むブックマーク このエントリーのブックマークコメント

2012年頃に、PHPJSONエクステンションソースコード中に次のようなライセンス文言が含まれていると話題になりました。


The Software shall be used for Good, not Evil.

これはJSONライセンスと呼ばれるライセンスの一文です。「このソフトウェアを良いことに使うのはいいけど、悪いことには使っちゃダメ」といったところでしょうか。


これはフリーソフトウェアの定義に反しており*1、各種LinuxディストリビューションJSONエクステンションを配布できないことになるため、ちょっとした騒動になったというわけです。


本稿ではこのJSONライセンスへの対応が現在どうなっているかを紹介します。


各種Linuxディストリビューションの対応

PHPJSONエクステンションはjson_encode()やjson_decode()などの重要な関数を提供するエクステンションですから、ディストリビューションとしても提供しないわけにはいきません。


多くのディストリビューションでは、標準のJSONエクステンションを削除し、代わりにpecl-json-cという別実装をphp-pecl-jsoncやphp5-jsonといったパッケージ名で提供しています。


このエクステンションは、この問題が発生したあとでPHPコミッターであるRemi Colletさんが開発したもので、JSON-Cラッパーとして実装されています。


ただ、UTF-8以外の文字の取り扱いが標準のJSONエクステンションと異なるなど、ユーザー目線では不便も残っている状況のようです。pecl-json-cが気に入らなくて標準エクステンションを自前ビルドして使っている人もいるようですね。


ちなみに、自分の手元でどちらのエクステンションが使われているかはphpinfo()でわかります。JSONエクステンションの情報に「JSON-C version (bundled)」という表記があればpecl-json-c版です。


PHP本体の対応

この問題は「PHP :: Bug #63520 :: JSON extension includes a problematic license statement」でPHP本体のバグレポートとしても議論されていましたが、ずっと膠着状態が続いていました。


また、「PHP RFC: Switch from json extension to jsonc」というRFCPHP標準のJSONエクステンションpecl-json-cに差し替えようという提案もされましたが、結局議論がまとまらなかったのか、最新のPHP 5.6.8でもライセンス的に問題のあるコードが残っています。


一方で、PHP7ではjsondが標準JSONエクステンションとして採用されました。これはJakub Zelenka(@bukka)さんがre2cとbisonで新規実装したものです。


PHP7からはライセンス問題がなくなるよ!ということでPHP本体としても解決といったところでしょうか。上記バグレポートもjsondのPHP7への取り込みをもってcloseされています。


参照

*1https://www.gnu.org/philosophy/free-sw.en.htmlfreedom 0「The freedom to run the program as you wish, for any purpose」に反している

トラックバック - http://d.hatena.ne.jp/hnw/20150419

2015年4月1日(水) PHP 5.4.0から無限大==無限大になってた このエントリーを含むブックマーク このエントリーのブックマークコメント

本日はエイプリルフールなので、嘘でも本当でも誰も困らないネタを紹介します。


内容としてはタイトルの通りで、浮動小数点数の無限大とマイナス無限大に関する==の挙動がPHP 5.3.xまでとPHP 5.4.0以降で変わっていたという話題です。


$ php-5.3.29 -r '$x=INF;var_dump($x, $x==$x);'
float(INF)
bool(false)
$ php-5.4.0 -r '$x=INF;var_dump($x, $x==$x);'
float(INF)
bool(true)

このように、PHP 5.4.0以降は INF == INF、-INF == -INF という挙動になりました。


僕は過去の記事「「===」がtrueを返し「==」がtrueを返さないサンプル」で、当時のPHPINF === INF なのに INF != INF となるのは違和感があるという風に書きました。これが自然な方向に修正されていたというわけです。やったね!

2015年3月8日(日) マルチブート環境の全OSで同じBluetoothデバイスを使う このエントリーを含むブックマーク このエントリーのブックマークコメント

マルチブート環境(デュアルブート・トリプルブートなど)でBluetoothデバイスを使う際の話題です。


Bluetoothデバイスを利用する際は通常「ペアリング」という作業が必要です。これは、初回接続時に128bitのリンクキーを発行して両者で共有し、通信相手のBDアドレスに紐付けておく仕組みです。これにより、次回接続時は同じリンクキーを使ってお互いを認証することができますから、面倒な手続きなしに利用することができます。


ところで、この仕組みはマルチブート環境ではうまく働きません。マルチブート環境ではそれぞれのOSが同じBluetoothアダプタを共有するため、Bluetoothデバイスからは各OSを区別できないのです。


もう少し具体的に説明します。マルチブート環境で1つのOSからデバイスをペアリングしたあとで別のOSを起動した状況を考えてみましょう。このとき、デバイス側から見るとペアリングが済んでいるはずのBDアドレスなのに、OS側ではペアリングしていないためリンクキーがわかりません。再ペアリングをすれば新たなリンクキーが発行されて接続できるようになりますが、今度は最初のOSがリンクキーを共有していない状況になってしまいます。別のOSを起動するたびに毎回ペアリングすれば使えるものの、これではせっかくのBluetoothの利便性が台無しです。


これを解決するには、OSの管理しているリンクキーの情報を書き換えてやるしかありません。本稿ではMacOSXWindowsLinuxのトリプルブート環境でリンクキーを揃える方法を紹介します。


この内容はApple Support Communitiesの「Dual pairing in OS X and Windows」がベースになっていますが、僕は正解にたどり着くのに苦労したのでまとめ直してみました。


Macのマルチブート環境

Macに他のOSインストールするということではBoot Campが有名ですね。本稿の情報はそうしたMacOSXWindowsデュアルブート環境でも活用できるかと思います。


ちなみに僕はBoot Campを使わずにMacBook Air(2010 Late)にMacOSX 10.9、Windows 7(32bit)、Ubuntu 14.04LTS(64bit)の3つをインストールしています*1。先日SSDを256GBに換装したので試しにインストールしてみたのですが、思ったより実用的だと感じています。


今回の作業で、これら3つのOSすべてで同じNexus5経由のBluetoothテザリングができるようになりました。

続きを読む

*1:興味がある方は「refind macbook」などのキーワードでググってください

 
ページビュー
1487456