型安全とは何だろうと思い調べてみた

「型安全」とは何だろう、と気になったので、型安全について書かれたQiitaの記事を読んでみた。
分かったことを、こちらにまとめておこうと思う。

型安全について

型を付けるか付けないか、という事でいろいろと意見があるらしい。
どちらにも利点があり、

型を付ける場合は、厳密な型付によって大きな問題になる前にエラーを特定できるようになる。
型を付けない場合は、型付をしない事でコード量が減り、記述がシンプルになる。

PHPは型が無いのだが、そういう言語は実行時に型を推論している。
このような言語は「動的型付け言語」と呼ばれるらしい。
逆にコンパイル時に型付するものは「静的型付け言語」と呼ばれる。

型安全性が低い言語は引数の指定を間違えてもエラーにならない。

//正しいコード
setUserName("tomo", 12)
//エラーになるべきコード
setUserName(12, "tomo")

上記のコードでは、型を認識していればコンパイルの時点でエラーを出力する。
C/C++PHPはキャストができエラーも吐かないので型安全とは言えないらしい。
型安全性の低い言語はあまり使いたくないなぁと思ったのだが、私の覚えた言語は全てキャスト変換できるので、型安全と言えないかもしれない。
キャスト変換ができないから「型安全な言語」というわけでは無いだろうが、キャスト変換できない言語にも触れておこうと思った。

一応、PHPでもPHP7からは型の指定ができるようになったようなので、そちらを触るというのも良いかもしれない。

PHP7でできるようになったことは以下のとおりである。

  • 厳密な型チェックモードに設定できる
  • 関数やメソッドの戻り値の型を指定できる
  • 引数に型を指定できる

注意する点としては、スカラ型の指定をする方法はPHP5とPHP7では互換性が無いこと。
PHP7が広まるまでは、自分の中だけでこの書き方を使う程度に控えておく必要がある。

蛇足

この記事を読んで初めて知ったのだが、以下のようにPHPで計算をすると全てのオペランドはfloatとして評価されるらしい。

$v = 3 + 1 * 0.1

C言語を使っていた時は、int型を使って小数点以下を切り捨てたりしていたのだが...
それを考えると、型付けできる方が良いような気がしてくる。

もう一つ知ったことがある。
PHPでも構造体(もどき)が作れるらしい。

class Controller
{
    function echoText()
    {
        echo "HELLO!!!!!";
    }
}
$obj = (object)["name"=>"tomo", "age"=>12, "Controller"=>new Controller];

var_dump($obj);
echo "<br>";
echo $obj->name . "<br>";
echo $obj->age . "<br>";
echo $obj->Controller->echoText();

出力結果は以下の通り

object(stdClass)#3 (3) { ["name"]=> string(4) "tomo" ["age"]=> int(12) ["Controller"]=> object(Controller)#2 (0) { } } 
tomo
12
HELLO!!!!!

こんな事をしなくてもクラスを作れば良いような気もするが、クラスを作る程でもない時もあるだろう。
覚えておいて損はないと思う。

参考

PHPの型と型安全について(PHP7からのPHPプログラミング) - Qiita

PHP備忘録を読んで

PHP備忘録 - QiitaというQiitaの記事をを読んだので、自分なりに分かったことをまとめてみようと思う。

PHP備忘録について

忘れないよう備えた記録という事だが、今年phpを始めたばかりの私にとっては覚えておくべき事が分かってとてもありがたい。

//配列にキーとバリューを指定
$array = array(
    "foo" => "bar",
    "bar" => "foo",
);

添え字は数字というのが私の中での基本だったのだが、phpを始めてから添え字に文字列を使うことが増えた。
確かに後で読み返した時、非常に分かりやすい。

配列に何か値を入れようとしているけど、何の値を入れているんだろう?

そんな事が減った。

添え字が数字じゃないのに、どうやってループを回すんだろう?
と思ったこともあったが、それはforeachという存在により解決した。

//配列の数だけ繰り返し (配列 as $配列の要素)
$array = array(1, 2, 3, 4);
foreach ($array as &$value) {
    $value = $value * 2;
}
unset($value);

上記のforeachの使い方しか知らない時は、まだ「添え字は数字」という考えを持っていたが、

// これならキーも取得できる
foreach ($array as $key => $value) {
}

この存在を知ってからは、「数字にこだわる必要も無いか」と思えるようになった。
おかげで、コードが少し見やすくなった。

最初、この記事のforeachのコードが少しおかしいと思ったのだが、参照渡しという方法を使っているらしい。

そこで、参照渡しに興味を持ったので少し調べてみた。
これまでC言語を使っていたので、ポインタと同じものだと思っていたが、phpの場合はC言語のポインタと少し違う挙動をするらしい。

これからphpを使っていくので、こちらにメモしておこうと思う。

