コッチの存在を忘れていた。

すっかり。mixiに再び引きこもって、こちらの存在をすっかり忘れていた。
まぁ、ブッチャケていうと最初に定義した自分像で書くのが面倒だったので、後回しにしていたらいつの間にか忘却の彼方ということに。


なので、そういう面倒な定義で書くのはもうやめようかと。


とはいえ実は、そもそも技術に関してやたらなことを書けないんですよね。
技術情報ををやたらなところで出してしまうと仕事上問題が出る可能性があるという現実(理由は深くは語れないが)と、自分の気付いたこと、知った技術などを(たとえ多くの人に既知の問題でも)アウトプットしていくのがユーザーコミュニティへの貢献となり、私人として望む形であるという理想の間で板ばさみ。

なので、ばれない範囲でコソコソと・・・やるつもりはないけど、アウトプットを制限されるのは本位ではないのでやりすぎない程度に書きます。


ただ、今の状態でそもそも書くことあるかなぁw

LL Ring[キミならどう書く 2.0 - ROUND 2 - ]がはじまっていた。

http://ll.jus.or.jp/2006/blog/doukaku2
で、Collazt予想なるお題が出ていた。
ネットサーフ中に見つけたので、素人ながらも、ちょっとPHPで書いてみた。
問題設定に従って$n=100になっているけれど、$nを換えればいくらでも上まで行く。

<?php

$n = 100;

$max_count = 0;
$max_answers = 0;
for ($i = 1;$i <= $n;$i++) {
	$appeared = array();
	$count = 1;

	$value = $i;
	while  ($value !== 1) {
		$value = ($value % 2) ? $value * 3 + 1 : $value / 2;
			
		if(isset($appeared[$value])) {
			echo "$value is cyclic\n";
			continue 2;
		} else {
			$appeared[$value] = true;
		}
		$count++;
	}

	$answer[$i] = $count;
	$max_count = max($max_count,$count);
}
$max_answers = array_keys($answer, $max_count);

echo "max g(k) is $max_count !\n answer k's \n";
print_r($max_answers);
echo "all k => g(k)\n";
print_r($answer);

?>

一応、重複や循環してしまい1にならない数が存在する可能性も考慮したので、やってることのわりに冗長になった。
ちなみに、n =100での回答は97が119回のステップ、というのが唯一で最高のようだ。


関数型言語、といわれたにも関わらずPHP。そして手続き型万歳な書き方。申し訳ない。
とかいって、間違ってたりして。
私はアホだからよく間違えるし・・・。


まぁ、間違ってても、挑戦することはいい事、と割り切っておこう。
トラックバック付けるの、ある意味怖いな・・・。

もうちょっと洗練させられる気がしてならないのだが、その場合キャッシュを使いまわして・・・ということになる。
n=100程度では、キャッシュを考慮する処理を加えるのと、少ない処理でループさせるのと、どちらが効率的なのだ?

$_POST、$_GETのよくある間違い

先に言っておくと、ある程度PHPに慣れている方には読んでも価値のない内容であることをお断りしておく。
それと、mixiでも一度書いたネタなので、そちらで見た人にもあまり意味はない。が、少しだけ内容は増えている。

※色々と指摘を受けたので、それを元に書き直し作業中。
名前は挙げませんが、指摘を下さった方の指導に感謝します。

まずは御託から

$_POSTや$_GETでのチェック判定の勘違いを時々見かける。
値がきちんと入っている場合はそれほどでもない。
その値に対してチェックをかけるせいか、意識がきちんと行き届いており、ほとんどの場合間違ってはいない。


問題は、「値が入力されているか?」という存在チェックだ。
きちんとできていないと、思わぬ落とし穴になる部分にも関わらず、よく間違ったスクリプトがある。


無論、使われていても問題ないような、取るに足らないものも多い。
それらは、挙動を理解したうえで適切な場合に用いるのならばそれほど問題にはならない。
だが、理解しないで使っていると、いつかどこかでほころびが出てしまう。そして、その問題に対処できなくなるのだ。


