Perl gives the programmer a lot of rope to work with. Whether one ties that rope into a drawbridge or a noose is the programmer's choice.
Also, CPAN is fantastic and widely supported. I really wish more languages would follow its example, especially when it comes to package namespaces.
In Python I can expect the standard library to be consistent and be maintained as part of the core language. Now I don't mean that everything has to be in the standard library (I'm fine with the database access libraries being third-party for example), but in Perl even the most basic stuff like exceptions is only on CPAN and there are again multiple packages to choose from..
Which means that perhaps for many of them there is a better module out in the ecosystem that almost nobody uses because they have one extra step to install them.
If you want something close to that in Perl 6, just install Inline::Python and you can use all of those “batteries included” with Python as if they were modules written in Perl 6.
Exceptions in Perl 6 are much easier to deal with than they are in Perl 5.
Mostly an urban myth. Where it isn't, at least 8 of those ways are actually important.
Exercise: write a python program that prints Python's quoting documentation, without external files, without editing the documentation. Spoiler alert: it's impossible.
how would it not
String literals are described by the following lexical definitions:
stringliteral: shortstring | longstring
shortstring: "'" shortstringitem* "'" | '"' shortstringitem* '"'
longstring: "'''" longstringitem* "'''" | '"""' longstringitem* '"""'
shortstringitem: shortstringchar | escapeseq
longstringitem: longstringchar | escapeseq
shortstringchar: <any ASCII character except "\" or newline or the quote>
longstringchar: <any ASCII character except "\">
escapeseq: "\" <any ASCII character>
You can't paste that text into a file and write a Python program around it that outputs the same text. You need to encode the quote characters.More generally, there is no way in (many languages including) Python to treat an arbitrary (yet known) block of data as data.
If you needed to have `」` in there you can fall back to `Q{{{{{{…}}}}}}` or `Q:to<END>;…END`
sub add1 {
my ($arg1, $arg2) = @_;
$arg1 + $arg2;
}
sub add2 {
my $arg1 = shift;
# possibly two screens of dense code here, then
my $arg2 = shift;
$arg1 + $arg2;
}
sub add3 {
$_[0] + $_[1]
}
# There may be some other ways to extract arguments
# that I am not aware of.
# It's possible to combine any of the methods!
And this is just argument access, one of the core language primitives.Because in the second (add2), you might do something interesting with the second (or third) arguments depending on the first. You might have optional arguments. Your arguments might be a list of items you don't know the size of. It allows you to develop what you need out of the extensible core mechanism. Modules can and have built on that.
> # There may be some other ways to extract arguments
There are. Now you can just do
sub add( $arg1, $arg2 ) {
$arg1 + $arg2;
}
My personal favorite is to use Function::Parameters[1] fun add( Num $arg1, Num $arg2 ) {
$arg1 + $arg2;
}
which allows named params, type constraints (runtime), default params, etc. def add1(*_):
_ = list(_)
arg1, arg2 = _
return arg1 + arg2
def add2(*_):
_ = list(_)
arg1 = _.pop(0)
arg2 = _.pop(0)
return arg1 + arg2
def add3(*_):
_ = list(_)
return _[0] + _[1] def add(x, y):
return x + y
whereas the Perl codebase that I work with has every possible combination of these methods.e: Just clarifying that your complaint here is that every sub in Perl 5 just receives a list of its arguments; this isn't a "more than one way to do it" issue.
The old P5 motto TIMTOWTDI was long ago updated to TIMTOWTDIBSCINABTE and P6 adopts the latter. While P6 supports most of the options shown for P5, most folk writing P6 will just write something like:
sub add($x, $y) { $x + $y }It doesn't matter which way you unpack your args unless you are trying to do something fancy (the sub 1% cases). Just pick one.
Hell, it's easy enough to make a script to rewrite multiple shifts into destructured list assignment or vice versa.
How much actual cognitive overhead is there associated with three of four different ways of unpacking args?
Speaking for myself (as a long-time Perl/Python/GoLang/etc programmer), when I jump into a language I don't know, it doesn't take me long to get 'muscle memory' for how such things work.
add3 shows how to access the aliased arguments directly.
# break the aliasing of @_ and make undef into 0.
sub undef_to_zero { @_ = map { $_ // 0 } @_; }
sub math_stuff {
# call with identical @_
&undef_to_zero;
# Do math without undef warnings.
my $sum = 0;
$sum += $_ for @_;
}
# Alter all arguments in calls by repeating them
sub fatten {
$_ = "$_" x 2 for @_;
}
$foo = "abc";
@bar = ( 1, 2, 4 );
foo($foo, @bar);
say $foo; # abcabc
say for @bar # 11
# 22
# 44The first example uses the explicitly named default array @_. This is a common pattern, and easy to read.
The second one omits the "default". Note that whilst it is possible to write some dense code between the $arg1 and $arg2, it won't work as expected if the dense code bit has array access - ie., the default array can change in the code.
The third example uses the typical sigils for accessing individual elements within an array (default or otherwise).
I wish the core language had saner defaults, but over time, I've seen some reasonable uses for the different styles:
1. General subs, the same as you example
2. shift removes the first element of the array and returns it. This can make the code more readable in certain cases:
use Params::Validate 'validate';
sub add2 {
my $self = shift;
my $args = validate (@_, { ... } );
}
3. Slightly less verbose code, for simple one-liners and/or anonymous functions: my $calc_functions = {
'add' => sub { $_[0] + $_[1] },
'subtract' => sub { $_[0] - $_[1] },
...
};
my $func = 'add';
$calc_functions->{$func}->($args);