[26193] in Perl-Users-Digest
Perl-Users Digest, Issue: 8382 Volume: 10
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Fri Sep 2 03:06:46 2005
Date: Fri, 2 Sep 2005 00:05:06 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Fri, 2 Sep 2005 Volume: 10 Number: 8382
Today's topics:
Re: Combining multiple hash references into one hash re xhoster@gmail.com
Re: Combining multiple hash references into one hash re <tadmc@augustmail.com>
Disappearing Module <hal@thresholddigital.com>
Re: Disappearing Module <mark.clementsREMOVETHIS@wanadoo.fr>
Re: How to have perl on a CD (windows) <vtatila@mail.student.oulu.fi>
My Net::eBay PERL module now recommended by eBay itself <ignoramus12789@NOSPAM.12789.invalid>
Re: Unexpected array behaviour <tadmc@augustmail.com>
Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: 02 Sep 2005 02:36:56 GMT
From: xhoster@gmail.com
Subject: Re: Combining multiple hash references into one hash reference
Message-Id: <20050901223656.094$zQ@newsreader.com>
Arvin Portlock <nomail@sorry.com> wrote:
> xhoster@gmail.com wrote:
>
> > Arvin Portlock wrote:
> >
> > >my %newhash = (%$hash1, %$hash2);
> > >
> > ># The following do not work:
> > ># my $newhash = { $hash1, $hash2 };
> > ># my $newhash = [ $hash1, $hash2 ];
> > ># my %newhash = ( $hash1, $hash2 );
> >
> > Maybe this is more to your liking:
> > my $newhash = { %$hash1, %$hash2 };
>
> That dereferencing % there makes me nervous. It looks
> to me like a new hash is being created and then a reference
> to it is being assigned to $newhash. So for each of the
> thousands of instances of $newhash, each will have (a ref-
> erence to) its very own copy of %hash1 and %hash2.
Yes, that's right.
> $hash1 and $hash2 do not go out of scope.
Why not? As far as I can tell (and I admit to being a bit lost here, with
all the non-trivial transtions from XML to hashes), once they are put into
$newhash, they are no longer needed.
>
> In my XML document (METS for the curious), There are some
> 30 or forty elements at the top of the document, then further
> down there are some thousands that reference some of those
> elements with attributes of type IDREFS.
>
> <element id="id1"> ... </element>
> <element id="id2"> ... </element>
> ...
> <element id="id30"> ... </element>
>
> <refelement ids="id1 id6 id21"/>
> <refelement ids="id22 id11 id21"/>
> ... etc. for thousands of <refelements>
>
...
>
> BTW, the above was only an attempt to simplify the problem.
> In reality of course I won't be naming my hashes %hash1,
> %hash2, etc.
I'm not sure that is the best choice for simplifying. $hash{1}{foo} and
$hash{2}{foo} are not much more complicated than $hash1{foo} and
$hash2{foo}, and they give valuable clues about the (simplified away)
structure of the program.
> Nor will I name the reference elements
> $newhash12, $newhash643, etc. The <elements> will live
> in a small hash keyed by the id. The <refelement>s will
> live in a large array. And I want to be able to write
> things like this:
>
> foreach my $refelement (@bigarray) {
> print $refelement->{size}, "\n";
> print $refelement->{type}, "\n";
> }
>
> Where "size" and "type" are typical keys from
> among the original 20 or 30 elements (assuming
> <refelement ids="id1 id6 id21"/>, "size" may be
> a key from the element referenced by "id1",
The key *is* what a hash element is referenced by, so the key of
the element referenced by "id1" is "id1"! Do you mean that the literal
string "size" might be the *value* of the element whose key is "id1"? Or
do you mean that the size will be the value of the element referenced by
the first component of the space-separated refelement? (which in this case
happens to be id1, because id1 is the first component of "id1 id6 id21")
>
> I'm trying to simplify the problem without posting the
> entire huge program, but this may be a bit closer to
> what I want (except it doesn't quite work):
>
> my $hashelements = {
> '1' => {
> 'key1' => 'Value 1',
> 'key2' => 'Value 2',
> 'key3' => 'Value 3'
> },
>
> '6' => {
> 'key4' => 'Value 4',
> 'key5' => 'Value 5',
> 'key6' => 'Value 6'
> },
>
> '21' => {
> 'key7' => 'Value 7',
> 'key8' => 'Value 8',
> 'key9' => 'Value 9'
> },
> };
>
> my $newhash = {};
> foreach my $id (1, 6, 21) {
> foreach my $key (keys %{$hashelements->{$id}}) {
> $newhash->{$key} = \{$hashelements->{$id}->{$key}};
You are creating an ref to an anonymous hash (by using curlies) then taking
a reference to that (using backslash). So you get a reference to a scalar
which holds a reference to a one-element hash. Try this:
$newhash->{$key} = \($hashelements->{$id}->{$key});
The parenthesis are not actually necessary, but in this case they make it
easier to read correctly (at least for me).
> }
> }
>
> foreach my $key (keys %$newhash) {
> print "$key: ", $newhash->{$key}, "\n";
You need an extra dereference:
print "$key: ", ${$newhash->{$key}}, "\n";
> }
>
> That $newhash->{$key} = \{$hashelements->{$id}->{$key}} part
> is an attempt to make sure I only create a reference to
> the value rather than make a copy of the value itself.
I'm not sure what you hope to gain by taking the reference. A reference
to the scalar holding the string "Value 9" is not much (if any) smaller
than the thing it is referencing in the first place. You would be better
off just copying it unless either a) You need a change made through
$newhash to be reflected in the original structure, or b) the actual string
is much much bigger than it's example of "Value 9" (which I suspose is not
unlikely)
But I still don't see why you want both $hashelements and $newhash to
exist simultaneously. Unless you are doing something else with
$hashelements which are you aren't showing us or telling us about, there is
no need for it once $newhash is made. Which means you could dispense with
$hashelements altogether, and change whatever is making $hashelements so
that it just makes $newhash directly, instead. If you do, for some reason,
need $hashelements in addition to $newhash, then I think you now know how
to do what you want.
> Perhaps using "each" somehow is the answer. Can't quite get
> that to work either though.
Each doesn't address the root of what you are trying to do, but you could
use it for a slight memory efficiency improvement. For example, replace
foreach my $key (keys %$newhash) {
with
while (defined (my $key = each %$newhash)) {
The first way makes a list which holds a copy of all the keys in
%$newhash right up front. The second one copies the keys one at
a time, as it goes through the hash, so that the memory for each
key can be reused.
Or you could use the list context "each". You have to change the print
statement, too, so it isn't a drop-in replacement, but it does look better
than what it replaces in this case:
while (my ($key,$v) = each %$newhash) {
print "$key: $$v\n";
};
Xho
--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
------------------------------
Date: Thu, 1 Sep 2005 19:35:40 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: Combining multiple hash references into one hash reference
Message-Id: <slrndhf7is.4qf.tadmc@magna.augustmail.com>
[ Please do not top-post.
Please stop top-posting very very soon.
]
Arvin Portlock <nomail@sorry.com> wrote:
> xhoster@gmail.com wrote:
>> Arvin Portlock wrote:
>>
>> >my %newhash = (%$hash1, %$hash2);
>> Maybe this is more to your liking:
>> my $newhash = { %$hash1, %$hash2 };
>
> That dereferencing % there makes me nervous.
Why?
What "danger" do you see that we can help you to avoid?
%newhash and %$newhash should both contain the same keys and values.
> It looks
> to me like a new hash is being created and then a reference
> to it is being assigned to $newhash.
Good, since that _is_ what is happening.
I think maybe your question is more about the contents of this
created hash rather than about the hash itself...
The anon hash contains _copies_ of the keys and values returned
by the dererencing operation. The named hash (%newhash) also
contains copies of the keys and values returned by the dererencing
operation.
> So for each of the
> thousands of instances of $newhash,
There is only _one_ $newhash scalar.
Do you mean that it will take on thousands of _values_ (hashrefs)?
That shouldn't be a problem. Perl's reference counting will free up
the old one when $newhash no longer refers to the old one.
> each will have (a ref-
> erence to) its very own copy of %hash1 and %hash2.
There *are no* such hashes in any of the code above.
It may have been a dual typo on your part, but it pretty much
stops us in our tracks with regard to figuring out what you
are asking...
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
------------------------------
Date: Fri, 02 Sep 2005 00:52:57 -0400
From: Hal Vaughan <hal@thresholddigital.com>
Subject: Disappearing Module
Message-Id: <Hb-dnZ2dnZ1A7nHvnZ2dnTZHit6dnZ2dRVn-z52dnZ0@comcast.com>
I've had a similar problem before and now I realize it was resolved by
removing a level of modules. I don't see how I can include sample code
unless I include entire modules, but basically, when I do a "use Module;",
in some cases the functions in that Module aren't available. Here's an
example that works:
#!/usr/bin/perl
#Program: t-test
use MyMods::Log;
....
initlog($channel); #This initializes the Log functions
Then, in MyMods/Log.pm, I have:
use MyMods::Channel;
sub initlog {
my $channel = shift(@_);
setchannelprogram($channel); #Routine in MyMods::Channel --
# used w/out problem
return;
}
When I do this, it works just fine. However, when I add another level, by
having a program use a module that uses MyMods::Log, then MyMod::Log cannot
access routines in MyMods::Channel. Here's an example of what does not
work:
#!/usr/bin/perl
#Program: t-fetch
use MyMods::Search;
.....
initsearch($channel); #This initializes Search
Then, in MyMods/Search.pm, I have:
use MyMods::Log;
...
sub initsearch {
my $channel = shift(@_);
initlog($channel); #Same initchannel as before, but now
#called by a function in a module, not
#directly from the main program
return;
}
Then, in MyMods/Log.pm, again, I have the same as before:
use MyMods::Channel;
sub initlog {
my $channel = shift(@_);
setchannelprogram($channel); #Routine in MyMods::Channel --
# Now won't work when called from a mod
# that is, in turn, called from a mod
return;
}
This time I'm using the same module MyMods::Log, and that module is using
the same module, MyMods::Channel, but this time, it is NOT able to use the
functions in MyMods::Channel. All other routines in other mods are
accessible, it's just the Channel.pm file I'm having trouble with.
So what am I doing wrong? Why can MyMods::Log access MyMods::Channel when
called from a module used by program, but NOT when called from a module
that is used by a module that is used by a program?
Thanks!
Hal
------------------------------
Date: Fri, 02 Sep 2005 07:06:54 +0200
From: Mark Clements <mark.clementsREMOVETHIS@wanadoo.fr>
Subject: Re: Disappearing Module
Message-Id: <4317ddf2$0$17228$8fcfb975@news.wanadoo.fr>
Hal Vaughan wrote:
> I've had a similar problem before and now I realize it was resolved by
> removing a level of modules. I don't see how I can include sample code
> unless I include entire modules, but basically, when I do a "use Module;",
> in some cases the functions in that Module aren't available. Here's an
> example that works:
>
> #!/usr/bin/perl
> #Program: t-test
>
> use MyMods::Log;
>
> ....
>
> initlog($channel); #This initializes the Log functions
>
> Then, in MyMods/Log.pm, I have:
>
> use MyMods::Channel;
>
> sub initlog {
> my $channel = shift(@_);
> setchannelprogram($channel); #Routine in MyMods::Channel --
> # used w/out problem
> return;
> }
>
> When I do this, it works just fine. However, when I add another level, by
> having a program use a module that uses MyMods::Log, then MyMod::Log cannot
> access routines in MyMods::Channel. Here's an example of what does not
> work:
>
> #!/usr/bin/perl
> #Program: t-fetch
>
> use MyMods::Search;
>
> .....
> initsearch($channel); #This initializes Search
>
> Then, in MyMods/Search.pm, I have:
>
> use MyMods::Log;
>
> ...
>
> sub initsearch {
> my $channel = shift(@_);
> initlog($channel); #Same initchannel as before, but now
> #called by a function in a module, not
> #directly from the main program
> return;
> }
>
> Then, in MyMods/Log.pm, again, I have the same as before:
>
> use MyMods::Channel;
>
> sub initlog {
> my $channel = shift(@_);
> setchannelprogram($channel); #Routine in MyMods::Channel --
> # Now won't work when called from a mod
> # that is, in turn, called from a mod
> return;
> }
>
> This time I'm using the same module MyMods::Log, and that module is using
> the same module, MyMods::Channel, but this time, it is NOT able to use the
> functions in MyMods::Channel. All other routines in other mods are
> accessible, it's just the Channel.pm file I'm having trouble with.
>
> So what am I doing wrong? Why can MyMods::Log access MyMods::Channel when
> called from a module used by program, but NOT when called from a module
> that is used by a module that is used by a program?
>
A few thoughts:
make sure the package declarations match up with the filenames
ie
package MyMods::Channel;
is at the start of MyMods/Channel.pm
Check out the Exporter
perldoc Exporter
Mark
------------------------------
Date: Fri, 2 Sep 2005 08:33:59 +0300
From: "Veli-Pekka Tätilä" <vtatila@mail.student.oulu.fi>
Subject: Re: How to have perl on a CD (windows)
Message-Id: <df8o8m$ov5$1@news.oulu.fi>
News KF wrote:
> I want to have a perl-application, that could reside on a CD or USB
> memory stick and could run on any windows computer.
Hi,
I think the only difference between the two is that CD's are read-only
usually, so you'd need to have the program write its files and extract any
temporary modules to some writable location. I've been succesfully using two
solutions.
Firstly, Tiny Perl is able to run Perl programs, say from a floppy, with
know needd to run a Windows installer first:
http://tinyperl.sourceforge.net/
There are not too many libraries but you can usually copy any of the more
special one's from an active state distro. The procedure is finding the lib
pm files either under site/lib or lib. You should also copy any related DLLs
under the .\auto directory. As moduiles may require each other, you can
either try running the module manually adding stuff until it works or find
out the dependencies with a CPAN util called scandeps..
Example hash::Util
Checking the lib.zip file under Tiny Perl reveals that no hash modules have
been installed. But Active State has got the files. Most of the stuff you
add with ppm goes under site\lib but Hash is core enough to be in the lib
directory directly, that is:
C:\Perl\lib\Hash
It only contains the file Util.pm that you'll need but you need to maintain
the directory hierarchy so grab the whole hash directory. As to where it
should be copied, regardless of whether the file came from site\lib or lib,
it goes in a directory called lib under Tiny Perl.
Looking for DLLs in the auto directory at:
C:\Perl\lib\auto
There's no sub-dir called hash so you should be done now provided that
Hash::Util doesn't depend on anything that Tiny perl doesn't already have.
The other app I've been using is called perl2exe and has a 30-day trial
version:
http://www.indigostar.com/perl2exe.htm
It is able to resolve all dependencies and link in all ordinarily named pm
and dll files for you based on the source code. It will create one, big,
nice self-contained exe file which extracts the libraries in some readable
temporary directory when you run it. It seems to be one of the Windows temp
directories by default.
Hope this can be of help,
--
With kind regards Veli-Pekka Tätilä (vtatila@mail.student.oulu.fi)
Accessibility, game music, synthesizers and programming:
http://www.student.oulu.fi/~vtatila/
------------------------------
Date: Fri, 02 Sep 2005 03:24:28 GMT
From: Ignoramus12789 <ignoramus12789@NOSPAM.12789.invalid>
Subject: My Net::eBay PERL module now recommended by eBay itself
Message-Id: <MBPRe.60261$Jz4.50444@fe50.usenetserver.com>
The Perl::eBay module that I wrote a few days ago, is now recommended
by ebay:
http://developer.ebay.com/php/
I want to say a big THANK you to all people who actually made helpful
suggestions, looked at what I did in depth and corrected my mistakes.
i
------------------------------
Date: Thu, 1 Sep 2005 22:11:18 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: Unexpected array behaviour
Message-Id: <slrndhfgmm.5fd.tadmc@magna.augustmail.com>
Spin <cNaOlSePbA@MvPeLtEsAtSaEr.com> wrote:
> Could I have some pointers on how to handle this data better
You could if we weren't so sarcastic and unhelpful.
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
------------------------------
Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>
Administrivia:
#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc. For subscription or unsubscription requests, send
#the single line:
#
# subscribe perl-users
#or:
# unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.
NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.
#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V10 Issue 8382
***************************************