* Ofer Nave <[EMAIL PROTECTED]> [2005-03-01 23:45]:
> I realize that since I can tell listrefs apart from strings and
> code refs, I could allow this:
> 
> prun(
>  $coderef1,
>  $coderef2 => [ $arg1, $arg2, $arg3 ],
> );
> 
> Which would run $coderef1 once, but run $coderef2 three times,
> once for each arg.  If you wanted to pass more than one arg at
> a time, you could create sublists:

Leave it out.

It looks like a great idea to you right now with the one or two
examples you developed this on, but you'll get sick of it very
quickly if you start to use it on a larger scale. Don't try to be
too clever, it will bite you once in maintenance mode.

I've done things like that several times in the past and they
always end up obfuscating the code more than they help. This is
really something that must be solved on the language level, à la
currying and compositing operators, not on the level of
individual APIs by overloading the semantics of various data
types.

If you feel it is really important to make this particular use
case easier, use an API like this:

    prun(
        $coderef1,
        [ $coderef2, $arg1 ],
        [ $coderef2, $arg2 ],
        [ $coderef2, $arg3 ],
    );

whose meaning is reasonably easy to guess without having to study
the documentation too closely.

For reducing redundancy, this allows you to fall back on regular
Perl idioms:

    prun(
        $coderef1,
        map( [ $coderef2, $_ ], $arg1, $arg2, $arg3, ),
    );

Now the prun() function has one fewer interface conventions, and
I can understand half of what's going on with my regular Perl
knowledge before I've even read your docs.

There is also precedent in taking an anonymous array with a
coderef in the first slot as a shortcut for "call this code with
these parameters"; offhand I remember that Tk does it this way
but there were other places I saw it. I believe that is because
it is a pretty natural notation.

And your code also has less to guess, because the number of
arguments doesn't change depending on whether I pass arguments to
some coderefs or not.

For similar reasons, I would suggest that you don't allow named
subs as in

    prun(
        foo => $coderef1,
        bar => $coderef2,
    );

but rather require

    prun( {
        foo => $coderef1,
        bar => $coderef2,
    } );

so that you only have to check one easily expressed condition.

Except when they aren't, consistency and simplicity are very
important goals, particularly for your interface.

Regards,
-- 
#Aristotle
*AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(",$\/"," ")[defined wantarray]/e;$1};
&Just->another->Perl->hacker;

Reply via email to