CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Function prototype to pass a literal hash reference

 



rpaskudniak
User


Nov 13, 2017, 5:11 PM

Post #1 of 6 (2641 views)
Function prototype to pass a literal hash reference Can't Post

Greetings, Family. Rasputin the verbose here.. Frown This post is no exception.

I am experimenting with function prototypes with an eye to using named parameters instead of a fixed-order parameter list. (I have no desire to stop using parentheses.) I have another purpose in mind as well, but let's not get ahead of the simpler issue.

In this code, which works, I call two similar functions, passing parameters named with the literal hash syntax. However, in the first call I put a list of 'parameter' => value parameters between the parentheses. In the second call I put that list between {braces}. Here's the code:

Code
  1 #!/usr/bin/perl -d -w 
2 # test-calls.pl - Just see how I pass a hash
3 #
4 use strict;
5 use warnings;
6 use Data::Dumper;
7
8 sub myfunc(%);
9 sub myfunc2(%);
10
11 my $p_count = myfunc('first' => "One",
12 'second' => "Two",
13 'third' => "Three");
14 printf("I counted %d parameters\n", $p_count);
15
16 $p_count = myfunc2({'first' => "One",
17 'second' => "Two",
18 'third' => "Three"});
19 printf("I counted %d keys\n", $p_count);
20
21 sub myfunc(%)
22 {
23 printf("This function accepts the whole hash\n");
24 my $rval = @_; # Get element count
25 my %z_hash = @_; # Cast it to a hash
26 my @items = keys %z_hash;
27 return $rval;
28 }
29
30 sub myfunc2(%)
31 {
32 printf("This function accepts the hash reference\n");
33 my $href = $_[0]; # First & only element is hash reference
34 my @items = keys %{$href};
35 return scalar @items;
36 }

Note that:
  • myfunc() sees the parameter list as an array and casts it into a hash variable.

  • myfunc2() sees a hash reference as its only parameter, $_[0]


  • However, the prototypes are identical: (%), while my obviously faulty intuition had initially tried to use (\%) as the prototype to myfunc2. I ended up reading (full disclosure: More skimming than reading Blush) Tom Christiansen's Far More than Everything You've Ever Wanted to Know about Prototypes in Perl and seeing that \% does NOT do what I expected. In the section "Problems with Reference Prototypes" Tom beautifully explains what a reference does in a prototype.

    Tom's explanation handles the errors I got when I used myfunc2(\%). So I have no problem anymore, except of my own making. Well, I'm kinda good at that... Sly

    What I had been leading up to was to overload the same function name: One version that accepts the named parameters as an array to be casted into a hash and the other that accepts the hash reference. Obviously, if I can't use different prototypes I can't overload the function name. And when I get this right I want to be able to use the same function name with different parameter arrangements in my application code.

    And now, you see the rest of the story (with a plagiarist's apology to Paul Harvey. Angelic)

    Is there a way anyone can think of to use the overload capability? Right now the only option I can think of is a single function that checks ref $_[0] to see whether or not it is a HASH reference. My application code has much of this and I have never been satisfied with it.

    Ideas?
    --------------------
    -- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)


    BillKSmith
    Veteran

    Nov 13, 2017, 8:54 PM

    Post #2 of 6 (2638 views)
    Re: [rpaskudniak] Function prototype to pass a literal hash reference [In reply to] Can't Post

    Without knowing your 'other purpose', I would use the function ref rather than prototypes.

    Code
    C:\Users\Bill\forums\guru>type 84525.pl 
    use strict;
    use warnings;

    sub myfunc {
    my %myargs = (ref($_[0]) eq 'HASH') ? %{$_[0]} : @_;
    my @items = keys %myargs;
    return scalar @items;
    }

    my $p_count = myfunc('first' => "One",
    'second' => "Two",
    'third' => "Three");
    printf("I counted %d parameters\n", $p_count);

    $p_count = myfunc({'first' => "One",
    'second' => "Two",
    'third' => "Three"});
    printf("I counted %d keys\n", $p_count);

    C:\Users\Bill\forums\guru>perl 84525.pl
    I counted 3 parameters
    I counted 3 keys

    Good Luck,
    Bill


    rpaskudniak
    User


    Nov 14, 2017, 10:05 PM

    Post #3 of 6 (2626 views)
    Re: [BillKSmith] Function prototype to pass a literal hash reference [In reply to] Can't Post

    Thanks for the reply Bill.

    And even greater thanks for reading through my post! I had at least one professor in college make some remarks about my facility for concision.

    This is exactly the technique I mentioned - the one I've used many times that leaves me feeling there must be a cleaner way.

    Since I do have that workaround and you have confirmed it for me I suppose I should just be satisfied with it and go on my merry way. But it will be an itch behind my ear forever more..

    (Hmm.. I can't think of a smiley that represents an itch behind the ear.. Cool )

    Still open to an untried idea here but losing hope of getting one.

    Who would get work done should not disdain the workaround.
    --------------------
    -- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)


    Laurent_R
    Veteran / Moderator

    Nov 15, 2017, 1:08 AM

    Post #4 of 6 (2621 views)
    Re: [rpaskudniak] Function prototype to pass a literal hash reference [In reply to] Can't Post

    Hi,

    this may not be the answer you're looking for, but I'll just mention that Perl 6 is doing exactly what you're looking for (if I understood correctly what you're up to), with a combination of subroutine signatures and so-called multi-functions. You can have several subroutines (multi subs) with the same name and the compiler will choose which one to call on the basis of the match between the calling arguments and the signature.

    The reason I'm mentioning this is that, maybe, the relatively new signature feature of Perl 5 might give you the functionality you're looking for, or some part thereof. (Note that I haven't explored at all the new signature feature in P5, since I am stuck at $work with an old version of Perl, so I am just saying it might be possible, I just don't know.)


    Laurent_R
    Veteran / Moderator

    Nov 15, 2017, 2:58 PM

    Post #5 of 6 (2610 views)
    Re: [Laurent_R] Function prototype to pass a literal hash reference [In reply to] Can't Post

    I now took the time to look at the documentation on Perl 5 signatures, it seems that it won't give you the multiple dispatch (or subroutine resolution at run time) that you're looking for.


    rpaskudniak
    User


    Nov 16, 2017, 3:20 PM

    Post #6 of 6 (2594 views)
    Re: [Laurent_R] Function prototype to pass a literal hash reference [In reply to] Can't Post

    A thread with Laurent. Hmm... Does that constitute a Laurent series? (Who says Math geeks don't have a sense of humor? Crazy )

    I appreciate you looking that up for me. It had not occurred to me to look up specific documentation for signatures. But there it is, the first topic in Perldoc Perlsub. I had not tried to

    Code
    use feature 'signatures'

    and the syntax that turns off the warning is somewhat less than clear.

    But I do get the message: I will continue to use the workaround confirmed by Bill. At least until I get around to downloading and installing Perl6. But that's an issue for another thread.

    Much thanks!
    --------------------
    -- Rasputin Paskudniak (In perpetual pursuit of undomesticated, semi-aquatic avians)

     
     


    Search for (options) Powered by Gossamer Forum v.1.2.0

    Web Applications & Managed Hosting Powered by Gossamer Threads
    Visit our Mailing List Archives