Extract strings from nested array in Perl Extract the strings from nested arrays in Perl.

It prints: a, b, c, d, E

use strict;
use warnings;
use feature qw(say signatures current_sub); 
no warnings qw(experimental::signatures);

my $nested = [1, 'a', [2, 3, 'b'], [4, [5, 6, 7, ['c']], [7, [8, 9, [10, 'd']]], 11, 'E']];

print join ', ', @{ extract_strings($nested) };

sub extract_strings($input) {
    my @output = ();

    my $loop = sub ($val) {
        if (ref $val eq 'ARRAY') {
            __SUB__-&gt;($_) for @{ $val };
        } else {
            push(@output, $val) if $val =~ /^[a-zA-Z]/;
        }
    };

    $loop-&gt;($input);

    return \@output;
}


Any idea for improvement without not core dependencies?
Your concept of "string" seems incomplete.  I would look to firm up that definition and precisely match the need.  Is "" a string?  Do you want "valid identifiers" (/^[^\d\W]\w+$/) or "plausible ASCII words"  (/^[A-Za-z]+$/) or just "not numbers"  (!/ ^ ( [+-]? \d* \.? \d+ (?:[Ee][+-]?\d+)? ) $/x)?  

I like use warnings FATAL =&gt; 'all'; so that I don't miss a warning in the midst of other output.  

A fat arrow between arguments of different purpose can enhance readability.

Coding in functional style (with grep and map instead of @output) is a natural fit to this kind of problem.  

Plain old recursion is suited to the task and would obviate the need for experimental features.  

Having extract_strings take a ref (as it does now) and return a list simplifies the logic even further.

print join ', ' =&gt; extract_strings($nested);

sub extract_strings {
    grep /^[a-zA-Z]/ =&gt; map { ref eq 'ARRAY' ? extract_strings($_) : $_ } @{ $_[0] } 
}


If returning a ref is necessary, wrap and unwrap accordingly:

sub extract_strings {
    [ grep /^[a-zA-Z]/ =&gt; map { ref eq 'ARRAY' ? @{ extract_strings($_) } : $_ } @{ $_[0] } ]
}