++[[]][+[]]+[+[]] = 10

「javascriptで ++[[]][+[]]+[+[]] = 10 になるのを説明できる人いる?」
って質問がStackOverFlowにUPされてたけど、
http://stackoverflow.com/questions/7202157/can-you-explain-why-10

その回答611が完璧!
これを理解するのに一番の肝は+[]で、

+[]を実行すると
1,[]のtoStringが実行され、+””と評価される。
2,さらにNumber型への変換がされ、0と評価される。

++[[]][+[]]+[+[]] を書き直すと

++[[]][0]
+
[0]

と評価され

++[[]][0]
+
[0]

その後

++([[]][0])
+
[0]

更に

([] + 1)
+
[0]

最後に

1
+
"0"
== "10"

で結果 10になる!

PHP5.4でコンストラクタを呼ばずにインスタンスが作れる

こんにちは。PHP5.4 ADVENTカレンダー13日目PHP5.4の新機能の一つ: アップロード進捗の取得に続いて14日目の担当のPaulです。

PHPはReflectionを使うことにより、privateとかprotectedとかのルールを無視して色々出来ます。
下はReflectionを使ってprivateメソッドを呼び出す例です。

class LockedDoor
{
    private function open()
    {
        return 'privateだけどドア開いちゃったよ!!';
    }
}

$refClass = new ReflectionClass('LockedDoor');
$refMethod = $refClass->getMethod('open');
$refMethod->setAccessible(true); //無理やりprivate解除
 //privateだけどobjectの外から実行できる
echo $refMethod->invoke($refClass->newInstance());

PHP5.4(Beta1)でReflectionClassにnewInstanceWithoutConstructorというメソッドが加わりました。
そうです!名前通りコンストラクタ使わずにインスタンスが作れるのです。

PHP5から__constructでコンストラクタが書ける様になりました。あれはあれでクラス名に依存しないので便利なんですけど、それのお陰でコピペのコンストラクタが増えたと思うのは僕だけでしょうか?
そういう問題には本来「親クラスを作って必要な処理はそこにまとめて、、、」やるべきなのでしょうが、「それが面倒だけど、コンストラクタの余分な処理をなんとかしたい!」って時に使えます。

例えば下の様なクラス

class MyClass
{
    private $lang;

    public function __construct() 
    {
        $this->lang = $_SERVER[HTTP_ACCEPT_LANGUAGE];
    }

    public function getLang() 
    {
        return $this->lang;
    }

    //意味ねーよ!
    public function setLang($lang) 
    {
        if ($this->lang == null) {
            $this->lang = $lang;
        }
    }
}

気持ちは分かるけどsetLangの意味がねーよ!と。

それもReflectionClass::newInstanceWithoutConstructorでなんとか出来ます。

$_SERVER[HTTP_ACCEPT_LANGUAGE] = 'ja';
$obj = new MyClass();
$obj->setLang('en');
echo $obj->getLang(), PHP_EOL; //jaのまま

$obj = (new ReflectionClass('MyClass'))->newInstanceWithoutConstructor();
$obj->setLang('en');
echo $obj->getLang(), PHP_EOL; //enと表示

個人的にはPHPは[スクリプト=コードが書き換えられる]ので、あまりReflectionに頼るのは如何なものかと思いますが、(Javaみたいにバイナリしかない場合はReflectionも必要だけど)
応急処置として頼りになるので、覚えておいて損はないと思います。

明日15日目は@srea2431さんです!お楽しみに!
あと、PHP5.4 ADVENTカレンダーまだまだ参加者募集中です!

traitでデザインパターン再考

こんにちは。php5.4adventカレンダーの10日目「PHP5.4でのhtmlspecialcharsの仕様変更とセキュリティ」を引き継いで11日目担当のPaulです。

PHP5.4で出てくるtraitこれのメリットとして、

  • mix-inができる。
  • あとでメソッド名再定義できるから、名前当たってもOK

みたいな事がRFCに書いてありましたが、

僕がRFCを眺めて感じたメリットは
親クラス作らなくても、実装の再利用が出来る!って事でした。

いや、ちゃんと親クラス作って、それを実装を追加したいクラスでextendして…
てやればタイプヒントの恩恵に預かれるのは分かってますが、、、
それをする余裕が無いことってありますヤン。
もちろんデリゲートも知ってますけど、あれはあれで追加のコード量が半端ないですヤン。
traitやったら、1個trait作っておけば、あとから実装追加したいクラスにuseなんちゃらって1行書くだけで済みますヤン。
それにもともと、タイプヒントでやってるクラスと、そうでないクラス両方に共通の実装ってなると何かと面倒でっしゃろ。

