Search code examples
phplambdagoto

How to pass label in PHP?


The background of this story is pretty long, so to keep things short -- I know goto is bad, but I have no other choice, because... PHP lacks comma operator.

I have such pattern -- regular function with entry point given as label, and inside it a small lambda which needs to goto to that entry point. Something like this (incorrect code):

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

I cannot just jump across the function boundaries, so my next idea is to return the label from the lambda and use it as "value" for goto. Something like this:

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

This does not work. Evaluating entire goto as a string eval ('goto _Entry_point_2_0;') does not work either.

The crazy part is I know the label in advance, so you can ask why I cannot write entire function like that:

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

The problem is in logic -- executing lambda and goto make 2 expressions now, not one. And I need to make it in one expression -- execute lambda and goto has to be packed in single expression.

I also cannot call recursively the main function because it is whole point of this work, to avoid recursive call :-).

What are the other ways to achieve this?

UPDATE 1 Maybe I rephrase -- what I would like to achieve with goto is continue my_function. Executed from or at the boundary of the inner function (i.e. lambda).

UPDATE 2 The main goal is to loop over the main function, so it is almost equivalent to:

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

"Almost" because of two reasons. I still have the problem with labels exactly as before, and what's more now I have problem where to add breaks to the loop.


Solution

  • Perhaps you are trying to solving your attemted solution rather than your original problem. This question smells XY problem.

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

    Looks for me like do while loop:

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

    Now applying an anonymous function like that is not allowed. In addition closure parameters need to be explicitly declared. Thus my solution needs to be written like this:

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

    If you want to have a "comma operator" you just make a function that takes any numbers of argumens and return the last:

    function begin(){
        return func_get_args()[func_num_args()-1];
    }
    
    begin(expression1, expression2, expression3); // ==> result of expression3
    

    All of a function arguments gets evaluated so it does the same given that the arguments are not dependent on each other.