http://www.perlmonks.org?node_id=1002183


in reply to how to make a package variable as c++

"As you see, I didn't know how to create and use what we say member variable in c++. The $XMLfile_name and the @hostList here is using as member variables. @hostList used for holding results parsed from the XML file."

As per $singleton = bless {}, $class, the singleton object is a blessed hash, right? Hmm... now I wonder how you can associate a couple bits of data with the object?

$singleton->{xml_filename} = $_[0]; $singleton->{hostlist} = \@hostlist;

"Another question: In the new method, as I read package method always put the invoker as the first argument. I suppose 'invoker' for new() means the class MyConfig and return an instance after blessed; And the 'invoker' for loadConfig seems change to be an instance, seems the $self by te first default argument is an instance not the class any more. But as I know the 'new' is an ordinary method as others, not a keywords, why they behaves different?"

The invocant is whatever is on the left side of the arrow operator ->. So:

Dancer->new; # invocant is "Dancer" $obj->dance; # invocant is $obj

"The last question:I don't think I made my while condition correct. How can I deal with the while index simply using $_? Thanks a lot in advance!!"

You could use a foreach loop, a la:

my @components = @{ $config->{host}->{component} }; foreach (@components) { push @hostList, $_->{component_name}; }

Though personally I'd just use map; no explicit looping construct necessary:

push @hostList, map { $_->{component_name} } @{ $config->{host}->{component} };

That said, I'd recommend looking at Moose and MooseX::Singleton. Moose takes away a lot of the boilerplate OO "plumbing" necessary in Perl, allowing you to concentrate on the interesting stuff.

{ package MyConfig; use Moose; use MooseX::Singleton; use XML::Simple; has xml_filename => ( is => 'ro', isa => 'Str', required => 1, ); has _config => ( is => 'ro', isa => 'Any', lazy_build => 1, ); has hostlist => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1, ); sub _build__config { my $self = shift; my $xml = XML::Simple->new; $xml->XMLin($self->xml_filename, ForceArray => [ 'host', 'comp +onent' ]) or die $!; } sub _build_hostlist { my $self = shift; my @hostlist = map { $_->{component_name} } @{ $self->_config->{host}[0]{component} }; return \@hostlist; } } my $config = MyConfig->new(xml_filename => "myconfig.xml"); my @hostlist = @{ $config->hostlist }; print "@hostlist";
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Replies are listed 'Best First'.
Re^2: how to make a package variable as c++
by anaconda_wly (Scribe) on Nov 04, 2012 at 11:27 UTC
    OK. Firstly thank you tobyink. I understand you answer to my 2nd question. I asked this because I think $self is something like this pointer in c++. So as you indicate, I see in perl, class itself can be an invoker when as a class method, in the method, sometimes the first input what's commonly named $self is a class, sometimes is an object, no difference when using inside the method.
Re^2: how to make a package variable as c++
by anaconda_wly (Scribe) on Nov 04, 2012 at 11:49 UTC
    I'm studying you code and reading perl docs in the meantime. It may take some time to degest your code. And thanks more.