Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using my() changes XML::Bare behavior drastically

Tags:

xml

perl

When I run this Perl script:

#!/bin/perl 
use XML::Bare; 
$ob = new XML::Bare(text=>'<xml><name>Bob</name></xml>'); 
for $i (keys %{$ob->{xml}}) {print "KEY: $i\n";} 

I get no output. However, if I put $ob inside a my():

#!/bin/perl 
use XML::Bare; 
my($ob) = new XML::Bare(text=>'<xml><name>Bob</name></xml>'); 
for $i (keys %{$ob->{xml}}) {print "KEY: $i\n";} 

I get this output:

KEY: _z 
KEY: _i 
KEY: xml 
KEY: _pos 

Why does my() change this behavior so drastically, especially given that I'm at the top level where my() should have no effect at all?


2 Answers

First of all, you should always begin your Perl scripts with

use strict;
use warnings;

This will force you to declare all your variables with my which catches many typos and simple mistakes.

In your case, it's not actually the my that causes the changed behavior, but the parentheses, which put $ob in list context.

Looking at the source of XML::Bare, we find this in the constructor:

sub new { 
    ...
    bless $self, $class;
    return $self if ( !wantarray );
    return ( $self, $self->parse() );
}

Notice that the second return line calls ->parse on the new object for you, which you forgot to do in your first example, which is why that one didn't have any data in it.

So you can say

my $obj = XML::Bare->new(text=>'<xml><name>Bob</name></xml>'); # in scalar context
$obj->parse;

Or

my ( $obj ) = XML::Bare->new(text=>'<xml><name>Bob</name></xml>'); # in list context

and they should be equivalent.

This is a pretty strange interface choice, but I'm not familiar with XML::Bare.

Notice also that I've avoided indirect method syntax (XML::Bare->new instead of new XML::Bare). This helps to avoid some nasty problems.

like image 96
friedo Avatar answered Mar 07 '26 07:03

friedo


The XML::Bare module is intentionally designed to work in 2 different ways.

Way #1:

my $ob = XML::Bare->new( text => "<xml/>" );
my $tree = $ob->parse();

Way #2:

my ( $ob, $tree ) = XML::Bare->new( text => "<xml/>" );

You are using the module in an undocumented way #3:

my ( $ob ) = XML::Bare->new( text => "<xml/>" );
my $tree = $ob->{'xml'};

This third way happens to work, because the module stores the tree within it's own object. I would recommend avoiding using it in this way, because it is confusing, and may change in future versions of the module.

like image 35
nanoscopic Avatar answered Mar 07 '26 06:03

nanoscopic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!