Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

passing a hash to a sub by reference.. AARRRGGGHHH! 2

Status
Not open for further replies.

MikeLacey

MIS
Nov 9, 1998
13,212
0
0
GB
This code works ok but I don't like it much, inelegant.

use strict;
my %cfg = (
[tab]'oracle_sid' => ''
)

print "oracle_sid=$cfg{'oracle_sid'}\n";
init(\%cfg);
print "oracle_sid=$cfg{'oracle_sid'}\n";

sub init{
[tab]$_[0]{'oracle_sid'} = 'Mike';
}
[/code]
The value of $cfg{'oracle_sid'} is left at 'Mike' after the subroutine call.

But it's not pretty is it... (and, more to the point, not very readable if I have a whole list of parameters)

I'd like to be able to refer to the hash by name, something like this (this doesn't work btw)
Code:
sub init{
my $href = \$_[0];
[tab]$href{'oracle_sid'} = 'Mike';
}
Perldoc perlref sort of implies that you can do this, but stops short of explaining to a mere mortal like myself just how I should do it.

I'd be grateful if someone would point out my glaring misunderstanding B-( (I *hate* not knowing stuff....)
 
Mike:-

I didn't work much in the oracle connectivity.
I think if u need a better code .I can give a try .

give in much simpler way like(please bear with me)

$x= "djhfjhf";
&int($x);
$x="fjgkdg":

sub int()
{
fgdfgdfgdf
}

I hope u undrstand what iam expecting



[sig][/sig]
 
Thanks for responding thendal

it's nothing to do with oracle to be honest....

I want to be able to pass a hash to subroutine by reference, so that the hash can be modified within the subroutine.

In the example above, the code: (re-written to avoid oracle distractions)

sub init{
$_[0]{'first_name'} = 'Mike';
}

this code works fine, you call it like this:

my %cfg;
init(\%cfg);

My problem with it is that I don't want to refer to variables inside a subroutine using the $_[0] method... It's ok if you just have the one parameter -- but any more than that and it will become unreadable.

So -- I'd like a way to pass a hash to a subroutine by reference - and then to refer to that hash, within the subroutine, using a readable name rather than by an index into the @_ array. [sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br> [/sig]
 
I sometimes just pass the hash name. Like this....

Code:
use strict;
$hName = 'cfg';
my %$hName = ( 'oracle_sid' => '' );

print &quot;oracle_sid=$$hName{'oracle_sid'}\n&quot;;
init($hName);
print &quot;oracle_sid=$$hName{'oracle_sid'}\n&quot;;

sub init{
my $hName = $_[0];
$$hName{'oracle_sid'} = 'Mike';
}

I have used this when I needed to handle some unknown number of hashes. I would keep a list of newly created hash names and then retrieve them as was needed for what ever chore I was working on. You can just pass the hash name around and dereference the name. Sorry about using a little different syntax.....' just the way I'm used to playing with references.

hope this helps. [sig]<p> <br><a href=mailto: > </a><br><a href= > </a><br> keep the rudder amid ship and beware the odd typo[/sig]
 
Mike:-

I am new bee.I tried like this.I don't know this is what ur exactly expecting.

%cfg=('firstname' => 'thendal0','firstname2' => 'thendal1');
@array=keys(%cfg);
print &quot;First=$cfg{$array[0]}\n&quot;;
$len=scalar @array;
&init($len);
print &quot;First=$cfg{$array[0]}\n&quot;;
sub init{
$len=$_[0];
for($i=0;$i<$len;$i++)
{
$cfg{$i} =&quot;Mike$i&quot;;
}
}

my whole point is instead of refering each hash values with
$_[0].passing one value(ie,whole length of the array)

I hope this will help u.

Thendal


[sig][/sig]
 
