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

Oh Mighty Gurus,

This is a Perl 101 question for sure, but I don't know what this code/operator/action is called, so I can't look up on internet what it is and find out what it does!

To wit, I have some code that, eventually, has a variable called $bcsdir that has the value of a long path-like string:

/part/of/path/Ganymed-4_0/Ganymed-4_0_Reynolds/CF0180x6C
Now, that last node doesn't actually exist on disk, but .../Ganymed-4_0_Reynolds/CF0180x6C_DE0360xPE0180 does. In the code, I then see this operate on $bcsdir:
$bcsdir = (<${bcsdir}*>)[0];
and that seems to expand out the path...or something? Because after that call, $bcsdir now has:
/part/of/path/Ganymed-4_0/Ganymed-4_0_Reynolds/CF0180x6C_DE0360xPE0180
The variable is longer and exists as a path!

So, in trying to help me learn how to hack Perl: what is happening and what is it called? Is this some magic I should learn? :)

Thanks, Matt

Replies are listed 'Best First'.
Re: What is this Perlism called...and what does it do?
by LanX (Saint) on Oct 28, 2021 at 19:54 UTC
    • <${bcsdir}*> is a "File Glob" (like with ls $bcsdir* in a unix shell)
    • $bcsdir = (...)[0] is a "List Slice" which returns the first element of the inner result list ...
    • (... or an empty list (resp undef in scalar context) if the result is empty)

    HTH! :)

    update

    here a little demo in the debugger

    > perl -de0 ... DB<15> $path = 'D:/tmp' DB<16> x <$path/x*> 0 'D:/tmp/xref.txt' 1 'D:/tmp/xref_trace' DB<17> x (<$path/x*>)[0] 0 'D:/tmp/xref.txt' DB<18>

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

Re: What is this Perlism called...and what does it do?
by choroba (Cardinal) on Oct 28, 2021 at 21:08 UTC
    The <...> can mean two different things: either a readline, or a glob. To be interpreted as the former, the thing inside the angle brackets must be a scalar, or a typeglob, or a typeglob reference, which it isn't here. It's usually cleaner to use glob directly, i.e.
    $bcsdir = (glob "$bcsdir*")[0];
    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: What is this Perlism called...and what does it do?
by hippo (Archbishop) on Oct 28, 2021 at 21:41 UTC

    You have the correct answers already. However, I thought it worth mentioning that the line in question can be made potentially less confusing by discarding the unwanted elements of the list on the left side of the assignment rather than the right. That is you can replace

    $bcsdir = (<${bcsdir}*>)[0];

    with

    ($bcsdir) = <${bcsdir}*>;

    The brackets on the left enforce list context and with only one element inside those brackets all bar the first result are discarded. The braces are not needed either, so it can be slimmed down further to just

    ($bcsdir) = <$bcsdir*>;

    Which of these is actually clearest is likely in the eye of the beholder.


    🦛

Re: What is this Perlism called...and what does it do?
by mathomp4 (Novice) on Oct 29, 2021 at 12:03 UTC
    Ahhh. Thanks all. For some reason my brain just didn't see <foo> inside the parentheses as a filehandle. I kept trying to figure out what the (<...>) operator was. And man, searching Google for "parentheses less-than perl" or "parentheses angle-bracket operator perl" is...not useful. :D
      > didn't see <foo> inside the parentheses as a filehandle

      In this case it's not a readline filehandle but a glob pattern like choroba already explained.

      The DWIM rules to distinguish between glob and readline are more complex tho °, but it's mostly evident by context.

      > And man, searching Google for "parentheses less-than perl" or ...

      try Perl Diamond Operator.

      As a rule of thumb, if you need to look up a Perl operator, search perlop (sic)

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

      °) from perlop#I/O-Operators

      > That means <$x> is always a readline() from an indirect handle, but <$hash{key}> is always a glob(). That's because $x is a simple scalar variable, but $hash{key} is not--it's a hash element. Even <$x > (note the extra space) is treated as glob("$x "), not readline($x).

Re: What is this Perlism called...and what does it do?
by Anonymous Monk on Oct 29, 2021 at 16:07 UTC

    If you want, you can also expand the angle brackets into something (IM(NS)HO) more readable:

    use File::Glob 'bsd_glob';
    
    ...
    
    ( $bcsdir ) = bsd_glob( "$bcsdir*" );
    
    

    Note that the curly brackets around the variable name in the interpolation are only needed if what comes after the variable name might look like a longer variable name. For example, you could print it as print "$bcsdir\n";, but if you wanted to pluralize the output (in English) for some reason it would have to be print "${bcsdir}s\n";. In this extremely contrived example the curly brackets keep Perl from thinking you want to interpolate $bcsdirs.