Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

More elegant way of doing "ordered hash"?

by PopeFelix (Sexton)
on Oct 09, 2013 at 22:01 UTC ( #1057626=perlquestion: print w/ replies, xml ) Need Help??
PopeFelix has asked for the wisdom of the Perl Monks concerning the following question:

I have the following data structure that I'm effectively treating as an ordered hash. I realize that I could use Tie::IxHash, but for various reasons (see below) I don't want to do that.

my $spec = { 'Parameters' => [ 'shipmentIncrementId' => { 'required' => 1, 'type' => 'string', }, 'carrier' => { 'required' => 1, 'type' => 'ups|usps|dhl|fedex|dhlint|custom', }, 'title' => { 'required' => 1, 'type' => 'string', }, 'trackNumber' => { 'required' => 1, 'type' => 'string', }, ], 'Response' => 'scalar', };

I'm iterating over the keys like so:

my @params = $thing->{'Parameters'}; for my $index (0..$#params) { next if $index % 2 != 0; my $parameter = $params[$index]; my $spec = $params[$index + 1]; # do something from here... }

Is there a more elegant way of doing that?

As to why I'm not doing Tie::IxHash: I'm using this to specify dynamic methods like so:

define_method 'foo' => { 'Parameters' => [ 'bar' => { 'required => 1, 'type' => 'string', }, 'baz' => { 'required => 1, 'type' => 'string', }, ] };

Note that the application requires the arguments to be in order. I'm not sure how I'd use Tie::IxHash in that situation.

Comment on More elegant way of doing "ordered hash"?
Select or Download Code
Re: More elegant way of doing "ordered hash"?
by boftx (Chaplain) on Oct 09, 2013 at 22:19 UTC

    Right off the top it looks like the 'define_method' code is accepting the value for 'Parameters' as a hash ref instead of an array ref so I'm not sure you are going to be keeping the order of the keys to begin with, especially with the latest version of Perl.

    That aside, unless you are in a position to rewrite the app (which I would guess is significant in size) to use named parameters instead of positional you have probably come up with the best way to do what you want. The entire problem disappears if you can switch to named params. Plus, you can take advantage of CPAN modules to enforce type checking, etc, like you are currently doing.

    Of course, if you can make the change, then go whole-hog and covert to Moose since what you have here looks a lot like someone tried to invent Moose with positional params.

    On time, cheap, compliant with final specs. Pick two.

      Value for Parameters is an arrayref.

      As for sending named parameters, I can't do that because what I'm doing is wrapping XML-RPC calls to Magento, and I haven't found a way to get XML::RPC to send named params.

      And yes, this was partially inspired by Moose. :)

        whoops! There was a typo there. Parameters should definitely be an arrayref in define_api_method
Re: More elegant way of doing "ordered hash"?
by kcott (Abbot) on Oct 10, 2013 at 08:00 UTC

    G'day PopeFelix,

    for my $index (0..$#params) { next if $index % 2 == 0; my $parameter = $params[$index]; my $spec = $params[$index + 1]; # do something from here... }

    Is there a more elegant way of doing that?

    How about:

    for (grep { not $_ % 2 } 0 .. $#params) { my ($parameter, $spec) = @params[$_, $_+1]; ... }

    [ You've got a couple of typos: the 1st $spec becomes $thing; you assign an arrayref to @params ]

    -- Ken

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1057626]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (7)
As of 2014-08-23 00:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (168 votes), past polls