phpの参照渡しについて

配列の要素のポインタを他の変数に代入すると、その要素の方はポインタ型に変換される

初めて見た時、何を言っているのか分からなかった。
理由は以下の通りである。

<?php
 
$array = array(1,2,3);
 
var_dump( $array );
$ref = &$array[1];
var_dump( $array );
 
?>

これを実行してみると

$ php -r '$array = array(1,2,3); var_dump( $array ); $ref = &$array[1]; var_dump( $array );'
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
array(3) {
  [0]=>
  int(1)
  [1]=>
  &int(2)
  [2]=>
  int(3)
}

となる。
array[1]の型が変わっている。

普通の変数の場合でも試してみる。

<?php
$v = 1;
$ref = &$v;
var_dump( $v );
?>

出力結果は以下の通り

$php -r '$v = 1; $ref = &$v; var_dump( $v );'
int(1)

型は変換されていない。

以下のコードも試してみる。

<?php
$a = 1;   // $a は 1
$b = &$a; // $b は $a の参照
$c = $b;  // $c はどうなる?
$c = 2;
 
print "${a}\n"; // これが1なら$cは参照、2なら$cは値ということになる
?>

出力結果は

$ php -r '$a = 1;$b = &$a;$c = $b;$c = 2;print "${a}\n";'  
1  

不思議な事に$aの参照が$cに渡されていない。
この場合は値が渡されるようである。

見やすさという観点だけでなく、phpで参照渡しは積極的に使うべきでは無いのかもしれない。

これを紹介していたブログには、「初心者はPHPをやるべきでは無い」と書かれていた。


きっちり書きたいときはC、JAVAPython
ゆるく使いたいときはC#RubyPerl
プログラミングという行為自体で遊びたいときはHaskellScalaClojure


分からなかった部分

分からない部分があったので、書かれていたものをそのまま記述しておこうと思う

$hoge = "this is hoge";

function &fuga() {
    return $this->value;
}

$fuga =& fuga();
$fuga = "this is fuga";
var_dump($hoge);//"this is fuga";

この辺は動的プログラミングとかで地味に効いてくる。
関数名と返り値取得の両方に&が必要、との事。クラスで可変となるプロパティ部にアクセサつけたりとかそういう感じの時何かと便利。

受け取るときに&抜いたら参照じゃなくなる辺りとかも便利だと思う。


  • 動的にプログラミングとかで地味に効いてくる
     →具体的にどんなところに効いてくるのだろう
  • クラスで可変となるプロパティ部にアクセサ付けたりとかそういう感じの時何かと便利
     →どんな状況なのだろうか、どんな感じに便利なのだろう 
  • 受け取るときに$抜いたら参照じゃなくなるあたりとかも便利だと思う
     →それができると何ができるようになるのだろう

上の3点が分からなかったので、今後も調べてみようと思う

参考文献

PHP備忘録 - Qiita

PHPとかいう糞言語|いんまのブログ

forの公式通りの最適化 at 低回数 を読んで

「forの公式通りの最適化 at 低回数」というQiitaの記事を読んでみて、自分なりに分かったことをまとめておきたいと思う。

私がPHPのコードを書くとき、いつもfor文を使いたくなる。 C言語Javaを使っていた時、いつも使っていたからだ。要は「慣れているから」使っている。比較する時に「==演算子」を使ってしまうのも、同じ理由である。

  • for文とforeach文の速度の比較結果はforeach文の勝利
  • 「==演算子」と「===演算子」の比較結果は「===演算子」の勝利

この記事に、for + countの表記方法が書いていた。私はこの書き方が好きである。 全ての配列に対して慣れているfor文を使う手段として、私の中では画期的な方法なのである。

  • foreach文との比較結果、foreach文が圧勝

悲しい...

一応言っておくと、私がコードを書く時、「最適化」を意識して書こうとはしている。しかし、それは最初だけで、だんだんと「これくらい良いか」、「面倒だし」、と言って途中からおろそかにしてしまう。 いつも最初に面倒くさがるのはfor文である。これくらいのループ回数ならあまり差が出ないだろう、と言ってついさっきまで心がけていた制約を緩めてしまう。 悪い癖である。

この記事を読んで初めて知ったこと

  • for文よりforeach文を比べるとforeach文の方が速い
  • echoとprint比べるとechoの方が速い
    • printは返り値があるため返り値の無いechoより遅くなってしまうらしい
  • 「==演算子」と「===演算子」を比べると「===演算子」の方が速い
    • 倍近くの差が出るらしい(逆だと思っていた)
    • 型比較もしてくれるので、「===演算子」を使っていくべきだろう

参考文献

forの公式通りの最適化 at 低回数
http://qiita.com/khsk/items/02ace94123baf516c676