[Israel.pm] function prototypes

Mikhael Goikhman migo at homemail.com
Wed Jun 11 13:15:12 PDT 2008


On 11 Jun 2008 19:05:18 +0300, Shmuel Fomberg wrote:
> 
> Shmuel Fomberg wrote:
> 
> > I'm trying to write a function:
> > sub MetaField ($&) { ... }
> > 
> > and call it like that:
> > MetaField("data", { $_->ctx->{length} })
> > or:
> > MetaField("data", $_->ctx->{length})
> > 
> > but only this works:
> > MetaField("data", sub { $_->ctx->{length} })
> 
> I want to clarify that the call is suppose to do what the last statment 
> does: when MetaField runs the sub, it will return the value inside 
> $_->ctx->{length}. (and not that $_->ctx->{length} will contain the sub ref)
> 
> The propose of this is to make it niffy. I need to make some info 
> available to the function, so I thought to load it on an object, local 
> $_ to it, and run the function.
> 
> So why map/grep can work without sub{}, and I can't?

It was mentioned already that the magic only occurs on the first CODE
argument (&...) and not on the following ones. The rational for this is
simple, to allow such compact syntax, but make the balance between what
is allowed and being ambiguous.

So, if your function is defined like this:

	sub multiple_eval (&;&&&&&&&&&&) {
		&{shift()} while @_;
	}

Then you may call it like this:

	multiple_eval { warn 42 };
	multiple_eval { warn 42 } sub { warn "Two" };
	multiple_eval { warn 42 } sub { warn "Two" }, sub { warn "Three" };
	multiple_eval(sub { warn 42 }, sub { warn "Two" });

But not like this (all these are ambiguous and will not be interpreted
the way you want them):

	multiple_eval { print 42 }, { warn "Second" };
	multiple_eval { print 42 } { warn "Second" };
	multiple_eval { print 42 } { warn "Second" } { warn "Three" };
	multiple_eval({ warn 42 });

This is because { something } is also the HASH syntax, only the first is
interpretted as the argument of the function with prototype (&...).

This is a limitation of Perl 5; in Perl 6 such conflict between
the function's argument and HASH syntax almost does not matter here, and
you have more ways to do it.

If you want a nifty idiomatic syntax. I may suggest you to either swap
the function arguments, like:

	sub apply (&$) {
		printf "%s: %s\n", $_[1], &{$_[0]};
	}

	apply { 2 * 3 } "half dozen";

Or divide into more functions, like this:

	sub apply (&$) {
		printf "%s: %s\n", &{$_[0]}, $_[1];
	}

	sub on (&) {
		&{$_[0]};
	}

	apply { "meaning of life" } on { 21 * 2 };

Regards,
Mikhael.

-- 
perl -le 'print+chr(64+hex)for+split//,d9b815c07f9b8d1e'



More information about the Perl mailing list