in reply to unless versus if ( ! ) inside a subroutine

I think what is being overlooked is the effect of evaluating the empty statement block {}, which appears in all of the examples of the OP.

In the statement if ('') {}, the last expression evaluated is the conditional, which is false (the empty string); this is the value returned.

In the statement if ('true') {}, the last expression evaluated is the true clause, which is the empty statement block, which evaluates to the empty string; this is the value returned.

In the statement if (! 'true') {}, the last expression evaluated is the conditional, which evaluates to false (the empty string), etc.

This can be confirmed by re-writing the if statement to the 'statement modifier' form and using do {} for the empty statement (because {} on its own will be interpreted as an anonymous hash constructor).

E.g.:

C:\@Work\Perl>perl -wMstrict -e "sub S { if (! $_[0]) {} } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <> C:\@Work\Perl>perl -wMstrict -e "sub S { if ( $_[0]) {} } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <> C:\@Work\Perl>perl -wMstrict -e "sub S { unless (! $_[0]) {} } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <1> <> C:\@Work\Perl>perl -wMstrict -e "sub S { unless ( $_[0]) {} } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <hiya> C:\@Work\Perl>perl -wMstrict -e "sub S { do {} if ! $_[0] } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <> C:\@Work\Perl>perl -wMstrict -e "sub S { do {} if $_[0] } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <> C:\@Work\Perl>perl -wMstrict -e "sub S { do {} unless ! $_[0] } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <1> <> C:\@Work\Perl>perl -wMstrict -e "sub S { do {} unless $_[0] } print qq(<@{[ S($_) ]}> \n) for @ARGV" "" "hiya" <> <hiya>