in reply to coderefs and (&) prototypes

Why does a (&) prototype only accept blocks or sub{} but not scalar coderefs?

It does. In fact, that's the only thing it accepts. The real question is why doesn't it accept arbitrary expressions that return a code ref. And the answer is that there's no way to guarantee that the expression will return a code ref. Rather than adding code to the optree to do run-time type checking, prototypes only allow operators that are guaranteed to return a value of the appropriate type.

For example,
The arg for (\@) must start with a @.
The arg for (\%) must start with a %.

sub {} is guaranteed to return a code ref, so it's allowed for (&).
\&cb is guaranteed to return a code ref, so it's allowed for (&). By extension, this includes \&{ EXPR }.

&foo, on the other hand, is a sub call. It can return anything. It's not allowed for (&) (or (\@) or (\%)).

Replies are listed 'Best First'.
Re^2: coderefs and (&) prototypes
by JadeNB (Chaplain) on Jul 28, 2009 at 21:20 UTC
    The real question is why doesn't it accept arbitrary expressions that return a code ref. And the answer is that there's no way to guarantee that the expression will return a code ref.
    and then
    \&cb is guaranteed to return a code ref, so it's allowed for (&). By extension, this includes \&{ EXPR }.

    I don't understand these two together. There's no way to guarantee that EXPR in \&{ EXPR } will evaluate to a code-ref either, and, if it doesn't, the extra \& noise isn't going to prevent it from blowing up at run-time—so why put the programmer through that extra syntactic hassle, if it doesn't buy him or her any extra safety?

      the extra \& noise isn't going to prevent it from blowing up at run-time

      The whole point of parameter validation is to blow up. Why would you want to prevent it?

      Without the "extra noise", it wouldn't blow up. That's the problem.

      sub f0 { my ($cb) = @_; '...' } sub f1(&) { my ($cb) = @_; '...' } f0(\&abc); # OK No error f0(\&{ maybe_coderef() }); # OK Error caught at run-time (if any) f0("abc"); # XX Error uncaught f0(maybe_coderef()); # XX Error uncaught (if any) f1(\&abc); # OK No error f1(\&{ maybe_coderef() }); # OK Error caught at run-time (if any) f1("abc"); # OK Error caught at compile-time f1(maybe_coderef()); # OK Error caught at compile-time (if any)

      Update: Added example