1

How could I pass a hash by reference to a subroutine without using the \ character in the subroutine calling expression like my_subroutine(%my_hash)?


More explanation: (in case the previous single-line question wasn't descriptive enough)

Passing a variable by reference to a subroutine without using the \ character in subroutine calling expression like my_subroutine($my_var) can be achieved by defining the subroutine as so:

sub my_subroutine {
    my $var_ref = \shift;
    ...
}

I have tried the same approach with hashes but it doesn't work properly:

sub my_subroutine {
    my $hash_ref = \shift;
    ...
}

I think that's because perl fragments any passed in hashes' keys-value pairs in a list (one-dimensional array) which is @_, also the same is done with passed-in arrays (but for values only not with keys).

I'm looking for a workaround on this to make my_subroutine(%my_hash) pass hash by-reference without the need to precede my subroutine parameters (hashes) by backslash character \ every time I call the subroutine. This will be helpful to make my main code look neater and leave the untidy looking to the inside of subroutines. Also if I'm working with a large group of developers, someone may forget to add the referencing character. I need to set that (hashes are always passed by reference to my_subroutine) inside the subroutine not by the other developer who calls my_subroutine.

Omar
  • 6,681
  • 5
  • 21
  • 36
  • Re "*I think that's because...*", The only thing that can be passed to subs (and returned from subs) are a number of scalars. The scalars you are passing when you do `my_subroutine(%my_hash)` consist of copies of the keys and the (actual non-copy) values of the hash. (Prototypes can affect which scalars are passed.) – ikegami Feb 11 '17 at 07:47
  • Re "*Passing a variable by reference to a subroutine without using the `\ ` character...*", Variables are always [passed *by* reference](http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value) in Perl (which is why `my $var_ref = \shift;` can get you a reference to it). Using `\ ` on the caller side passes *a* reference (which is, of course, passed by reference). – ikegami Feb 11 '17 at 07:49
  • 2
    *"This will be helpful to make my main code look neater"* It will also be misleading about what is actually happening. If that is your only goal then forget it. – Borodin Feb 11 '17 at 11:23

2 Answers2

5

Prototypes may still considered bad, but you can use them here to achieve your goal.

sub my_subroutine (\%) {
    my $hashref = shift;
    ...
}

my_subroutine(%hash);

With the prototype, the first argument to the subroutine is coerced to a hash reference.

Note that inside the subroutine, the hash is received as a hash reference. You will also need to call the subroutine with a named hash.

my_subroutine( { "anonymous" => "hash", "not" => "OK" } );  # not OK with proto
Community
  • 1
  • 1
mob
  • 117,087
  • 18
  • 149
  • 283
  • 2
    Take a look at [*Prototypes Considered Harmful*](http://www.perlmonks.org/?node_id=861966) by the excellent Tom Christiansen. I think it's counter-productive to imply to the OP, who is presumably a beginner, that it's okay to use prototyped subroutines so that they don't have to put backslashes in their call parameters. – Borodin Feb 11 '17 at 14:55
0

How about something like this:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Printer;

my %h1 = ( a => 10, b => 20);
mySub(%h1);

sub mySub {
    my ($h1) = {@_};
    p $h1;
}
Aranya Sen
  • 974
  • 8
  • 13
  • There's something wrong. It doesn't support editing the passed-in hash. Kindly check my test code [here](https://gist.github.com/omarabdelsalam/2e238f24ae9961a984a9a40e97fe7439). – Omar Feb 11 '17 at 04:11
  • 1
    @Omar That's because `{@_}` copies the contents of `@_` into a new anonymous hash. You won't be able to modify the original hash with this approach. – ThisSuitIsBlackNot Feb 11 '17 at 04:25
  • In that case you have to use prototype (and ensure the sub is defined _before_ it is used). Please check the reply to your gist – Aranya Sen Feb 11 '17 at 04:26
  • Gist was showing sub mySub(\%) as sub mySub(%). Please check now. – Aranya Sen Feb 11 '17 at 04:36