print statement creates key in hash with reference to empty array??

R

rhorizon74

In the code below the print val statement actually creates an key 'ABC'
in the hash if it does not exist ( i wanted to print the value of the
0th element in an array , the reference to which is stored in a hash
with key 'ABC').

Why should a print create a new key, shouldnt it just print undefined,
and not create any new key.

Thank you
Code:

use strict;
use Data::Dumper;
&main();

sub main
{
my %a;
my $aref = \%a;

print "val: @{$aref->{ABC}}[0]\n";
print Dumper($aref)."\n";
}


Output:
val:
$VAR1 = {
'ABC' => []
};
 
A

A. Sinan Unur

In the code below the print val statement actually creates an key
'ABC' in the hash if it does not exist ( i wanted to print the value
of the 0th element in an array , the reference to which is stored in a
hash with key 'ABC').

That's called autovivification (sp?) You can read Uri Guttman's article:

http://www.sysarch.com/Perl/tutorials/autoviv.html

If you want to avoid it, you need to use exists, and print only when the
said element does exist.

if( exists $hash{$key} ) {
print "$hash{$key}\n";
}
Why should a print create a new key, shouldnt it just print undefined,
and not create any new key.

Why do you think so?
use strict;

use warnings;

missing.
use Data::Dumper;
&main();

Do you know what '&' does here? If not, then don't use it.

See

perldoc perlsub


Sinan
 
I

it_says_BALLS_on_your forehead

rhorizon74 said:
In the code below the print val statement actually creates an key 'ABC'
in the hash if it does not exist ( i wanted to print the value of the
0th element in an array , the reference to which is stored in a hash
with key 'ABC').

Why should a print create a new key, shouldnt it just print undefined,
and not create any new key.

Thank you
Code:

use strict;
use Data::Dumper;
&main();

sub main
{
my %a;
my $aref = \%a;

print "val: @{$aref->{ABC}}[0]\n";
print Dumper($aref)."\n";
}


Output:
val:
$VAR1 = {
'ABC' => []
};

lookup autovivification.
 
R

rhorizon74

Thanks for the help.

That explains what is happening (i had used the exists approach to work
around).
But it does seem bogus that for a simple print statement i need to
check each and every level. I havent seen too many languages do
something like this (i may be wrong).
But a print statement shouldnt really be creating any data.


Thanks for the help though.
 
A

A. Sinan Unur

But it does seem bogus that for a simple print statement i need to
check each and every level. I havent seen too many languages do
something like this

Please feel free to use one of the languages that behave in the way you
think they should.

Sinan
 
D

Dr.Ruud

A. Sinan Unur schreef:
if( exists $hash{$key} ) {
print "$hash{$key}\n";
}


Hunting for alternatives:

$ echo 'if( exists $hash{$key} ) { print "$hash($key)\n"; }' \
| perl -MO=Deparse,-x7

exists $hash{$key} and do {
print "$hash($key)\n"
};

I don't know why the do-block is needed.


$ echo 'print "$hash{$key}\n" if exists $hash{$key};' \
| perl -MO=Deparse,-x7

exists $hash{$key} and print "$hash{$key}\n";
 
A

A. Sinan Unur

A. Sinan Unur schreef:



Hunting for alternatives:

$ echo 'if( exists $hash{$key} ) { print "$hash($key)\n"; }' \

Check out the missing curlies in the second hash access. Not that it
changes anything.

Sinan
 
R

rhorizon74

Just wanted to check if i was missing anything, Didnt think anybody
woud get offended if i questioned a programming language, didnt realize
that the perl way was set in stone.

Thanks for your help anyways
 
A

A. Sinan Unur

[ Please quote some context when you reply. ]

Just wanted to check if i was missing anything, Didnt think anybody
woud get offended if i questioned a programming language, didnt realize
that the perl way was set in stone.

You did not offend anyone, at least not me.

It was obvious that you had not read either the link I posted, or the
documentation, and yet you were still opining about what should and should
not be. With that attitude, I rather not read your posts.

Sinan
 
U

Uri Guttman

r> Thanks for the help.
r> That explains what is happening (i had used the exists approach to work
r> around).
r> But it does seem bogus that for a simple print statement i need to
r> check each and every level. I havent seen too many languages do
r> something like this (i may be wrong).
r> But a print statement shouldnt really be creating any data.

if you read my article (which sinan posted the url for) then you will
learn more about autoviv and why it is like it is. and even calling
exists will do the same thing (but that is being fixed in perl6). the
win of autovivication is much greater then the loss of rare code like
yours. if you didn't have it you would need to check each time you used a
reference in structure and either assign a new one or use the existing
one. that is massively ugly and clumsy (and i have seen newbies coding
like that all the time).

uri
 
A

Ala Qumsieh

rhorizon74 said:
Thanks for the help.

That explains what is happening (i had used the exists approach to work
around).
But it does seem bogus that for a simple print statement i need to
check each and every level. I havent seen too many languages do
something like this (i may be wrong).
But a print statement shouldnt really be creating any data.

It is not the print(), it is the fact that you are trying to access the
value of the ABC key. If hashes didn't autovivify, then you won't be
able to do this:

$hash{key1}{key2}{key3} = 'value';

before you actually create all the keys explicitly:

