[comp.lang.perl] subroutine as a parameter

jhh@sprite.Berkeley.EDU (John H. Hartman) (10/30/90)

I'm trying to write my own sort routine that does a stable sort.
I can't figure out how to pass a subroutine as an argument.
Ideally my stable sort routine would take two parameters, the 
comparison subroutine and the array to be sorted.  Thanks.

John

-----------------------------------------------------------------------
John H. Hartman
Graduate Student, UCB Sprite project
jhh@sprite.berkeley.edu

merlyn@iwarp.intel.com (Randal Schwartz) (10/31/90)

In article <29351@pasteur.Berkeley.EDU>, jhh@sprite (John H. Hartman) writes:
| I'm trying to write my own sort routine that does a stable sort.
| I can't figure out how to pass a subroutine as an argument.
| Ideally my stable sort routine would take two parameters, the 
| comparison subroutine and the array to be sorted.  Thanks.

Does this help?

##################################################
sub apply {
	local($function) = shift;
	do $function(@_); # call $function, passing remaining args
}

sub testit {
	print "args are <@_>\n";
}

&apply("testit","arg","argg","arggh");
##################################################

print "Just another applied Perl hacker,"
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Intel put the 'backward' in 'backward compatible'..."=========/

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (10/31/90)

In article <29351@pasteur.Berkeley.EDU> jhh@sprite.Berkeley.EDU (John H. Hartman) writes:
: I'm trying to write my own sort routine that does a stable sort.
: I can't figure out how to pass a subroutine as an argument.
: Ideally my stable sort routine would take two parameters, the 
: comparison subroutine and the array to be sorted.  Thanks.

There's more than one way to skin this carp.  Since you can call a subroutine
indirectly through a scalar variable, you could just pass the subroutine
name in as a string:

	&mysort('bynum', @array);

	sub mysort {
	    local($by) = shift;
	    sort $by @_;
	}

	sub bynum { $a <=> $b; }

The chief difficulty with this is that it might get mixed up about package
names unless you passed in a sort name like "package'bynum", if the sort is
in a different package than the call to &mysort.

One possible way around this is to use the caller function to figure
out what package &mysort was called from, and qualify the subroutine
name if necessary:

	$by = (caller)[0] . "'" . $by  unless $by =~ /'/;

Another way around this is to use the type glob to pass in the symbol table
entry for the sort subroutine.  You can also use it to pass the array
more efficiently:

	&mysort(*bynum, *array);

	sub mysort {
	    local(*by, *ar) = @_;

	    sort by @ar;
	}

	sub bynum { $a <=> $b; }

This doesn't get confused by differing packages (at least it won't after
patch 38) because the symbol table entries you're passing in know which
package they came from.

Larry