で、、、あとから実装を追加したくなるのってどのデザインパターンかなと思って
このサイトを眺めてたら

  • Decorator
  • Visitor
  • Observer

ぐらい?

この中で一番簡単そうなObserverパターンをtraitで書いて見ました。

まずはSubject trait

trait Subject {
    /**
     * Observer追加
     *
     * @param Observer $observer
     */
    public function attach(Observer $observer)
    {
        array_push($this->observers, $observer);
    }

    /**
     * SplSubjectと同じ名前で通知を定義
     */
    public function notify($funcName)
    {
        foreach ($this->observers as $key => $item) {
            $item->update([$this, $funcName]);
        }
    }
}

次はObserver

class Observer
{
    public function update(Callable $f)
    {
        $f();
    }
}
</code>

<p>最後にSubjectの実装</p>
<code>
class AKB 
{

    use Subject;                       //この2行を付け足すだけで
    private $observers = array(); //ObserverのSubjectになる。

    private $members = array();
    private $latest;

   
     /**
      * メンバーが追加される度に通知
      */
    public function addMember($member)
    {
        array_push($this-&gt;members, $member);
        $this-&gt;notify('getLatest');
    }
    
    /**
     * Observerで呼び出される。
     */
    public function getLatest()
    {
        echo $this-&gt;members[count($this-&gt;members) -1] . "が加わりました!" . PHP_EOL;
    }

}

実行すると

$o = new Observer();

$akb = new AKB();
$akb-&gt;attach($o);

$akb-&gt;addMember("前田敦子");
$akb-&gt;addMember("大島優子");
$akb-&gt;addMember("柏木由紀");
</code>
<p><br /></p>
<code>
"前田敦子が加わりました!"
"大島優子が加わりました!"
"柏木由紀が加わりました!"

僕的には作ったあと、「これ本当に便利になったかな?」って思ってしまいましたが、
既存のクラスに少し手を加えるだけ良いし、
例えばAKBクラスが親クラスを持っていたら今までは親クラスに変更を入れるかinterfaceをインプリメントするコードを書かなければいけなかったので、楽になったと思います!

次回12日目は@co3kさんです!お楽しみに

追記:12月12日 class AKBのところにバグが有ったので修正しました。

PHP5.4の新機能(その3)

1回目2回目だけではまだまだ書ききれないPHP5.4の新機能を紹介いたします。

1.配列のシンタックスシュガー

すっかり紹介を忘れてました。
他の言語のように配列の簡単な初期化がサポートされます。
(これを名前空間とか、無名関数の前にやってほしかったなぁ、、、)

$a = ['AKB', 'SKE', 'MNB'];
$b = ['チームA' => '倉持明日香', 'チームK' => '秋元才加', 'チームB' => '柏木由紀'];

そう、arrayとか書かなくて良いのですよ!  ”[]“だけで良いのですよ!!!

2.staticメソッドの可変呼び出し

波括弧を使いstaticメソッドの呼び出しを可変に出来ます。

class StaticClass {
public static $name = '峯岸みなみ';
public static function getName() {
return '峯岸みなみ';
}
}

$property = 'name';
echo StaticClass::${$property},PHP_EOL; //「峯岸みなみ」と表示される。(5.3でもOK)

$method = 'getName';
echo StaticClass::{$method}() ,PHP_EOL; //「峯岸みなみ」と表示される。(5.4からOK)

プロパティの呼び出しは5.3から{}が使えていたのですが、5.4からメソッドでも使える用になりました。

3.callableが型ヒントに使える

β1からタイプヒントにcallable型が使える様になりました。

//callable タイプヒント
function hi(callable $f) {
echo $f(), PHP_EOL;
}

class Human
{
public function hello() {
return "上からマリコ";
}
}

hi([new Human(), 'hello']); //「上からマリコ」が表示される。

$songName = function() {
return "Everyday カチューシャ";
};

hi($songName); //「Everyday カチューシャ」が表示される。

現在の実装として無名関数の親クラスはClojureでそれを型ヒントに使えるのですが、
将来変更される可能性があるのでより便利な型が追加されたようです。

