Есть ли трюк в PHP 4 для реализации функций, возвращающих функции? Я ожидал, что следующий код будет работать:
function xxx($a) { return function($b) { print "a=$a, b=$b \n"; } } $f1 = xxx(1); $f1(2);
К сожалению, нет никакой удачи в PHP 4. Вероятно, это работает на PHP 5, но я ограничился PHP 4.
Я попытался обходным путем с OO, но снова потерпел неудачу (объявления классов не могут быть вложенными):
class Closure { function run($a) { print "raise: NotImplementedException, instead: $a\n"; } } class WantCheckNesting extends Closure { function run($a, $b) { class Nested extends Closure { function run($c) { print "a=$a, b=$b, c=$c\n"; } } $o = new Nested(); return $o; } } $d = new WantCheckNesting(); $e = $d->run(2, 3); $e->run(4);
Существует функция «create_function», но она очень ограничена: тело должно быть строкой.
Любые другие идеи?
Вероятно, вы лаете на неправильном дереве. PHP не является функциональным языком программирования. Некоторые изменения были сделаны начиная с PHP 5.3, но даже там у вас нет ожидаемых областей переменных, которые позволят вам делать то, что у вас есть в ваших примерах.
Единственными инструментами, которые вы можете использовать в PHP 4, являются create_function и некоторая изобретательность, чтобы написать определение функции в виде строки.
<?php function getMyFunc($a){ return create_function('$b', 'print "a='.$a.', b=$b";'); } $f1 = getMyFunc(1); $f1(2); ?>
… но даже если это просто для вашего опубликованного примера, это определенно нецелесообразно для более сложных ситуаций.
В PHP4 вы можете использовать переменные функции, подобные этому, если ваша функция уже определена в области (так что это не реальное закрытие).
ЭТО ДЕЙСТВИТЕЛЬНЫЙ КОД. ЭТО НЕ МОЖЕТ ИСПЫТАТЬ. ЭТО НЕ БЫСТРО (даже медленнее, чем закрытие, если это возможно). Это просто для удовольствия и доказывает, что это «как-то» может быть сделано, если вам действительно это нужно.
Требуется перезаписываемый каталог tmp /.
<?php function xxx($a) { $sid = GetUniversalSessionId(); $tmpfname= 'tmp/'.$sid.'.php'; $handle = fopen($tmpfname, "w"); fwrite($handle, '<?php function func_'.($sid).'($b) { $a='."'".str_replace("\'","\\'",str_replace("\\","\\\\",$a))."'".'; print "a=$a, b=$b \n"; } ?>'); fclose($handle); include($tmpfname); unlink($tmpfname); return 'func_'.($sid); } $result=xxx(32); $result(20); // This is just to get a unique identifier for every connection and every function call: // UNIVERSALSESSIONIDS v1.3 if(defined('UNIVERSALSESSIONIDS')) return; define('UNIVERSALSESSIONIDS', TRUE); function GetTimeStart() { return strtotime('2006-07-10'); } function GetUniversalSessionId() { return GetCodedSid(letterNumBase(),16); } function GetCodedSid($baseChars,$Pad=0) { $Zero=$baseChars{0}; list ($usec, $sec) = explode (' ', microtime()); $new_sid = ($sec-GetTimeStart()) . str_pad ((int)($usec * 100000000), 8, '0', STR_PAD_LEFT) . str_pad (rand (0, 9999), 4, '0', STR_PAD_LEFT); $new_sid=ConvertDecToAnyStr($new_sid,$baseChars); $new_sid=str_pad ($new_sid, $Pad, $Zero, STR_PAD_LEFT); return $new_sid; } function divide($decstr,$decnum) { $Start=''; $Result=''; $WRITE=FALSE; do { $Start.=substr($decstr,0,1); $decstr=substr($decstr,1); $DecStart=intval($Start); $Rest=$DecStart%$decnum; $PartDiv=($DecStart-$Rest)/$decnum; if($PartDiv>0) $WRITE=TRUE; if($WRITE) $Result.=$PartDiv; $Start=$Rest; } while ($decstr!=''); if($Result=='') $Result='0'; return array($Result,$Rest); } function bigBase() { global $gSavedBigBase; if(isset($gSavedBigBase)) return $gSavedBigBase; $BigBase=''; for($i=33;$i<=128;$i++) $BigBase.=chr($i); $gSavedBigBase=$BigBase; return $BigBase; } function letterNumBase() { global $gSavedBigBase2; if(isset($gSavedBigBase2)) return $gSavedBigBase2; $BigBase=''; for($i=ord('0');$i<=ord('1');$i++) $BigBase.=chr($i); for($i=ord('A');$i<=ord('Z');$i++) $BigBase.=chr($i); $BigBase.='_'; // for($i=ord('a');$i<=ord('z');$i++) $BigBase.=chr($i); $gSavedBigBase2=$BigBase; return $BigBase; } function ConvertDecToAny($decstr,$decbase) { $Result=array(); do { $Div=divide($decstr,$decbase); $decstr=$Div[0]; $Rest=$Div[1]; $Result[]=$Rest; } while($decstr!='0'); return $Result; } function ConvertDecToAnyStr($decstr,$baseChars='01') { $decbase=strlen($baseChars); $Result=''; do { $Div=divide($decstr,$decbase); $decstr=$Div[0]; $Rest=$Div[1]; $Result=$baseChars{$Rest}.$Result; } while($decstr!='0'); return $Result; } ?>