理解さえしていれば、「つい」使ってしまい、何か問題が起きても、すぐにその箇所だと気がつける。
(それでは手遅れだ、と言うこともあるのだが。最初から正しい物だけを使う癖を付ければよいのだ)
そういう意味で、取るに足らない挙動の細部の違いを理解しておくことは、意味のあることだろう。

やっと本題

さて、まず一番最初に頭に叩き込んでおいて欲しいのが、
「$_POSTも$_GETも、ユーザーからの入力は(通常なら)文字列型になる」
ということ(あくまでも、不正な入力でない場合だ。不正な入力の場合に他の型を持ち得るかは私は知らない。)
と、
PHPは弱い型変換をする言語である」
ということだ。


ぽかーん、とされるかもしれない。
そんなこと、当たり前だ。常識なのだ。
だが、意外と間違えている人が多いのだ。
説明自体は、ただの関数の挙動の話になるだろう。
どれも当たり前の話だが、$_POST、$_GETの挙動への先入観のためにその「当たり前」を勘違いしてしまう。


では、よくある間違いと、それがどういう部分でまずいのかを連ねていこう。
ちなみに、労力を減らすためtrim()は省略。$_POST、$_GETの両方は大変なので、$_POSTのみで。
(先頭にifが付いているのは、可読性のため。)


※考え落ちを指摘されてしまったが、POST値の判定をする前にPOSTされたかどうかの判定をしておかないと、NOTICEが出るものが多々。
申し訳ない限りです。とりあえず、POSTの値があるかどうかの判定、ということで読んでください。

if ($_POST["hoge"]) ...

暗黙の変換なので忘れがちだが、これはbooleanへのキャストが行われている。
以下の全てにわたってそうなのだが、これはPOSTされた値を直にキャストする。


従って、フォームの内容が空("")でも0("0")でも、falseになる。他の値が入っていれば、trueだ。
テキストフォームはいい。が、セレクトボックスでこれをやったら笑うしかない。
だが、これが使われている例は多い。

if (isset($_POST["hoge"])) ...

isset()は、その変数が定義されているかどうかだ。
つまり、name="hoge"でPOSTするフォームがある時点で、GETのストリングにhoge=がある時点で、値に関わらずこの判定はtrueだ。
従って、POST値の存在判定には使用できない。判定できるのは、POST動作がされたかどうかだ。
POST値の判定にこれを用いたら、まずい。