4.コンストラクタからメソッドチェーンが実行可能

β2から追加された新機能です。

class Human
{
function __construct($name) {
$this->name = $name;
}

public function hello() {
return "Hi " . $this->name;
}
}

// 古い方法
$human = new Human("まゆゆ");
echo $human->hello();

// 新しい方法
echo (new Human("まゆゆ"))->hello();

phpは変数のスコープが他の言語と比べても広いので、
コンストラクタからメソッドチェーンや、配列をメソッドチェーンの様に利用
は変数の宣言を抑えて、名前の衝突を避けることができるので地味に嬉しいですね。

関数型プログラミングは早く普及しそう

関数型言語は普及するのか?みたいな議論がtwitterで話題になっていたので、自分の意見を述べたくなりました。

こちらの記事で

Java はやっぱり C と似ているんです。つまり構造化言語を書いていたプログラマ達からオブジェクト指向言語はすぐ近くに見えていたんですよ。

っていうのは凄く同意できて、僕自身もScalaやLispを読むと思わず目が丸くなりモニタの前で10分ぐらい硬直してしまうのですが、

この似ているのがとても厄介で、似ているがゆえに「オブジェクト指向言語で、オブジェクト指向でないコード」を散々見てきました。

例えばこんなコードです。

//荷物の大きさから送料を込みの値段を計算。
height = product.getHeight();
width = product.getWidth();
depth = product.getDepth();

//高さ・幅・奥行きどれかが1m以上であれば送料\1000
shippingCharge = 500;
if (hegiht > 100 || width > 100 || depth > 100) {
shippingCharge = 1000;
} else if (...) {
//省略
}
//商品の値段+送料
totalPrice = product.getPrice() + shippingCharge;

※1

オブジェクト指向が理解できている人であれば、上記のコードを見た瞬間に

totalPrice = product.getPriceWithShippingCharge();

みたいにリファクタリングしたくなりますよね。

でも、実際の現場ではリファクタリング前の「なんちゃってオブジェクト指向」の様なコードが本当に多い。※2
僕の経験値で言えば、経験3年ぐらいのPGの5人のうち4人は「なんちゃって」のコードしか書けてない。
経験5年以上の概要設計やマネジメントを任されてる人でさえ「なんちゃって」のコードを読んでもなんとも思わない人が多い。

なんで「なんちゃって」が問題にならないのかと言えば、
「オブジェクト指向でなくても機能要件を満たすことが出来る。」
からです。
リファクタリング前のコードは将来拡張性・保守性の懸念(別の送料計算方式の商品が来たら条件分岐どうするの)はあるのですが、
「送料込みの商品の値段を計算する」と言う、機能要件は満たしているのです。
逆に、リファクタリング後のコードは拡張性をポリモーフィズムでカバーできるので長い目で見たら優れているのですが、
それは「送料込みの商品の値段を計算する」要件とは何も関係ないのですね。

要するに

  • 構造化プログラミングは、それを覚えないと仕事にならないので絶対覚える
  • オブジェクト指向プログラミングは、それがなくても仕事になるので積極的に覚えない

だから、オブジェクト指向プログラミングはあまり普及してないというのが実感です。

同様の問題は関数型言語にも起こりえます。

下記の様な関数型言語らしくないコードも(Scala)※3

while(i < aList.length){
aList(i) += 1
}

上記をリファクタリングした関数型言語らしい書き方も(Scala)※3

var f = (x:Int) => x + 1
map(aList)(f)

どちらも機能要件(配列の要素に1をプラスする。)は満たしているのですよね。

だから、オブジェクト指向と一緒で
「関数型言語の普及より、関数プログラミングの普及は遅れる」と予想しています。

でも、「オブジェクト指向」よりは、「関数型プログラミング」の方が普及のスピードは早いと思います。
「非オブジェクト指向」における、「保守性」「拡張性」の問題は
「人員の投入」「プログラマに『頑張って』もらう」など、デベロッパ側に負担を押し付けるだけで何とかなるのですが、
「非関数型プログラミング」における、「マルチスレッド環境でのトラブル」「並列環境でのパフォーマンス問題」は
ソフトウェア利用者に「品質」として露見するので、深刻度が高いからです。

※1、「送料って住所で決まるんじゃないの」ってツッコミはご容赦お願いします。
※2、JavaやRubyのような「最初からOO言語」よりもPHP・Perlのような「後付OO言語」の開発者のほうが「なんちゃって」が多い気がします。
※3、ちょっと「非関数型」と「関数型」の例に自身がないです。もっと良い例があれば教えて下さい。

