A map works by taking one element of its input list at a time, running the code in the block with that element in $_, and returning whatever the last evaluated statement (which returns) does. These returned values, after processing all elements of the input list, comprise its output list.
So the @digits in your block is at every iteration assigned (strings with) the digits of the currently processed element, not all digits of all elements.† They are then either returned in a list, or an empty list is returned which thus "disappears" in the overall return list.‡
Since you return the list with these digits from the block when the last one is 4, then when your map block processes 4 (third element in the array) it returns 4, and when it processes 64 it returns the list with its digits, 6 and 4. Altogether 4 6 4.
† It may also help realizing that the block in the map { ... } LIST syntax stands for a subroutine call with such code executed for every element. This is afforded by use of prototypes. Note that the prototypes are rightly advised against in casual use but here they are needed.
This cannot be fully implemented in pure Perl, but here is a simple example
sub a_bit_like_map :prototype(&$) {
my ($code, @in) = @_;
my @res;
foreach my $el (@in) {
local $_ = $el;
push @res, $code->($el);
}
return @res
}
Now this can be called as either of
my @mapped = a_bit_like_map( sub { ... }, LIST );
my @mapped = a_bit_like_map { ... } LIST;
This :prototype attribute is necessary in newer Perls, and in which signatures are enabled, since without it the syntax would collide with that of signatures.
With older Perls you'll see them used as sub func(&@) { ... }.
‡ A way to use map as a filter, too