if (empty($_POST["hoge"])...

これが意外とフェイク。
empty()は空文字列がtrueになるが、困ったことに"0"もtrueとして扱うのだ。他の値が入力されれば、falseだ。
最初の単純なbooleanへのキャストの逆の動作をすることになる。

if (is_null($_POST["hoge"]) ...

これは・・・もう言うまでもないだろう。
何をPOSTしてもfalseだ。これもPOST動作が行われたかどうかを判定するのにしか使えない。

if (count($_POST) > 0)...
if (sizeof($_POST) > 0)...

こんなものも見かけた。個別チェックではないから、少し趣旨が違うのだが。
これも、出来ることはPOSTの動作判定だけだ。
buttonに名前が付いていれば当然それも拾うし、form名の指定がないので用途が狭い。
それに、どこから来たのかわからないPOSTもtrueで通してしまうのだ。
カッコよく書いたつもりが赤っ恥だ。
無論、POSTがされたかどうか自体を知りたいならこれらも良い。
が、値の判定時に使うものではない。

では、正しい判定法は何がある?

理屈まで含めてもっとも良いのは

if ($_POST["hoge"] === "")...

だ。なお、"0"と""はゆるい型変換でも等価とみなされないので

if ($_POST["hoge"] == "")....

でもよい。empty()の場合とは違うので注意。


また、少し知ったかぶって書こうとするなら

if (strlen($_POST["hoge"])...

が余計な記号がなくていいかもしれない。
このあたりは、文字列関数でなんとでも書きようはありそうだが。

最後に

また、どうでもいい事を長々書いてしまった。
まだ足りないものもあるだろうし、記述が完全でないものもあるだろう。
だが、これを通じて各種動作への配慮が行われるようになれば、それで本記事の役割は十分果たしたことになる。


本当に些細な事だが、こういった事にも自然と気を配れる用になるのは、大事なことではないだろうか。

なぜブログを作ったか

今までは、あえて閉じた場所でのみPHP等の話を書いていた。
なぜならそれは、どちらかと言うと自分自身のメモ的な意味合いが強かったということもあるし、その内容はほとんどが陳腐なものである、と感じていたためで、公開して議論するほどの事はないだろうと考えていたからだ。
それになにより、公にするのは逆に自分の無知をさらけ出す行為に等しいのではないか、と、そんな感覚に縛られていたのだ。


だが、最近様々な情報に目を配るようにし、ブログ上で議論が行われている現状を目にすることが多くなった。
そのような状況を目にするにつれ私は、自身が発見した問題や所持している情報を閉じた空間の中で停滞させるのはあらゆる面からいって良い事ではない、と考えるに至った。


私自身はたいした腕もなく、クリティカルな問題を指摘できる頭脳も知識もない。
下手をすると、問題に対して指摘した内容そのものが逆に間違っている可能性すらあるほどだ。
(これは謙遜ではなく事実だ。私のことをよく知る方は、私がそのような間違いを頻繁に犯す軽率な人間であることをよくご存知だろう。)

しかし、(有益かどうかはともかくとして)持っている情報は開示・共有するという行為は、少なくとも現状に対してマイナスに作用することはほとんどない、と私は考える。
たとえそれが、誤った情報であったとしてもだ。


正しい情報であれば、それが開示されることが結果として良い循環を生む事は、もはや考察するまでもない。
仮に誤った情報であったとしても、それを開示することで更なる有識者の方々から過ちを指摘してもらえる可能性が生まれる。
もしそうなれば、自分が正しい知識を得るのみならず、同じ誤解を持っていた別の人にとって、その誤解を訂正する機会を与えることになる。


もちろん、情報の開示が一時的に悪循環を生む可能性もあるが、中長期的に見ればその影響は取るに足らぬ物となるだろう。
そうでなければ、オープンソースプロジェクトが支配的な位置を占める現状は存在し得ないからだ。
従って、自分の得た技術関係の情報をオープンな場に晒す事は、自分にとっても他人にとってもけして無駄なことではない、と思い至り、このようなブログ作成に着手することにしたのである。

長いので要約

二言で言えてしまう。
「聞くは一時の恥、聞かぬは一生の恥」
「情けは人の為ならず」
この諺の示す意味の下、公開ブログを作ろうと思ったに過ぎない。

最後に

長々と書いたわりに・・・。
まとまりが無い?内容が薄い?
仰るとおりである。
ただ単に、下らない事を大げさに書くのが好きなだけの下らない人間なのだ、私は。


さて、登録初日からつらつらと書き連ねたが、まだまだはてダの操作や設定はテスト段階。
当面は、遊びも兼ねて雑記ばかりになるかもしれない。
ま、何事でも最初からものすごい事が出来る場合など滅多に無い。
色々と、弄くり倒して行こうと思う。

はてダ作成

とうとうはてなに登録。そして、はてダに手をだしてみた。

このブログ内での自分自身の簡単な定義

一応、ここは不特定多数の目に触れるオープンスペースであるので、一人称「私」、文体「である」調(常体)で統一して行こうと思う。
私のことを実際に知っている方々は少々違和感を覚えるかもしれないが、そのあたりは察していただきたい。
ただし、文体に関しては必ずしも常体にこだわるつもりはなく、あくまでもこのブログでのデフォルトを常体に置く、ということだ。
従って、状況に応じて「ですます」調(敬体)や口語体で記述が混在する可能性がある。
特に雑記およびコメントへの返信等ではそのような文体の混在の頻度は高くなると予想され、親しい知人からのコメントの場合、一人称も「私」でなくなる場合がある。

要約

読者に意味のない事を堅苦しく書いたが、ここで上記のように「このブログ内での自分像」を定義しておきたかっただけの事なのであまりお気になさらず。単に定義好きなのだ。
要約すると、人目に触れるから意識して硬めに文章を書くつもりだけど、先の事はわからないし、コメントは結局砕けて書くよ、ということだ。


三日坊主の危険性もあるが、出来る限り続けていくようにするつもりなので、今後ともどうぞ御贔屓に。