$hash{key1} = {};
$hash{key1}{key2} = {};
$hash{key1}{key2}{key3} = 'value';

Autovivification is a Good Thing (tm).

--Ala
 
X

xhoster

rhorizon74 said:
Thanks for the help.

That explains what is happening (i had used the exists approach to work
around).
But it does seem bogus that for a simple print statement i need to
check each and every level. I havent seen too many languages do
something like this (i may be wrong).

Right. Many languages would just seg-fault, or perhaps corrupt memory
and take down the entire system, instead.
But a print statement shouldnt really be creating any data.

What should it do?

Xho
 
R

rhorizon74

Hi,

The code i posted is just a sample, i was trying to understand exactly
what was happening.

The are a bunch of scenarios where a different module is supposed to
build a hash, and my module needs to print the values. In which case
for each level of nesting of a hash i will be forced to check if the
node exists (starting with the outer hash and going onto the inner
hash). With my limited exposure to perl i guess it seemed a bit
diffcult to grasp.

I do understand the efficiency it provides while creating a structure.

I did check with a lot of colleagues some who were not exactly novices
like me with way much more experience in perl and they too had come
across this scenario (they grappled with this by adding checks for each
level before printing the values) , but to be honest none with any
exact knowlege of vivication. So it did seem like this problem was
commonly faced by a lot of programmers.


Thanks for the reply
 
R

rhorizon74

Hi,

Id rather have my program fail, most scripting languages would print an
error (they would not seg-fault). That would be better than giving
incorrect results.

Moral of the story is i need to do an exists before i do anything with
any hash related structure in perl.

Thank you
 
U

Uri Guttman

r> The are a bunch of scenarios where a different module is supposed to
r> build a hash, and my module needs to print the values. In which case
r> for each level of nesting of a hash i will be forced to check if the
r> node exists (starting with the outer hash and going onto the inner
r> hash). With my limited exposure to perl i guess it seemed a bit
r> diffcult to grasp.

why are you printing lower levels and not the upper ones? try using
data::dumper instead of rolling your own tree dumper.

r> I did check with a lot of colleagues some who were not exactly novices
r> like me with way much more experience in perl and they too had come
r> across this scenario (they grappled with this by adding checks for each
r> level before printing the values) , but to be honest none with any
r> exact knowlege of vivication. So it did seem like this problem was
r> commonly faced by a lot of programmers.

it seems you still haven't read my article. have you? it has a sub which
will do what you want so you don't have to reinvent it. i suggest you
read it and also tell your colleagues to read it.

r> Thanks for the reply

no thanks for the top post with full quote of my email. have you read
the group guidelines which are posted regularly?

<snip of my entire quoted post>

uri
 
U

Uri Guttman

r> Id rather have my program fail, most scripting languages would print an
r> error (they would not seg-fault). That would be better than giving
r> incorrect results.

incorrect results? by whose definition are the results incorrect? you
didn't read the docs to understand autoviv and assumed incorrect
behavior. i lay that on you and not perl.

r> Moral of the story is i need to do an exists before i do anything with
r> any hash related structure in perl.

the real moral is you haven't learned yet how to work with perl data
structures. needing to print low level entries is very unusual. that
leads me to suspect the quality of your structure's design. i have done
many deep structures and never have come across this need. usually
something at a higher level can be done so you don't need to directly
access missing elements and thereby cause autoviv to happen.

until you learn more about perl and its data structures you will be
doomed to this poor style of design and coding.

and read my article already. it was written specifically for you.

uri
 
D

Dr.Ruud

Abigail:
Dr.Ruud:

Because the then part of an if statement is a block. 'do {}' turns a
block into an expression.

I still don't see why it isn't 'cleaned up' further in the special case
that the expression is one statement. As you can deduce, I assume that
the "do{}" is never necessary around a single statement, that "()" is
sufficient.

I don't expect "()" for "do{}" to speed up anything, I just wondered a
bit why that step isn't taken.
 
A

Anno Siegel

Dr.Ruud said:
Abigail:

I still don't see why it isn't 'cleaned up' further in the special case
that the expression is one statement. As you can deduce, I assume that
the "do{}" is never necessary around a single statement, that "()" is
sufficient.

No, the "do{}"s are necessary, there *must* be a statement in this place.
It's just that the DWIM mechanism inserts them for you in many situations
where little else would make sense. What deparse shows is what perl
actually compiles.
I don't expect "()" for "do{}" to speed up anything, I just wondered a
bit why that step isn't taken.

I don't see who could take that step. The Perl interpreter needs the
"do{}"s, it cant discard them. Deparsing can't very well suppress them
either, once they're there.

Anno
 
D

Dr.Ruud

Anno Siegel schreef:
Dr.Ruud:

No, the "do{}"s are necessary, there *must* be a statement in this
place. It's just that the DWIM mechanism inserts them for you in many
situations where little else would make sense. What deparse shows is
what perl actually compiles.

From an earlier post:

$ echo 'print "$hash{$key}\n" if exists $hash{$key};' \
| perl -MO=Deparse,-x7

exists $hash{$key} and print "$hash{$key}\n";

That doesn't get a do{}.

Deparse can't very well suppress them either, once they're there.

And I just wondered why not, for cases like this one.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top