Ok -- thx both [sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br> [/sig]
 
I've done it like this:

my %cfg = ('oracle_sid' => '');

print &quot;oracle_sid=$cfg{'oracle_sid'}\n&quot;;
%cfg = init(%cfg);
print &quot;oracle_sid=$cfg{'oracle_sid'}\n&quot;;

sub init
{
my %cfg = @_;
$cfg{'oracle_sid'} = 'Mike';
return %cfg;
}

Only problem is that I've only gotten this to work when the hash is the last parameter in a list and there is only one hash. I can't pass two hashes this way (which has been a pain in the butt because I had to turn strict off and make a global hash for one of them).

I hope this helps you... and maybe you can solve my problem.
[sig]<p> Sincerely,<br><a href=mailto: > </a><br><a href= Anderson</a><br>CEO, Order amid Chaos, Inc.<br>
[/sig]
 
I've found some stuff -- will post it tomorrow.... thx all [sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br> [/sig]
 
heck -- sorry, I forgot, will post it tomorrow AM (UK time) [sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br>Making mistakes, so you don't have to. &lt;grin&gt;[/sig]
 
Does anyone remember Turbo Pascal? (stop retching!) You could pass whatever into a sub and it would arive intact. Arrays and all.

Ahhh, those were the days :) Maybe in a future version...? [sig]<p>fortytwo<br><a href=mailto:will@hellacool.co.uk>will@hellacool.co.uk</a><br><a href= test site</a><br> [/sig]
 
I remember Turbo Pascal just fine <grin>
anyway..... as promised, if a little late, sorry about the delay Tom et al..

Initially I wanted to be able to pass a hash to a sub and have a modified version of that hash returned to me by the sub. After some thought (not like me I know) I decided I wanted som checking for programmers who managed to mistype parameter names - so here's what I ended up doing:

config file like this
[tt]
oracle_sid = pil3
oracle_logon = mlacey/mrbigboy
[/tt]

which is read, in the main program, like this:
[tt]
use strict;
use Utils;
Utils::init_cfg('bpackar.cfg');
my $orasid=cfg_val('oracle_sid');
my ($orauser, $orapass) = split(/\//,Utils::cfg_val('oracle_logon'),3);
[/tt]

The relevant bit of Utils.pm is this... (You're welcome to all of it, but it's a bit long)
[tt]
package Utils;
use strict;
my %cfg;
my $cfg_inited = 0;

sub init_cfg($){my ($file)=@_;
my ($config_param, $value);
[tab]die &quot;$0: Utils::init_cfg: no cfg file specified\n&quot; unless $file;
[tab]open(CFGFILE,$file) || die &quot;$0: Utils::init_cfg: cannot open cfg file ile)\n$!\n&quot;;
[tab]while(<CFGFILE>){
[tab][tab]chomp;
[tab][tab]s/#.*|^\s+|\s+$//; # remove blank lines, spaces and comments
[tab][tab]next unless length;
[tab][tab]($config_param, $value) = split(/\s*=\s*/,$_,2);
[tab][tab]Utils::cfg{$config_param}=$value;
[tab]}
[tab]$Utils::cfg_inited = 1;
} # sub init_cfg

sub cfg_val($){my ($key)=@_;

[tab]die &quot;$0: Utils::cfg_val: cfg file not yet read\n&quot; unless $Utils::cfg_inited;
[tab]if(defined($Utils::cfg{$key})){
[tab][tab]return($Utils::cfg{$key});
[tab]} else {
[tab][tab]die &quot;$0: Utils::cfg_val: value ($key) not defined in cfg file\n&quot;;
[tab]}
} # sub cfg_val
[/tt]

[sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br>Making mistakes, so you don't have to. &lt;grin&gt;[/sig]
 
Hi Mike, thanks for posting. Yeah, Pascal was OK, but not very useful practically. Mike, I don't see where you are passing a hash to a sub... it looks like your hash is global. What am I missing?

BTW, I had a new idea for this... make the hash into an object and pass that.
[sig]<p> Sincerely,<br><a href=mailto: > </a><br><a href= Anderson</a><br>CEO, Order amid Chaos, Inc.<br>
[/sig]
 
Hi Tom,

Trick is that the hash is defined in the Utils package and only read or written by routines defined within it.

You only get values in the hash by putting them in the cfg file and callng Utils::init_cfg

You only get values out of the hash by calling Utils::cfg_val and if you try and read a value that is not defined in the cfg file it gives you an error message and dies.

Obviously there's nothing to stop a programmer saying something like:

%Utils::cfg{'my_undocumented_param'} = 'yuk';

and then using it, like all Perl stuff really. The idea was to catch errors rather than to enforce a standard.

Perl Objects -- yeah.... I've heard of them :-( but my understanding of them, despite reading the Camel book from cover to cover more than once, is somewhat limited (zero that is). All that blessing gives me a nasty rash... I'm pinning my &quot;Understandable and Readble Perl OO&quot; hopes on Perl6.
[sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br>Making mistakes, so you don't have to. &lt;grin&gt;[/sig]
 
From what I have heard/read about Perl 6, it seems that it will have a lot of OOP that you can utilize. I read an article by one of the creaters.

I can't wait for 6 to come out too.

-Vic [sig]<p>vic cherubini<br><a href=mailto:malice365@hotmail.com>malice365@hotmail.com</a><br><a href= software</a><br>====<br>
Knows: Perl, HTML, JavScript, C/C++, PHP, Flash, Director<br>
Wants to Know: Java, Cold Fusion, Tcl/TK<br>
====[/sig]
 
well -- we shall see I guess <smile> [sig]<p>Mike<br><a href=mailto:michael.j.lacey@ntlworld.com>michael.j.lacey@ntlworld.com</a><br><a href= Cargill's Corporate Web Site</a><br>Making mistakes, so you don't have to. &lt;grin&gt;[/sig]
 
I don't know how this thread got so complicated, but it seems to me the original question was a less ugly method for using a hash reference in a subroutine. Here's how:
Code:
init(\%myhash);

sub init {

my($hashref) = @_;

${$hashref}{'first_name'} = 'Mike';

}

The ${$hashref} part is the trick. It &quot;dereference&quot; $hashref to be a hash, just as if it actually said &quot;myhash&quot;, and then the code is interpreted as if it said $myhash{'first_name'}.

Yes, I've read all the perldocs multiple times. Sometimes I STILL have to go back and look up how to use references.

 
Thanks for posting tsdragon, much appreciated.

What does &amp;#64;_; do?
Mike
michael.j.lacey@ntlworld.com
 
Hi Mike,
I've been passing hashes and arrays back and forth into and out of subs. Looks like tsdragon is doing it similar to what I'd suggest below.. I don't know what the &amp;_64;_; is though...

sub dosomething {
#$getvar1 and $getvar2 are just examples of regular
#variables being passed; $reftoarray will hold the
#reference to any array you're passing and same for
#$reftohash

my ($getvar1, $getvar2, $reftoarray, $reftohash) = @_;
my (@array) = @{$reftoarray};
my (%hash) = %{$reftohash};

#do whatever here with your hash or array (called %hash
#and @array, respectively)...

#pass back out the array and hash references...
return (\@array, \%hash);
}

#main program

my (@somearray, %somehash);
my ($reftothearray, $reftothehash) = dosomething(&quot;A&quot;, &quot;B&quot;, \@somearray, \%somehash);
my (@passedarray) = @{\$reftothearray);
my (%passedhash) = %{\$reftothehash);

exit;

Anyways, hope this is general enough to show everything passing back and forth. Hope this helps!! :)

Ben
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top