'Confusion on syntax of of diamond operator in parsing and barewords

I'm very new to perl, so I'm sure my confusion here is simply due to not understanding perl syntax and how it handles bare words. I'm failing to find good answers to my question online though.

I had code I'm refactoring, it use to look like this

@month_dirs = <$log_directory/*>;

I changed $log_directory to be loaded with a config file (AppConfig to be exact). Now instead of exporting $log_directory we output $conf which is an AppConfig object. To access loaded variables you usually make a method call to the variable name so I tried ...

@month_dirs = <$conf->log_directory()."/*">

This fails, because I can't make a method call $conf->log_directory in a location where a barword is expected. Just playing around I tried this instead

 $month_directory_command = $conf->log_directory()."/*";
 @month_dirs = <$month_directory_command>;

This still fails, silently, without any indicator that this is a problem. I tried using a string directly in the diamond but it fails, apparently only barewords, not strings, are accepted by the diamond I'm surprised by that since I'm not allowed to use a string at all, I thought most places Barewords could be used a string could instead, is this simply because most code implements separate logic to accept barewords vs strings, but not required to be implemented this way?

I can make this work by emulating exactly the original syntax

 $month_directory_command = $conf->log_directory();
 @month_dirs = <$month_directory_command/*>;

However, this feels ugly to me. I'm also confused why I can do that, but I can't create a bare word with:

 $bare_word = $conf->log_directory()/*

or

 $month_directory_command = $conf->log_directory();
 $bare_word = $month_directory_command/*;
 @month_dirs = <$bare_word>;     

Why do some variables work for bare words but not others? why can I use a scaler variable but not if it's returned from a method call?

I tried looking up perl syntax on barewords but didn't have much luck describing situations where they are not written directly, but are composed of variables.

I'm hoping someone can help me better understand the bareword syntax here. What defines when I can use a variable as part of a bare word and if I can save it as a variable?

I'd like to figure out a cleaner syntax for using the barword in my diamond operator if one can be suggested, but more then that I'd like to understand the syntax so I know how to work with barewords in the future. I promise I did try hunting this down ahead of time, but without much luck.

Incidentally, it seems the suggestion is to not use barewords in perl anyways? Is there someway I should be avoid barewords in the diamond operator?



Solution 1:[1]

One of the main reasons to avoid the diamond operator like this is that it has two totally-unrelated meanings. The usual form you find diamond in is

$data = <$fh>;

This acts like a read function; the full (non-symbol) name for this function is readline. This line of source is equivalent to

$data = readline( $fh );

However, your original form given was

@month_dirs = <$log_directory/*>;

which is an entirely different form. This acts like a shell glob, returning a list of filename matches by scanning the filesystem. This form is better written out using the glob function:

@month_dirs = glob( "$log_directory/*" );

Note also that this being a normal function just takes a normal string argument. In this manner, you can use it with any of your provided examples, such as:

@month_dirs = glob( $conf->log_directory()."/*" );

Solution 2:[2]

bareword can only be inside the bracket <>, syntax inside is shell syntax, more a perl one

# wrong -     
$bare_word = $month_directory_command/*;
# right - star is allowed because it is inside the quote single or double
$bare_word = "$month_directory_command/*";

# star is allowed simply because it is inside the bracket
@month_dirs = <$month_directory_command/*>;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LeoNerd
Solution 2 Gang