This fixes the immediate problem and leaves behind, IMHO, a little nightmare for the poor shlub who has to maintain this code six months or a year from now; better make sure he or she does not know your name or where you live – unless the maintainer is you, in which case justice may be said to have been served! Much better, I think, to use an sprintf statement instead.
>perl -wMstrict -le
"my $books = [ qw(a b c) ];
my @body = qw(x y);
my $Author2 = 'defoe';
;;
push @body, qq{<td rowspan=${\scalar @$books}>$Author2</td>};
push @body, sprintf qq{<td rowspan=%d>$Author2</td>}, scalar @$books;
print qq{'$_'} for @body;
"
'x'
'y'
'<td rowspan=3>defoe</td>'
'<td rowspan=3>defoe</td>'
|