Explanation
说明
PHP has some holes in its' syntax and occasionally in development a programmer will step in them. This can lead to much frustration as these syntax holes seem to exist for no reason. For example, one can't easily create an array and access an arbitrary element of that array on the same line (func1()[100]
is not valid PHP syntax). The workaround for this issue is to use a temporary variable and break the statement into two lines, but sometimes that can lead to very verbose, clunky code.
PHP在其语法中有一些漏洞,偶尔在开发过程中,程序员会介入它们。这可能会导致很多挫败感,因为这些语法漏洞似乎无缘无故地存在。例如,一个人不能轻易地创建一个数组并在同一行*问该数组的任意元素(func1()[100]是无效的PHP语法)。此问题的解决方法是使用临时变量并将语句分成两行,但有时这会导致非常详细,笨重的代码。
Challenge
挑战
I know of a few of these holes (I'm sure there are more). It is quite hard to even come up with a solution, let alone in a code-golf style. Winner is the person with in the least characters total for all four Syntax Holes.
我知道其中一些漏洞(我相信还有更多漏洞)。甚至很难提出解决方案,更不用说代码高尔夫风格了。获胜者是所有四个语法孔中总字符数最少的人。
Rules
规则
- Statement must be one line in this form:
$output = ...;
, where...
doesn't contain any;
's. - 声明必须是这种形式的一行:$ output = ...;,where ...不包含任何;'s。
- Only use standard library functions (no custom functions or
eval
allowed) - 仅使用标准库函数(不允许自定义函数或eval)
- Statement works identically to the assumed functional of the non-working syntax (even in cases that it fails).
- Statement与非工作语法的假定功能相同(即使在失败的情况下)。
- Statement must run without syntax error of any kind with
E_STRICT | E_ALL
. - 语句必须在没有E_STRICT |的任何语法错误的情况下运行E_ALL。
Syntax Holes
语法孔
-
$output = func_return_array()[$key];
- accessing an arbitrary offset (string
orinteger
) of the returned array of a function - $ output = func_return_array()[$ key]; - 访问函数返回数组的任意偏移量(字符串或整数)
-
$output = new {$class_base.$class_suffix}();
- arbitrary string concatenation being used to create a new class - $ output = new {$ class_base。$ class_suffix}(); - 用于创建新类的任意字符串连接
-
$output = {$func_base.$func_suffix}();
- arbitrary string concatenation being called as function - $ output = {$ func_base。$ func_suffix}(); - 任意字符串连接被称为函数
-
$output = func_return_closure()();
- call a closure being returned from another function - $ output = func_return_closure()(); - 调用从另一个函数返回的闭包
2 个解决方案
#1
8
The only solution I see involves a temporary variable, so there is some (minimal) namespace pollution. Any way of tightening the temporary variable code would shorten all 4 of these:
我看到的唯一解决方案涉及一个临时变量,因此存在一些(最小的)命名空间污染。任何收紧临时变量代码的方法都会缩短所有这4个:
<?php
error_reporting(E_ALL | E_STRICT);
// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;
$output = ${!${''}=func_return_array()}[$key];
echo '1: ' . $output . "\n";
// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';
$output = new ${!${''}=$class_base.$class_suffix}();
echo '2: ';
var_dump($output);
// 3
$func_base = 'func_'; $func_suffix = 'return_array';
$output = ${!${''}=$func_base.$func_suffix}();
echo '3: ';
var_dump($output);
// 4
function func_return_closure() {
return function() {
return 'This is a closure';
};
}
$output = ${!${''}=func_return_closure()}();
echo '4: ';
var_dump($output);
Output:
输出:
1: hello
2: object(Thing)#1 (0) {
}
3: array(1) {
[0]=>
string(5) "hello"
}
4: string(17) "This is a closure"
#2
2
My solution is slightly longer than Shauns' but I thought I'd throw it up anyway. It should work identically to the original syntax, even in error cases. I'm basically exploiting the ternary syntax to allow two lines in one. I also changed the temporary variable to ${0}
instead of ${''}
since it save a character and variables that begin with numbers are not valid.
我的解决方案比Shauns略长,但我想我还是会把它扔掉。它应该与原始语法完全相同,即使在错误情况下也是如此。我基本上利用三元语法允许两行合二为一。我还将临时变量更改为$ {0}而不是$ {''},因为它保存了一个字符,而以数字开头的变量无效。
The below statements,
以下陈述,
line1;
$output = line2;
Is identical to the following statement for every possible case.
对于每种可能的情况,都与以下陈述相同。
$output = (line1)&&0?:(line2);
My solution:
我的解决方案
<?php
error_reporting(E_ALL | E_STRICT);
// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;
$output = (${0}=func_return_array())&&0?:${0}[$key];
echo '1: ' . $output . "\n";
// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';
$output = (${0}=$class_base.$class_suffix)&&0?:new ${0};
echo '2: ';
var_dump($output);
// 3
$func_base = 'func_'; $func_suffix = 'return_array';
$output = (${0}=$func_base.$func_suffix)&&0?:${0}();
echo '3: ';
var_dump($output);
// 4
function func_return_closure() {
return function() {
return 'This is a closure';
};
}
$output = call_user_func(func_return_closure()); //more straight forward
//$output = (${0}=func_return_closure())&&0?:${0}();
echo '4: ';
var_dump($output);
?>
#1
8
The only solution I see involves a temporary variable, so there is some (minimal) namespace pollution. Any way of tightening the temporary variable code would shorten all 4 of these:
我看到的唯一解决方案涉及一个临时变量,因此存在一些(最小的)命名空间污染。任何收紧临时变量代码的方法都会缩短所有这4个:
<?php
error_reporting(E_ALL | E_STRICT);
// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;
$output = ${!${''}=func_return_array()}[$key];
echo '1: ' . $output . "\n";
// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';
$output = new ${!${''}=$class_base.$class_suffix}();
echo '2: ';
var_dump($output);
// 3
$func_base = 'func_'; $func_suffix = 'return_array';
$output = ${!${''}=$func_base.$func_suffix}();
echo '3: ';
var_dump($output);
// 4
function func_return_closure() {
return function() {
return 'This is a closure';
};
}
$output = ${!${''}=func_return_closure()}();
echo '4: ';
var_dump($output);
Output:
输出:
1: hello
2: object(Thing)#1 (0) {
}
3: array(1) {
[0]=>
string(5) "hello"
}
4: string(17) "This is a closure"
#2
2
My solution is slightly longer than Shauns' but I thought I'd throw it up anyway. It should work identically to the original syntax, even in error cases. I'm basically exploiting the ternary syntax to allow two lines in one. I also changed the temporary variable to ${0}
instead of ${''}
since it save a character and variables that begin with numbers are not valid.
我的解决方案比Shauns略长,但我想我还是会把它扔掉。它应该与原始语法完全相同,即使在错误情况下也是如此。我基本上利用三元语法允许两行合二为一。我还将临时变量更改为$ {0}而不是$ {''},因为它保存了一个字符,而以数字开头的变量无效。
The below statements,
以下陈述,
line1;
$output = line2;
Is identical to the following statement for every possible case.
对于每种可能的情况,都与以下陈述相同。
$output = (line1)&&0?:(line2);
My solution:
我的解决方案
<?php
error_reporting(E_ALL | E_STRICT);
// 1
function func_return_array() { return array(0 => 'hello'); }
$key = 0;
$output = (${0}=func_return_array())&&0?:${0}[$key];
echo '1: ' . $output . "\n";
// 2
class Thing {}
$class_base = 'Thi'; $class_suffix = 'ng';
$output = (${0}=$class_base.$class_suffix)&&0?:new ${0};
echo '2: ';
var_dump($output);
// 3
$func_base = 'func_'; $func_suffix = 'return_array';
$output = (${0}=$func_base.$func_suffix)&&0?:${0}();
echo '3: ';
var_dump($output);
// 4
function func_return_closure() {
return function() {
return 'This is a closure';
};
}
$output = call_user_func(func_return_closure()); //more straight forward
//$output = (${0}=func_return_closure())&&0?:${0}();
echo '4: ';
var_dump($output);
?>