超PHPerになろう

Enjoy PHP Programming

沖縄で変なコードを満喫してきた #omosiro_code

沖縄在住の新進気鋭の超絶技巧プログラマであるりゅうくん主催の会に参加してきました。

connpass.com

ずっとRubyで変なことをやってるhanachinさん、TRICK 2018で5作品入選で鮮烈な存在感を発揮したぺん!(tompng)さん、元同僚でギークハウス沖縄オーナーのさぼさんを始めとする東京と沖縄の変なプログラマが参加してくださいました。

主催のりゅうくんによるまとめ

ryu1kun.hatenablog.com

MatzLisp

話の枕として持ってきた記事はこれです。

なんかもともとは2013年6月にノリで書いたコードっぽくて、それをTRICK 2015に応募したけど玉砕しました。

qiita.com

僕のコードはインデントをくふうしただけの一発ねたなのですが、その年にはk-tsjさんのめっちゃ完成度が高いコードがMatz Lisp Awardとして受賞してたので玉砕は完全に納得です。

あとこのファイル名なのですが、脆弱性として利用可能な拡張子偽装ができるWindowsの「仕様」として著名なものです。

(let []) って書いてるあたりにClojureとして誤認されたさが垣間見えてますね。まともにClojureを書いてる人は絶対誤認しないですけど… このスクリプトの正しいファイル名は choise.[RLO]jlc.rb です。jlcが反転してcljに見えるんですね。UIぶっこわれてますけど。

一方でGitHub - Bug Bounty Program | HackerOneによれば、

Phishing using Unicode homoglyphs or RTLO characters

とのことで、これは脆弱性ではないらしいです。ふーーーん。

あと、いまこの記事を書くまで忘れてたんですが、上記の本のRubyによるScheme処理系をLispっぽいインデントで書いてました。完全に記憶から消し飛んでたよ。

github.com

Objective Programming Paradigm

自分が実装したDSLっぽいものだと最初期の2012年頃に書いたやつだった気がします。元ねたは当時たしか高専生だったLisper(Schemer)の某氏がTwitterとGistに投げてた言語を適当に再実装してみたやつです。未だにそうなのですが他人が文章で説明してるけど理解できないことが多いので、自分なりに再実装してみる癖があります。

メッセージ送信演算子の選択ですが、Rubyで再定義できる演算子のうち ** だけが右結合 だったので選びました。 (目的は美しいDSL設計ではなくObjective Programming Paradigmの概念実証だったので)

演算子の結合順序に関して気になるひとはこんな感じのクラスを定義してIRBとかで a * b * c とか a ** b ** c とかやって遊んでみてください。へんてこDSLを実装してどうしても右結合性が欲しくなったら ** 。おぼえておいてください。

class Foo
  def initialize(v)
    @v = v
  end

  def inspect
   "#<Foo, @v=#{@v.inspect}>"
  end

  def **(sbj)
    p [sbj, self]
    self
  end

  def *(sbj)
    p [sbj, self]
    self
  end
end

a, b, c = Foo.new(:a), Foo.new(:b), Foo.new(:c)

この元コードを書いた某氏は数年前にWeb上の一切合切の痕跡を断ってしまったのですが(そのあと一度だけ会ったことはある)、元気にしてるかなあ。奴とこの言語の話をしたことはないので、僕の解釈が合ってたのかはよくわからないです。

クラスローダーを使ったPHPメタプログラミング

PHPに詳しくないひとが多かったので前提から説明しました。

qiita.com

そしてPHPの全ファイルで機能する use の代替をクラスローダーで実現するやつです。

qiita.com

要はそれぞれの名前空間エイリアスを生やしまくることで実現します。実行時のパフォーマンスのペナルティは(たぶん)あまりないような気がします。ちゃんと計測してないけど。アルゴリズム改善の余地はあるかも。

PHPで無名再帰

PHPには use変数リファレンスを利用することで Closure再帰ができます。もちろんそれが常套手段なのですが、その制約を超えて再帰するテクニックを二つ紹介しました。

一つめにZコンビネータを利用する方法。これは不動点コンビネータの一つです。

ここで関数 f不動点とは、f(x) = x を満たすような x のことをいう。

