This question comes in an attempt to understand one of the answer in : How to check that a string is a palindrome using regular expressions?
Answer
It might be easier to understand with this analogous function, that does the same thing for arrays:
sub palindrome {
if (scalar(@_) >= 2) {
my $first_dot = shift;
my $slash_two = pop;
return $first_dot eq $slash_two && palindrome(@_);
} else {
# zero or one items
return 1;
}
}
print "yes!\n" if palindrome(qw(one two three two one));
print "really?\n" if palindrome(qw(one two three two two one));
The (?1)
notation is a recursive reference to the start of the first parenthesis in the regex, the \2
is a backreference in the current recursion to the (.)
. Those two are anchored at the start and end of 'whatever is matching at the current recursion depth', so everything else is matched at the next depth down.
ikegami suspects this is faster:
sub palindrome {
my $next = 0;
my %symbols;
my $s = join '', map chr( $symbols{$_} ||= $next++ ), @_;
return $s =~ /^((.)(?1)\2|.?)\z/s;
}