Skip to content

Commit

Permalink
Merge pull request #757 from pstaabp/move-PGsort
Browse files Browse the repository at this point in the history
move PGsort from Translator.pm to PGbasicmacros.pl
  • Loading branch information
pstaabp authored Jan 19, 2023
2 parents af5f4d5 + ddd8999 commit 27d226f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 40 deletions.
40 changes: 0 additions & 40 deletions lib/WeBWorK/PG/Translator.pm
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ sub new {
&PG_answer_eval
&PG_restricted_eval
&send_mail_to
&PGsort
In addition the environment hash C<%envir> is shared. This variable is unpacked
when PG.pl is run and provides most of the environment variables for each problem
Expand All @@ -285,7 +284,6 @@ The macros shared with the safe compartment are
'&PG_restricted_eval'
'&be_strict'
'&send_mail_to'
'&PGsort'
=cut

Expand All @@ -298,7 +296,6 @@ my @Translator_shared_subroutine_array = qw(
&PG_restricted_eval
&PG_macro_file_eval
&be_strict
&PGsort
);

sub initialize {
Expand Down Expand Up @@ -1270,43 +1267,6 @@ sub safetyFilter {
return ($answer, $errorno);
}

=head2 PGsort
Because of the way sort is optimized in Perl, the symbols $a and $b
have special significance.
C<sort {$a<=>$b} @list>
C<sort {$a cmp $b} @list>
sorts the list numerically and lexically respectively.
If C<my $a;> is used in a problem, before the sort routine is defined in a macro, then
things get badly confused. To correct this the macro PGsort is defined below. It is
evaluated before the problem template is read. In PGbasicmacros.pl, the two subroutines
PGsort sub { $_[0] < $_[1] }, @list;
PGsort sub { $_[0] lt $_[1] }, @list;
(called num_sort and lex_sort) provide slightly slower, but safer, routines for the PG language.
(The subroutines for ordering are B<required>. Note the commas!)
=cut

sub PGsort {
my ($cmp, @list) = @_;
die "Must supply an ordering function with PGsort: PGsort sub {\$_[0] < \$_[1] }, \@list\n"
unless ref $cmp eq 'CODE';

return if @list == 0;

my $b_item = shift @list;
my ($small, $large);
for my $a_item (@list) {
push @{ &$cmp($a_item, $b_item) ? $small : $large }, $a_item;
}
return PGsort($cmp, @$small), $b_item, PGsort($cmp, @$large);
}

=head2 PG_restricted_eval
PG_restricted_eval($string)
Expand Down
37 changes: 37 additions & 0 deletions macros/core/PGbasicmacros.pl
Original file line number Diff line number Diff line change
Expand Up @@ -2724,6 +2724,43 @@ sub sspf {
$sign . sprintf($format, $number);
}

=head2 PGsort

Because of the way sort is optimized in Perl, the symbols $a and $b
have special significance.

C<sort {$a<=>$b} @list>
C<sort {$a cmp $b} @list>

sorts the list numerically and lexically respectively.

If C<my $a;> is used in a problem, before the sort routine is defined in a macro, then
things get badly confused. To correct this the macro PGsort is defined below. It is
evaluated before the problem template is read. In PGbasicmacros.pl, the two subroutines

PGsort sub { $_[0] < $_[1] }, @list;
PGsort sub { $_[0] lt $_[1] }, @list;

(called num_sort and lex_sort) provide slightly slower, but safer, routines for the PG language.
(The subroutines for ordering are B<required>. Note the commas!)

=cut

sub PGsort {
my ($cmp, @list) = @_;
die "Must supply an ordering function with PGsort: PGsort sub {\$_[0] < \$_[1] }, \@list\n"
unless ref $cmp eq 'CODE';

return if @list == 0;

my $b_item = shift @list;
my ($small, $large);
for my $a_item (@list) {
push @{ &$cmp($a_item, $b_item) ? $small : $large }, $a_item;
}
return PGsort($cmp, @$small), $b_item, PGsort($cmp, @$large);
}

=head2 Sorting and other list macros

Usage:
Expand Down

0 comments on commit 27d226f

Please sign in to comment.