Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Dollar Bracket Star ${*...}

by snoopyjc (Initiate)
on Dec 27, 2021 at 18:17 UTC ( [id://11139947]=perlquestion: print w/replies, xml ) Need Help??

snoopyjc has asked for the wisdom of the Perl Monks concerning the following question:

Hi I've been programming in perl for quite some time now, and it's the first time I've run into this construct before, looking at the source code for Net::FTP (https://perldoc.perl.org/Net::FTP.txt):
${*$ftp}{'net_ftp_host'} = $host; # Remote hostname ${*$ftp}{'net_ftp_type'} = 'A'; # ASCII/binary/etc mode ${*$ftp}{'net_ftp_blksize'} = abs($arg{'BlockSize'} || 10240);
As far as I know, "*" is a typeglob representing $ftp %ftp @ftp and ftp, but why are they using that here? Shouldn't the code just say $ftp->{'net_ftp_host'} = $host; ?

Replies are listed 'Best First'.
Re: Dollar Bracket Star ${*...}
by LanX (Saint) on Dec 27, 2021 at 19:12 UTC
    > *$ftp

    That's dereferencing of a glob reference, admittedly not a very common construct.

    > ${*$ftp}{KEY}

    That's accessing the %hsh for $ftp=\*hsh with $hsh{KEY}

    > I've been programming in perl for quite some time now

    you might have seen constructs like \*DATA before, those are glob references.

    DB<7> x \*DATA 0 GLOB(0x2d92040) -> *main::DATA DB<8> p ref \*DATA GLOB

    I hope it's clearer now.

    Bareword filehandles and globs are historically linked. (Perl4 legacy IIRC)

    EDIT

    or better phrased the slot for filehandles in typeglobs has no own sigil like other types, hence you can only use *glob for referencing them.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      Thanks Rolf and all others! I did some digging and found this at the bottom of sub new in IO::Handle:
      my $io = gensym; bless $io, $class;
      The call to gensym is also new to me but I looked it up and now I understand what’s going on! —joe
Re: Dollar Bracket Star ${*...}
by jdporter (Paladin) on Dec 27, 2021 at 18:35 UTC

    No, $ftp->{...} would imply that $ftp is a hash reference. But it is not, it is a glob reference.

Re: Dollar Bracket Star ${*...}
by perlfan (Vicar) on Dec 27, 2021 at 22:11 UTC
    There's a lot going on there, but this might be helpful, Chapter 8. Symbol Tables and Typeglobs (from Mastering Perl by bdf).

    If you've ever seen the construct of locally mocking a subroutine, it's the same concept:
    # code not tested sub test_this { my $stuff = call_to_external_service(); return $stuff; } #... # subroutine mock for a unit test, e.g., { no warnings qw/redefine/; my $expected = { some => 'expected result'}; local *call_to_external_service = sub { return $expected, }; # now call a test or something that calls is_deeply test_this(), $expected, qw{whatever...}; }
    The * on the LHS is like a wild card to match the "type" on the RHS. Another term related to this is monkey patching.

      Monkey patching can be quite useful in another way, too. It allows to generate lots of functions in a loop instead of writing them one-by-one. I sometimes use this in some wrapper modules, so i can for example log all database calls for debugging.

      BEGIN { # Auto-magically generate a number of similar functions without ac +tually # writing them down one-by-one. This makes changes much easier, bu +t # you need perl wizardry level +10 to understand how it works... my @simpleFuncs = qw(commit rollback errstr); my @stdFuncs = qw(do quote pg_savepoint pg_rollback_to pg_release) +; for my $a (@simpleFuncs){ no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitN +oStrict) *{__PACKAGE__ . "::$a"} = sub { $_[0]->checkDBH(); return $_[0 +]->{mdbh}->$a(); }; } for my $a (@stdFuncs){ no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitN +oStrict) *{__PACKAGE__ . "::$a"} = sub { $_[0]->checkDBH(); if($_[0]->{ +isDebugging}) {print STDERR $_[0]->{modname}, " ", $_[1], "\n";}; ret +urn $_[0]->{mdbh}->$a($_[1]); }; } };

      perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
        $a is a special variable. Don't use it for anything else.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: Dollar Bracket Star ${*...}
by eyepopslikeamosquito (Archbishop) on Dec 28, 2021 at 00:47 UTC
Re: Dollar Bracket Star ${*...}
by ikegami (Patriarch) on Dec 28, 2021 at 23:47 UTC

    The symbol table consists of a hierarchy of globs. A glob, short for typeglob, is a structure that has a slot for each variable type supported by Perl (and a few more). By using a glob for each symbol in the symbol table, we can have variable of each type with the same name.

    • Scalar ($foo)
    • Array (@foo)
    • Hash (%foo)
    • Sub (&foo)
    • File handle
    • Dir handle
    • Format
    • etc

    $ftp is expected to be a glob. (Probably so it can be used as a file handle.)


    ${*$ftp}{net_ftp_host}
    can also be written as
    $ftp->**->{net_ftp_host}
    which is equivalent to
    $ftp->*{HASH}->{net_ftp_host}

    But it's not equivalent to

    $ftp->{net_ftp_host} # XXX

    The program is accessing the HASH slot of the glob, which contains a reference to a hash with the object's attributes.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11139947]
Approved by Perlbotics
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (1)
As of 2024-04-25 19:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found