Page 1
PHP縛りゲーの世界
第136回 PHP勉強会@東京
2019年3月27日 #phpstudy
公開日:
by USAMI Kenta @tadsan
に東京都渋谷区のGMO Yoursで開催された『第136回 PHP勉強会@東京』でライトニングトーク(5分)として発表しました。
PHP縛りゲーの世界
第136回 PHP勉強会@東京
2019年3月27日 #phpstudy
お前誰よ
うさみけんた (@tadsan) / Zonu.EXE
待ってるにょ
宣伝
今週末は
PHPerKaigiです
CIとか静的解析
の話をします
チケットを持って ない人は今すぐ購
入
さて
みなさん
プログラミングは
好きですか?
プログラミングは
楽しいですか?
もっと楽しくし たくないですか?
そうですね
制約を課すべし
ゲームをプレイする際、本来ゲーム側から は設定されていない制限(縛り)を自ら科 す事によって、より難易度の高いゲームを
プレイする事。
ニコニコ大百科
–
https://dic.nicovideo.jp/a/
%E7%B8%9B%E3%82%8A%E3%83%97%E3%83%AC%E3%82%A4
他言語における
実例
セミコロンレスJava
常識的なJavaは、式文の
末尾にセミコロン(;)を要求
ところが、工夫することで ;
の挿入を回避して
コードを書くことが可能
Pythonワンライナー
Pythonはインデントベースの 文法(オフサイドルール)を持 つため、改行を要求する文法
が多い
……が、さまざまなテクを駆 使することでこの制約を回避
それならPHPは
セミコロンレスPHP
PHPもJavaと同じく式文の末 尾にセミコロン(;)を要求する
だが実はPHPは ?> 直前の ; を
省略できる
?> も禁止することで成立する
ワンライナーPHP
PHPは改行が文法的な意味を
(ほぼ)持たず ; で区切って
複数の式文を一行に書ける
Pythonと同等の難易度には
ならない
どうしよう
🤔
🤑
$
PHPにおける $ とは
言わずと知れた変数のシンボ
ル(sigil)
おそらくPerlに由来するが、 Perlの意味とはまったく異なる
実際いろんなところで必須
PHPにおける $
<?php
function foo($a, $b) {
$name = "hoge"; // 変数代入
var_dump($_SERVER); // ← スーパーグローバル変数
foreach (piyo() as $p) { // ← 省略できない echo $piyo->$name; // ← 可変プロパティ
}
}
どうしよう
(2回め)
変数を利用できない= 状態の更新ができない
🙃
大丈夫です
$なしで意外と
書けます
FizzBuzzは
書けます
どうすんの
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
'Fizz', null, null];
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
'Fizz', null, null];
定数定義 ($不要)
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null,
無名関数を起動
'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
'Fizz', null, null];
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
FizzBuzzのロジック
'Fizz', null, null];
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
100から0になるまで、
'Fizz', null, null];
自分自身の関数を呼び出す
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
'Fizz', null, null];
FizzBuzzをプリント
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
PHPにおける $
<?php
const FB = ['FizzBuzz', null, null, 'Fizz', null, 'Buzz', 'Fizz', null, null, 'Fizz', 'Buzz', null,
'Fizz', null, null];
引数をとる
call_user_func(new class { function __invoke() {
if (func_get_arg(0) -1 )
call_user_func(__METHOD__, func_get_arg(0) - 1); echo FB[func_get_arg(0) % 15] ?? func_get_arg(0), "\n";
}}, 100);
変数禁止って言ってんの
に
func_get_arg(0)
使ってるのずるくね?
ずるい
とってもずるい
しかしfunc_get_arg()を
禁止すると関数が完全に利用不 能になるので難易度急上昇↑↑
今回は妥協
今回は再帰呼び出しする
ことで状態更新を回避
さらなる難易度を
求めるあなたへ
難易度を下げる関数を禁止
状態を持てる関数
APCu, ,
getenv() ini_get()
変数テーブルの操作
,
compact() extract()
難易度を下げる関数を禁止
定数の動的定義
,
define() constant()
更新不能のグローバル変数と
して状態を持てるため
禁止する文字を増やす
とか : とか(両方は重い)
{}