Why use &getcwd() and not getcwd() in Perl? - perl

I am new to Perl language, and in the code I am using there is this line :
$BASEDIR = &getcwd();
I am wondering why there is a & in front of the call to getcwd, and I could not find any reference about that. Could someone help me with this ?
Thanks a lot !

It causes the subroutine's prototype to be ignored.
$ perl -e'
sub f($#) { print("#_\n"); }
my #a = (4,5,6);
f(4,5,6);
f(#a);
&f(#a);
'
4 5 6
3
4 5 6
But that's probably not the reason it's used here. After all, Cwd::getcwd doesn't have a prototype. & can't be used on named operators (i.e. the functions of perlfunc, e.g. print), so some beginners use it on subroutines to distinguish them from operators. I believe this is a practice recommended by a popular Perl book.

Short answer is that it is optional unless you are running a really old version of perl.
For more detail see the perlsub man page (run perldoc perlsub or man perlsub depending on your environment)
A subroutine may be called using an explicit "&" prefix. The "&" is optional in modern Perl, as are parentheses if the subroutine has been predeclared. The "&" is not optional when just naming the subroutine, such as when it's used as an argument to defined() or undef(). Nor is it optional when you want to do an indirect subroutine call with a subroutine name or reference using the "&$subref()" or "&{$subref}()" constructs, although the "$subref->()" notation solves that problem. See perlref for more about all that.

Related

Why Perl ignores spaces between a sigil and variable name?

The question Is space supposed to be ignored between a sigil and its variable name? was answered positively.
What is the reason Perl interprets $ foo as $foo?
perl -w -E 'my $ foo = $$; say "Perl $]\n\$ foo = ", $foo'
Perl 5.028001
$ foo = 3492
Isn't it against The Syntax of Variable Names documentation?
That documentation only discusses the name, not the sigil. The sigil can always be separated from the name by space characters. It is definitely underdocumented and I would not suggest ever making use of it, but it is used.
Perl does not have sigils, it has "dereference" operators:
$test[1] means 'give me the scalar at the index 1 of the array called "test" from this scope'. That is why you can put spaces after the "sigil".
I don't understand why everybody keeps calling them sigils, it makes things very confusing. BASIC had sigils, PHP has sigils, but Perl 5 does not even if it looks like it has. I wish I had realized the "sigils" are in fact operators when I was learning Perl, understanding and parsing references and derefferencing would have been a lot easier, not to mention grokking symbol tree manipulation.
The "sigils" are not documented as "operators" in perldoc, but it is much easier to parse Perl code if you think of them as being operators.
Later, after discussion in the comments: here is how Perl 5 uses "sigils": https://www.oreilly.com/library/view/advanced-perl-programming/0596004567/ch01.html

What does the dollar character in the brackets of a Perl subroutine mean?

I've inherited some Perl code and occasionally I see subroutines defined like this:
sub do_it($) {
...
}
I can't find the docs that explain this. What does the dollar symbol in brackets mean?
It is a subroutine prototype.
The single $ means that the sub will only accept a single scalar value, and will interpret other types using scalar context. For instance, if you pass an array as the param e.g. do_it(#array), Perl will not expand #array into a list, but instead pass in the length of the array to the subroutine body.
This is sometimes useful as Perl can give an error message when the subroutine is called incorrectly. Also, Perl's interpreter can use the prototypes to disambiguate method calls. I have seen the & symbol (for code block prototype) used quite neatly to write native-looking routines that call to anonymous code.
However, it only works in some situations - e.g. it doesn't work very well in OO Perl. Hence its use is a bit patchy. Perl Best Practices recommends against using them.
The ($) is called a subroutine prototype.
See the PerlSub man page for more information: http://perldoc.perl.org/perlsub.html#Prototypes
Prototyping isn't very common nowadays. Best Practice is not using it.

Perl 6 - Subroutine taking "Bareword" input

So I've been diving into Perl 6 and have been looking at interpreting another language using Perl 6's operator definitions. I understand that this could be done by parsing the code but I'm looking to push Perl 6's capabilities to see what it can do. Having this functionality would also make the parsing a lot easier
I'm trying to make a variable definition in a C-style format.(The language isn't important)
Something like:
char foo;
Where the char represents the type and the foo is the variable name. From my understanding the char can be interpreted using an operator definition like so:
sub prefix:<char>($input) {
say $input;
}
Which calls a subroutine with the foo as $input. The idea from here would be to use foo as a string and hold it's reference in a hash somewhere. The problem with this is that Perl 6 seems to see any bareword as a function call and will complain when it can't find the "Undeclared routine".
I've looked possibly everywhere for an answer to this and the only thing that makes me still think that this may be possible is the qw function from Perl 5 which is now < > in Perl 6. The < > is obviously an operator which leads me to believe that there is a subroutine defined somewhere that tells this operator how to work and how to deal with the bareword input.
So to my question:
Is there a way of accepting bareword input into a subroutine just like the < > operator does?
Cheers!
The best way to do that would be to create a Grammar that parses your language. If you additionally want it to run the DSL you have just created, combine it with Actions.

Should I call Perl subroutines with no arguments as marine() or marine?

As per my sample code below, there are two styles to call a subroutine: subname and subname().
#!C:\Perl\bin\perl.exe
use strict;
use warnings;
use 5.010;
&marine(); # style 1
&marine; # style 2
sub marine {
state $n = 0; # private, persistent variable $n
$n += 1;
print "Hello, sailor number $n!\n";
}
Which one, &marine(); or &marine;, is the better choice if there are no arguments in the call?
In Learning Perl, where this example comes from, we're at the very beginning of showing you subroutines. We only tell you to use the & so that you, as the beginning Perler, don't run into a problem where you define a subroutine with the same name as a Perl built-in then wonder why it doesn't work. The & in front always calls your defined subroutine. Beginning students often create their own subroutine log to print a message because they are used to doing that in other technologies they use. In Perl, that's the math function builtin.
After you get used to using Perl and you know about the Perl built-ins (scan through perlfunc), drop the &. There's some special magic with & that you hardly ever need:
marine();
You can leave off the () if you've pre-declared the subroutine, but I normally leave the () there even for an empty argument list. It's a bit more robust since you're giving Perl the hint that the marine is a subroutine name. To me, I recognize that more quickly as a subroutine.
The side effect of using & without parentheses is that the subroutine is invoked with #_. This program
sub g {
print "g: #_\n";
}
sub f {
&g(); # g()
&g; # g(#_)
g(); # g()
g; # g()
}
f(1,2,3);
produces this output:
g:
g: 1 2 3
g:
g:
It's good style to declare your subroutines first with the sub keyword, then call them. (Of course there are ways around it, but why make things more complicated than necessary?)
Do not use the & syntax unless you know what it does exactly to #_ and subroutines declared with prototypes. It is terribly obscure, rarely needed and a source of bugs through unintended behaviour. Just leave it away – Perl::Critic aptly says about it:
Since Perl 5, the ampersand sigil is completely optional when invoking subroutines.
Now, given following these style hints, I prefer to call subroutines that require no parameters in style 1, that is to say marine();. The reasons are
visual consistency with subroutines that do require parameters
it cannot be confused with a different keyword.
As a general rule I recommend the following:
Unless you need the & because you're over riding a built in function or you have no parameter list omit it.
Always include the () as in marine().
I do both of these for code readability. The first rule makes it clear when I'm overriding internal Perl functions by making them distinct. The second makes it clear when I'm invoking functions.
perl allows you to omit parenthesis in your function call.
So you can call your function with arguments in two different ways:
your_function( arg1,arg2,arg3);
or
your function arg1,arg2,arg3 ;
Its a matter of choice that which form do you prefer. With users from C background the former is more intuitive.
I personally use the former for functions defined by me and latter for built in functions like:
print "something" instead of print("something")

Are #{$list_ref} and #$list_ref equivalent in Perl?

I am new to Perl and am curious whether #{$list_ref} and #$list_ref are perfectly equivalent.
They seem to be interchangeable, but I am nervous that there is something subtle going on that I may be missing.
Yes, they're equivalent. You need braces when the expression is more than a simple scalar variable, e.g.,
push #{ $foo{$bar} } => "baz";
For more detail, see the Using References section of the documentation on references. The standard Perl documentation also includes several tutorials on using references:
Understand References Today (mentioned by hobbs in the question's comments)
Manipulating Arrays of Arrays in Perl
Perl Data Structures Cookbook
I've always found it helpful to remember that the outer braces are not syntactical magic, they're just a block that returns a reference. The expression inside the block can be anything that returns a reference:
$ perl -le 'sub foo {[qw/ apple orange banana /]} print ${print "Do something here."; foo()} [1]'
Do something here.
orange