PHP縛りゲーの世界

公開日:

東京都渋谷区GMO Yoursで開催された『第136回 PHP勉強会@東京』でライトニングトーク(5分)として発表しました。

Download PDF

スライドテキスト

Page 1

PHP縛りゲーの世界

第136回 PHP勉強会@東京

2019年3月27日 #phpstudy

Page 2

お前誰よ
うさみけんた (@tadsan) / Zonu.EXE

  • GitHub/Packagistでは id: zonuexe
    • ピクシブ株式会社 pixiv運営本部
  • Emacs Lisper, PHPer
  • Emacs PHP Modeのメンテナ引き継ぎました
    • 好きなリスプはEmacs Lispです
    • Qiitaに記事を書いたり変なコメントしてるよ

Page 3

待ってるにょ

Page 4

Page 5

Page 6

宣伝

Page 7

今週末は
PHPerKaigiです

Page 8

CIとか静的解析
の話をします

Page 9

チケットを持って ない人は今すぐ購

Page 10

さて
みなさん

Page 11

プログラミングは

好きですか?

Page 12

プログラミングは

楽しいですか?

Page 13

もっと楽しくし たくないですか?

Page 14

そうですね

Page 15

制約を課すべし

Page 16

ゲームをプレイする際、本来ゲーム側から は設定されていない制限(縛り)を自ら科 す事によって、より難易度の高いゲームを
プレイする事。
ニコニコ大百科

https://dic.nicovideo.jp/a/
%E7%B8%9B%E3%82%8A%E3%83%97%E3%83%AC%E3%82%A4

Page 17

他言語における

実例

Page 18

セミコロンレスJava

常識的なJavaは、式文の

末尾にセミコロン(;)を要求

ところが、工夫することで ;
の挿入を回避して

コードを書くことが可能

Page 19

Pythonワンライナー

Pythonはインデントベースの 文法(オフサイドルール)を持 つため、改行を要求する文法
が多い

……が、さまざまなテクを駆 使することでこの制約を回避

Page 20

それならPHPは

Page 21

セミコロンレスPHP

PHPもJavaと同じく式文の末 尾にセミコロン(;)を要求する

だが実はPHPは ?> 直前の ; を
省略できる

?> も禁止することで成立する

Page 22

ワンライナーPHP

PHPは改行が文法的な意味を

(ほぼ)持たず ; で区切って

複数の式文を一行に書ける

Pythonと同等の難易度には

ならない

Page 23

どうしよう

Page 24

🤔

Page 25

🤑

Page 26

Page 27

PHPにおける $ とは

言わずと知れた変数のシンボ
ル(sigil)

おそらくPerlに由来するが、 Perlの意味とはまったく異なる

実際いろんなところで必須

Page 28

PHPにおける $

<?php

function foo($a, $b) {
$name = "hoge"; // 変数代入
var_dump($_SERVER); // ← スーパーグローバル変数

foreach (piyo() as $p) { // ← 省略できない echo $piyo->$name; // ← 可変プロパティ

}
}

Page 29

どうしよう

Page 30

(2回め)

Page 31

変数を利用できない= 状態の更新ができない

Page 32

🙃

Page 33

大丈夫です

Page 34

$なしで意外と

書けます

Page 35

FizzBuzzは

書けます

Page 36

どうすんの

Page 37

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);

Page 38

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);

Page 39

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);

Page 40

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);

Page 41

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);

Page 42

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);

Page 43

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);

Page 44

変数禁止って言ってんの

func_get_arg(0)

使ってるのずるくね?

Page 45

ずるい

とってもずるい

Page 46

しかしfunc_get_arg()を

禁止すると関数が完全に利用不 能になるので難易度急上昇↑↑

Page 47

今回は妥協

Page 48

今回は再帰呼び出しする
ことで状態更新を回避

Page 49

さらなる難易度を
求めるあなたへ

Page 50

難易度を下げる関数を禁止

状態を持てる関数

APCu, ,

getenv() ini_get()

変数テーブルの操作

,
compact() extract()

Page 51

難易度を下げる関数を禁止

定数の動的定義

,
define() constant()
更新不能のグローバル変数と
して状態を持てるため

禁止する文字を増やす

とか : とか(両方は重い)

{}