不動点コンビネータとしてYコンビネータで、アメリカのシードアクセラレーター(ベンチャーキャピタル)として著名なY Combinator LLCの社名として有名です。

WikipediaにはJavaScriptでの不動点コンビネータの例があります。これはYコンビネータを正格評価の言語でも実行可能なように変形したものです。さらにそれをPHPで利用可能なようにしたものをライブラリにしてあります。

github.com

変なコード紹介の場としてはこっちを見せた方が盛り上がったかもしれませんね。

qiita.com

で、第三の無名再帰の方法として最近発見したのが無名クラスを利用する方法です。

はじめに、PHPのクラスに__invoke()マジックメソッドを実装すると、そのクラスのインスタンスオブジェクトを関数のように呼び出しができるようになります。そしてPHP7には無名クラスが導入されました。しかしながら無名関数には名前がないのに対し、無名クラスには名前があるのです。何を言ってるのか? __FUNCTION____METHOD____CLASS__ などのマジカル定数を出力するとわかります。

<?php

call_user_func(function(){ var_dump(__FUNCTION__); });
// string(9) "{closure}"

call_user_func(new class{ function __invoke(){ var_dump(__METHOD__); } });
// string(87) "class@anonymous\000/Users/megurine/Dropbox/junk/2019/06/qr_omSMR3.php0x10aede09e::__invoke"

これの性質を利用して無名クラスで call_user_func(__METHOD__) と書くと自分自身を呼ぶことができます。

無名関数の __FUNCTION__{closure}としか出力されないのに対して、無名クラスの __METHOD__ はファイル具体的なクラス名が含まれてます。……クラス名?そう、 class@ とか \0 とか / とか常識的なクラス名には含まれない文字がいっぱい入ってますがクラス名です。種明かしをすると無名クラスは無名ではなく、アクセスしにくい名前が付けられた、ただのクラスなのです。

正確には無名再帰ではないのですが実際無名関数と同じことが短く書けるので、まあまあ嬉しいですね。

ELVM

ELVMはShinichiro Hamaji(shinh)さんによる、多数の言語にコンパイルできるコンパイラインフラストラクチャです。

具体的な説明はshinhさんによるスライドと記事をお読みいただくのが良いです。

shinh.skr.jp

shinh.hatenablog.com

任意のプログラムをELVM IRで表現できれば、いわゆる難解プログラミング言語を含むバックエンドによって任意の言語に変換することができます。極めつけは8ccが移植されてるので、「Brainfuckで動くCコンパイラ」のような意味不明なものが実現されてます。実用性はともかくチューリング等価って本当に等価なんだなあと実感することができます。

前置きはさておき、2016年頃にPHPのバックエンドの実装を送ったときの昔話をしました。

github.com

一から書くのは難しそうだな…! と思ったのでJavaScript実装をPHPっぽく書き直すところから作業を始めました。

HTML+CSSチューリング完全

ぺん!さんのCSSだけで動くライフゲームが衝撃的すぎたので、(2012年に書いた記事なので自分の中では黒歴史に近いのですが)むかしの自分の記事をほじくり返しました。

こんな関係です。

dt.hateblo.jp

あと、フォントの合字で計算できるのでは? って話が出てたので、二年ほど前ににせねこさんが作ってたOpenTypeで万年カレンダー(2019/06のように並ぶとフォントでカレンダーが表示される)を紹介しました。

nixeneko.hatenablog.com

PHP voidクイズ

せっかくなので一年ちょっと前にTwitterに上げたねたの話をしました。

詳しいことはQiitaに書きました。そちらには上記のクイズをさらに意地悪にしたバージョンがあります。

qiita.com

このクイズは会場ではhanachinさん一人が正解されました。PHP予約語って難しいですね…!

まとめ

まとめも何もないのですが、ぺん!さんやhanachinさんの超絶技巧を間近で目の当たりにしたのは楽しかったです。あとりゅうくんのライブ記号プログラミングやばい。

最近沖縄界隈がめちゃくちゃ活発なので、興味を持った人はギークハウス沖縄もよろしく!

blog.geekhouse.okinawa

あとギークハウス沖縄の近くのチャーリー多幸寿(タコス)がめちゃくちゃおいしかったです。