Description
I first posted about this in the forums.
The following MWE illustrates a bug. If you enter the correct answer, it is not accepted and there is a perl warning "The evaluated answer is not an answer hash : ||."
This came to my attention from an instructor who previously used certain problems in 2.16, and they worked. But now they do not work on 2.17. And this MWE does not work on 2.18. So it is possibly a bug introduced between 2.16 and 2.17.
Note that if you change $ans to a Real, there is no issue. I also tried making $ans an Interval and there was no issue. It seems to have to do with $ans being a NumberWithUnits. Also there is no issue if I remove the withPostFilter or pass an empty hash to AnswerHints. So it also seems to have to do with AnswerHints.
DOCUMENT();
loadMacros(qw(PGstandard.pl PGML.pl parserNumberWithUnits.pl answerHints.pl));
$ans = NumberWithUnits("1 m");
#$ans = Real("1"); # This works.
$cmp = $ans->cmp()->withPostFilter(AnswerHints(2 => "no"));
BEGIN_PGML
Enter [`[$ans]`].
[_]{$cmp}
END_PGML
ENDDOCUMENT();
I have done some sleuthing. First, it does not help to revert the two macro libraries here to earlier (say 2.16) versions. The change in behavior is something deeper. Things go bad inside lib/AnswerHash.pm
. There is this loop, where I have inserted warn
statements while debugging
foreach my $i (@post_filters) {
last if defined($rh_ans->{done}) and $rh_ans->{done} == 1; # no further action needed
my @array = @$i;
my $filter = shift(@array); # the array now contains the options for the filter
warn('A');
$rh_ans = &$filter($rh_ans, @array);
warn('B');
$self->print_result_if_debug('post_filter', $rh_ans, @array);
}
Running the MWE, I get an "A" without a "B". Something about trying to access &$filter
(in the particular case when it is an AnswerHints filter involving a NumberWithUnits as in the MWE) terminates not only this loop, but also the ambient subroutine. That's what leads to the error message; the ambient subroutine then returns nothing at all, which is "not an answer hash".
I can even change warn('A');
to warn('A' . &$filter);
, and then I don't even get an "A". This suggests it's not so much something about executing that filter code, but just accessing it at all.