лямбда — Как передать метку в PHP?

История этой истории довольно длинная, поэтому, если говорить кратко, я знаю, что goto — это плохо, но у меня нет другого выбора, потому что … в PHP отсутствует оператор запятой.

У меня есть такой шаблон — обычная функция с точкой входа, заданной как метка, и внутри нее небольшая лямбда, которая должна goto к этой точке входа. Примерно так (неверный код):

  function water()
{
_Entry_point_2_0:
// ... some code
(function() { /*...*/ ;goto _Entry_point_2_0;})();
// ... some code
}

Я не могу просто перепрыгнуть через границы функций, поэтому моя следующая идея — вернуть метку из лямбды и использовать ее как «значение» для goto. Что-то вроде этого:

  function water()
{
_Entry_point_2_0:
// ... some code
goto (function() { /*...*/ ;return '_Entry_point_2_0';})();
// ... some code
}

Это не работает. Оценивая весь goto как строка eval ('goto _Entry_point_2_0;') тоже не работает.

Сумасшедшая часть в том, что я знаю лейбл заранее, поэтому вы можете спросить, почему я не могу написать такую ​​функцию целиком:

  function water()
{
_Entry_point_2_0:
// ... some code
(function() { /*...*/ ;})();
goto _Entry_point_2_0;
// ... some code
}

Проблема в логике — выполнение лямбды а также сделай 2 выражения сейчас, а не одно. И мне нужно сделать это в одном выражении — выполнить lambda, а goto должен быть упакован в одно выражение.

Я также не могу рекурсивно вызывать основную функцию, потому что в этом и заключается весь смысл этой работы, чтобы избежать рекурсивного вызова :-).

Каковы другие способы достижения этого?

ОБНОВЛЕНИЕ 1 Может быть, я перефразирую — то, что я хотел бы достичь с Goto continue my_function, Выполняется от или на границе внутренней функции (т.е. лямбда).

ОБНОВЛЕНИЕ 2 Основная цель состоит в том, чтобы перебрать основную функцию, поэтому она почти эквивалентна:

  function water()
{
_Entry_point_2_0: while (true)
{
// ... some code
continue (function() { /*...*/ ; return '_Entry_point_2_0'; })();
// ... some code
}
}

«Почти» по двум причинам. У меня все еще есть проблема с ярлыками точно так же, как раньше, и, более того, теперь у меня есть проблема, где добавить breakс петлей.

3

Решение

Возможно, вы пытаетесь решить ваше озадаченное решение, а не исходную проблему. Этот вопрос пахнет XY проблема.

_Entry_point_2_0:
// ... some code
(function() { /*...*/ ;goto _Entry_point_2_0;})();

Выглядит для меня как do while цикл:

do {
// ... some code
} while ((function() { /*...*/ ; return $k !== 0;})());

Теперь применение анонимной функции не допускается. Кроме того, параметры замыкания должны быть явно объявлены. Таким образом, мое решение должно быть написано так:

$k = 10;
$f = function() use (&$k) { /*...*/ ; return $k !== 0; };
do {
// some code
} while ( $f() );

Если вы хотите иметь «оператор запятой», вы просто создаете функцию, которая принимает любое количество аргументов и возвращает последнее:

function begin(){
return func_get_args()[func_num_args()-1];
}

begin(expression1, expression2, expression3); // ==> result of expression3

Все аргументы функции оцениваются, поэтому она делает то же самое, учитывая, что аргументы не зависят друг от друга.

1

Другие решения

Таким образом, вы не можете пропустить итерацию цикла из анонимной / лямбда-функции. Но вы можете вернуть значение, сравнить значения в основной функции, а затем пропустить итерацию оттуда. Звучит просто, правда?

Редактировать: если вы также хотите оторваться от ламбы, вы можете использовать ту же стратегию.

function water() {
$lambda = function() { /*...*/; };

while (true) {
// Call the lambda function and store the return value.
$return = $lambda();

// If the return value was 'skip this iteration', well... skip it.
// Note: I'd normally compare to false, null or similar.
if ($return == 'skip this iteration') {
continue;
}
elseif ($return == "we're done!") {
break;
}

// Do stuff here.
}
}

Мне нужно сделать это в одном выражении — выполнить лямбду, а goto должен быть упакован в одном выражении.

Итак, из вашего последнего комментария я теперь частично понимаю, почему у вас есть это требование. Но это все еще не совсем ясно. Вы написали скрипт для внедрения этого кода в некоторые ранее существующие функции и не знаете окружения. Но ярлыки goto уже на месте? В любом случае, возможно, ваша проблема так проста: вы хотите, чтобы код был единым линия только. Но это возможно, код Можно охватывать только одну строку в PHP. Это не самая красивая, но работает просто отлично.

function water() {
while (true) {
if (function() { /*...*/; }() == 'skip this iteration') { continue; /* Or goto */ }
// Do stuff here.
}
}
3

Я уверен, что это невозможно по замыслу.

Анонимные функции требует, чтобы все «состояние» передавалось через оператор использования. Вы не можете передать ярлык в качестве ссылки

Ошибка синтаксического анализа PHP: синтаксическая ошибка, непредвиденная ‘_Entry_point_2_0’
(T_STRING), ожидая ‘&’или переменная (T_VARIABLE)

Функция работает в своей области видимости без ссылки на метку, что означает, что ее необходимо каким-то образом вернуть.

Goto Docs иметь следующее

This is not a full unrestricted goto. The target label must be within the same file and context, meaning that you cannot jump out of a function or method, nor can you jump into one.

также недопустимо передавать переменную в goto

PHP Parse error:  syntax error, unexpected '$goto' (T_VARIABLE), expecting identifier (T_STRING)

Хотя все это, вероятно, хорошая вещь, поскольку goto предполагает, что логический поток неверен, вы сможете найти способ структурировать этот процесс, который является более основательным и не требует перехода.

Редактировать:

После обновления 2 почему бы не сделать

 if(your lambda() == something) {
Continue;
}

Извините написал код на моем телефоне. Это, кажется, делает то же самое и гораздо более читабельно

1

Вы можете использовать рекурсию:

function myFunc($i = 0) {
if ($i < 10) { //or any other logic to prevent "infinite loop"//Main code
myFunc($i++);
}
}
0
По вопросам рекламы [email protected]