Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^3: Adding attributes to values?

by rminner (Chaplain)
on Oct 21, 2007 at 10:26 UTC ( [id://646246]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Adding attributes to values?
in thread Adding attributes to values?

Hi,

you might achieve concurrent use of named and positional args by doing the following:
If a single hash_ref is passed, then treat it as single hash_ref containing named arguments. Otherwise consider them to be positional.

For Example:
sub get_args { if ((scalar(@_) == 1) && ref($_[0]) eq 'HASH') { print "got named args!\n"; } else { print "got positional args\n"; } } sub named_or_positional { get_args(@_); } named_or_positional({foo => 'avalue' , bar => ['a', 'b']}); named_or_positional('whatever' , 'we', 'are', 'passing');

Only Limitation: you won't be able to use a single hash_ref as a positional argument (as it would be treated like an named arg). The Passing of named arguments as a hash ref is also recommended in "Perl Best Practices" by Damian Conway as it catches named arguments where the number of args is odd and not even(usually caused by some typo). This bears the advantage that you catch those typos at compile time and not at runtime.

Replies are listed 'Best First'.
Re^4: Adding attributes to values?
by oyse (Monk) on Oct 21, 2007 at 10:40 UTC

    Yes that is one possible solution to the problem and one that is used by one of the modules that are alread on CPAN. It does however have some problems.

    1. Makes it possible that some hard to find bugs are introduced. For instance a function that takes a list of elements and processes them in someway. If that list contains just one item and that item is a hash ref, the item is interpreted as a named argument which is not what is intended. This can give some strange behaviour and the bug can be hard to track down for the module user.
    2. It creates a special case that can be somewhat un-intuitive for people using the module to create subroutine signatures.
      In that case you might simply pass all named args inside a hash_ref and all positional args inside an array reference. Downside of all this is of course an extreme amount of diffrently shaped brackets getting used ...
      sub get_args { if (scalar(@_) == 1) { if (ref($_[0]) eq 'HASH') { return "got named args!\n"; } elsif (ref($_[0]) eq 'ARRAY') { return "got positional args\n"; } else { die "argument wasn't a hash or array reference!\n"; } } else { die "got more than one arg!\n"; } } sub named_or_positional { print get_args(@_); } named_or_positional({foo => 'avalue' , bar => ['a', 'b']}); named_or_positional(['whatever' , 'we', 'are', 'passing']); named_or_positional('whatever' , 'we', 'are', 'passing');

      Then you would have to check whether there is a single hash_ref or a single array_ref for determining whether it's positional or named. Any other case than a single hash or array ref would have to be considered a error.

      If you don't mind the additional overhead of square/curled brackets, then it would allow you simple differentiation of named an positional args.

        That was a good idea. Thanks!

        I think that the syntactical overhead would be acceptable, I just have to put some more thought into it to see if there is anything I am missing.

        Update: After giving it a bit more thought I think I will try a different approach. The extra square brackets does not conform with how people expect argument passing to be performed in Perl and some might therefore find it confusing. I will instead try an approach where the named arguments has must contain a special key marking it as an named arguments hash. Like this:

        my_func( { key => 'value', ..... $NAMED_ARGS => '' } );

        I think that might be a better solution since people can pass parameters just like they normally would, but get the option of passing them by name if they are inclinded to do so.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://646246]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2024-04-19 06:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found