javascriptの論理演算子

今日は、javascriptの論理演算子について話します。
と、言うのも僕が普段使ってるPHP/Javaとjavascriptは論理演算子の返す値が違うのですね。

Mozillaのjavascriptのドキュメント(論理積)には次のように書かれています。

(Logical AND) Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.

要するに、expr1 && expr2 の時
expr1がfalsy(false判定)であればそれを返して、そうでなければexpr2を返すそうです。

PHPやJavaと違ってboolean値でないのがポイントで、
例えば

if(a){
 return a.method();
}else{
 return a;
}

は以下のように省略できます。

return a && a.method();

そしてjavascriptの論理和は以下のように説明されています。

(Logical OR) Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.

つまり、expr1 || expr2 の時
expr1がtruthy(true判定)であればそれを返して、そうでなければexpr2を返すそうです。
(&&の逆です。)

だからjavascriptでは以下のように変数を初期化することができます。

var myVar = input || default;

さらにテクニカルな使い方はこのサイトで解説されています。
http://addyosmani.com/blog/exploring-javascripts-logical-or-operator/
これRubyユーザであればa &&= b や a ||= b があるのですぐになじむかも知れませんが、
PHP使い/Java使いだと、混乱しそうですよね。

php5.4の新機能(Trait)

前回、Traitsについて書くと書きましたが、
それについて自分がしっかり理解できていなかったのですね、、、、

Traitsのサンプルをみると

trait A {
  public function smallTalk() {
    echo 'a';
  }

  public function bigTalk() {
    echo 'A';
  }

}

trait B {
  public function smallTalk() {
    echo 'b';
  }

  public function bigTalk() {
    echo 'B';
 }

}

 class Talker {
   use A, B {
     B::smallTalk instead A;
     A::bigTalk instead B;
   }
 }

$talker = new Talker();
$talker->smallTalk(); //bと表示
$talker->bigTalk(); //Aと表示

みたいな例が出てきますが、これって

class A {
  public function smallTalk() {
    echo 'a';
  }
  public function bigTalk() {
    echo 'A';
  }
}

class B {
  public function smallTalk() {
    echo 'b';
  }
  public function bigTalk() {
    echo 'B';
  }
}

class Talker {

  private $a;
  private $b;

  public function __construct() {
    $this->a = new A();
    $this->b = new B();
  }

  public function smallTalk() {
    $this->b->smallTalk();
  }

  public function bigTalk() {
    $this->a->bigTalk();
  }

}

$taker = new Talker();
$talker->smallTalk(); //bと表示
$talker->bigTalk(); //Aと表示

と変わらないんじゃねーの? と思ってたのです。
しかし、ここのサンプルをみて、Traitの意味が分かってきたのです!
https://wiki.php.net/rfc/traits

class Base {
  public function sayHello() {
    echo 'Hello ';
  }

}

trait SayWorld {
  public function sayHello() {
    parent::sayHello(); //親クラスが無いのにpearent?
    echo 'World!';
  }
}

class MyHelloWorld extends Base {
  use SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello(); // Hello World! と表示される

なるほど、これは他のクラスへのデリゲーションでは実現できない。

  • 継承はコードの再利用ができるけど、親クラスは一つのみ(ダイアモンド継承を避けるため)
  • デリーゲーションは、制約なく色々組み合わせる事が出けど、継承関係の再組み合わせは出来ない。

この問題を解決するための新しい単位が「Trait」か!

上記の例は、正直使いどころが直ぐに思い浮かばないけど、
下の例は結構便利そうですね。

trait Hello {
  public function sayHelloWorld() {
    echo 'Hello'.$this->getWorld();
  }

  abstract public function getWorld(); //実装を呼び出し側に任せる
}

class MyHelloWorld {
  private $world;
  use Hello;

  public function getWorld() {
    return $this->world;
  }

  public function setWorld($val) {
    $this->world = $val;
  }
}

上の例も、デリゲーションでもなんとかなるけど、abstractという形で実装の強制はできないし、
なによりデリゲーションよりずっとコード量がへるので便利ですね!

php5.4の新機能を2週にわたってレビューしましたが、いかがでしょうか?
他にこんな新機能も注目だよ!っていうのがあれば教えて下さい。