

Ask HN: Which programming languages allow pass-by-reference in foreach loops? - pbowyer

I&#x27;ve always wondered why the following isn&#x27;t possible in PHP:<p><pre><code>        &lt;?php
        $start_ids = array(1, 2, 3);
        
        foreach ($start_ids as $id) {
            if ($id &gt; 1000) break;
        
            print &quot;$id\n&quot;;
            $start_ids = array_merge($start_ids, array($id . &#x27;1&#x27;, $id . &#x27;2&#x27;, $id . &#x27;3&#x27;));
        }
</code></pre>
Do any languages allow this? It&#x27;d be nice not to resort to recursion.
======
dozzie
Perl allows this kind of code, similarly to Python and probably Ruby.

    
    
      my @start_ids = (1, 2, 3);
      for my $id (@start_ids) {
        last if $id > 1000;
    
        print $id;
        push @start_ids, map { $id . $_ } 1, 2, 3;
      }
    

But this is bad, really bad idea. This is bad code, it doesn't describe what
you want to achieve, it's difficult to track and analyze, it's hard to tell
when it stops. You really should want recursion here.

And it's not "pass by reference" here. References have nothing to do.

~~~
pbowyer
> But this is bad, really bad idea. This is bad code, it doesn't describe what
> you want to achieve, it's difficult to track and analyze, it's hard to tell
> when it stops. You really should want recursion here.

Thanks for the warning :) It felt much cleaner, my code for the one like
above:

    
    
        $documents = $start_ids;
        foreach ($documents as $id) {
            $sub_ids = getChildren($id, 1);
            // Now filter out any which appear in $stop_ids
            $sub_ids = array_diff($sub_ids, $stop_ids);
            $documents = array_merge($documents, $sub_ids);
        }
        print_r($documents);
    

And the one with recursion:

    
    
        $documents = $start_ids;
        foreach ($start_ids as $id) {
            recurse($id, $documents);
        }
        print_r($documents);
        
        function recurse($id, &$documents)
        {
            global $stop_ids;
    
            $sub_ids = getChildren($id);
            // Now filter out any which appear in $stop_ids
            $sub_ids = array_diff($sub_ids, $stop_ids);
            $documents = array_merge($documents, $sub_ids);
        
            foreach ($sub_ids as $sid) {
                recurse($sid, $documents);
            }
        }
    
    

> And it's not "pass by reference" here. References have nothing to do.

I've seen this terminology used in PHP - describing 'foreach' as "pass by
copy" to make it clear that you can alter the argument and it won't affect the
loop, as a copy was made when foreach was run. How would you describe it
instead?

