Subroutine that returns a hash - splits it into separate variables

I have a routine that returns a hash. The last lines of the subroutine:

print Dumper(\%fileDetails); return %fileDetails; 

in this case, the recorder prints:

 $VAR1 = { 'somthing' => 0, 'somthingelse' => 7.68016712043654, 'else' => 'burst' } 

But when I try to reset it by calling the subroutine with this line:

 print Dumper(\fileDetailsSub($files[$i])); 

self test print:

 $VAR1 = \'somthing'; $VAR2 = \0; $VAR3 = \'somthingelse'; $VAR4 = \7.68016712043654; $VAR5 = \'else'; $VAR6 = \'burst'; 

Once the hash is broken, I can no longer use it. Why is this happening? And how can I maintain the correct structure when returning a subroutine?

Thanks Mark.

+6
source share
5 answers

There is no such thing as returning a hash in Perl.

Routines take lists as their arguments and can return lists as their results. Note that a list is a completely different creature from the array.

When you write

 return %fileDetails; 

This is equivalent to:

 return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' ); 

When you call a routine and return this list, one thing you can do is assign a new hash to it:

 my %result = fileDetailsSub(); 

This works because the hash can be initialized with a list of key-value pairs. (Remember that (foo => 42, bar => 43 ) is the same as ('foo', 42, 'bar', 43) .

Now, when you use the backslash reference operator in a hash, as in \%fileDetails , you get a hash that is a scalar that points to a hash.

Similarly, if you write \@array , you will get a reference to the array.

But when you use the link operator in a list, you do not get a link to the list (since lists are not variables (they are ephemeral), they cannot be referenced.) Instead, the link operator distributes over the list items, therefore

 \( 'foo', 'bar', 'baz' ); 

creates a new list:

 ( \'foo', \'bar', \'baz' ); 

(In this case, we get a list full of scalar links.) And this is what you see when you try to Dumper results of your subroutine: a reference operator distributed over the list of items returned from your sub.

So, one solution is to assign the result list to the actual hash variable before using Dumper. The other is to return a hash link (that you are splitting anyway) from sub:

 return \%fileDetails; ... my $details_ref = fileDetailsSub(); print Dumper( $details_ref ); # access it like this: my $elem = $details_ref->{something}; my %copy = %{ $details_ref }; 

See below for more details.

+9
source

Why not return a hash link instead?

 return \%fileDetails; 

As long as it is a lexical variable, it will not complicate the work with other uses of the subprogram. I.e:.

 sub fileDetails { my %fileDetails; ... # assign stuff return \%fileDetails; } 

When execution exits the subroutine, the variable goes out of scope, but the data contained in the memory remains.

It looks like the output of Dumper looks like you are giving it a list of links. Subroutines cannot return arrays or hashes; they can only return lists of scalars. What you do is something like this:

 print Dumper \(qw(something 0 somethingelse 7.123 else burst)); 
+8
source

Perl functions cannot return hashes, only lists. The return %foo aligns %foo to a list and returns a flattened list. To get the return value that will be interpreted as a hash, you can assign it to a named hash

 %new_hash = fileDetailsSub(...); print Dumper(\%new_hash); 

or pronounce it (not sure if this is the best word for him) with the sequence of operations %{{...}} :

 print Dumper( \%{ {fileDetailsSub(...)} } ); 

Another approach, as TLP points out, is to return a hash link from your function.

+3
source

You cannot return the hash directly, but perl can automatically convert between hashes and lists as needed. So perl converts this to a list, and you grab it as a list. i.e.

 Dumper( filedetail() ) # list my %fd = filedetail(); Dumper( \%fd ); #hash 
+1
source

In the context of a list, Perl does not distinguish between a hash and a list of key / value pairs. That is, if the subroutine return hash, then what it really returns is a list (key1, value1, key2, value2...) . Fortunately, this works both ways; if you take such a list and assign it to a hash, you will get a true copy of the original:

 my %fileDetailsCopy = subroutineName(); 

But if he had not violated another code, most likely it would have been more reasonable if the sub-return referred to the hash, as TLP said.

0
source

Source: https://habr.com/ru/post/946024/


All Articles