Stealing from Python

We all know that Python, Perl and Ruby (ok, and PHP, and probably other languages) are always stealing ideas from one another. This is a nice thing to do.

After programming a few with Python there is a couple of details I like. I know not all are possible to implement in Perl. Some of them are, and I would love if they were. I know not all people agree with me (that good, too). Nevertheless, I present here a couple of ideas.

Although I do not like relying only in indentation for blocks, I like the fact that conditionals and loops does not need parenthesis. It makes the code much more legible. I imagine that to make this in Perl it would be crazy. Good enough we don't need them when using it as a modifier.

Another clean idea from Python is the in operator. For me it makes more sense to ask if $var in @array or if $var in %hash than using the ~~ operator (that some claim to have a couple of flaws) or using if grep { $_ eq $var } @array or if exists($hash{$var}). Notice the number of characters needed in each approach, and the number of characters that need modifier keys.

Having in as a reserved word, we might even be able to write things like for $x in @array or for $x in keys(%hash). I agree I am walking in Python direction. But that's not necessarily bad.

Finally, Python has a couple of built-in methods that might make some sense, like max and min (that are parametrized letting you specify how to compute values from the elements in the list). Even sum might make some sense (but would not be a priority). I know these are available on modules, and that blessed() is more urgent.

OK, now, please, do not slap me too hard :)

12 Comments

sum, max and min are useful to have, yes, but we do already have them in List::Util which has been in core since 5.8. Maybe it would be nice if they were fully-built in, but the problem with adding new built-ins (at least alphanumeric ones) is that they can conflict with function names that people are already using in their code. So as a result, there needs to be pragmas to explicitly enable them, a la use feature qw(say state switch). So if we're going to need a pragma to enable them, how is that any easier than use List::Util qw(max min sum)?

blessed seems to make more sense. It seems to be something that genuinely should have been part of Perl 5 from the start. Introducing bless without blessed (or at least a version of ref that makes it easy to differentiate between blessed and unblessed references) seems like an oversight.

in on the other hand seems like it would be just replicating part of what smart match already does. Why introduce a more limited version of a feature that already exists? Should there be a new version of last that only acts on while loops and not foreach etc? It's true that smart match has its detractors, but who's to say in would far any better?

Oh yes, I also meant to add that using something like perl5 and/or Syntax::Collector it's quite easy to create a collection of pragmas and imports such that typing:

use perl5-alberto;

... is equivalent to ...

use feature qw(say state switch);
use strict;
use utf8;
use warnings;
use List::More qw(max min sum);
use Scalar::Util qw(blessed reftype weaken);

Or some other combination of features and modules that you like.

 use Acme::Pythonic; # this semicolon yet needed

sub delete_edges:
my $G = shift
while my ($u, $v) = splice(@_, 0, 2):
if defined $v:
$G->delete_edge($u, $v)
else:
my @e = $G->edges($u)
while ($u, $v) = splice(@e, 0, 2):
$G->delete_edge($u, $v)


    for my $n in 1..100:
while $n != 1:
if $n % 2:
$n = 3*$n + 1
else:
$n /= 2

I really like the idea of 'in' in all actuality I spent a day (not even known it was in another language) looking for 'in' because it makes so much damn sense (linguistically especially).

I like the idea, "in" as an explicit "return true if scalar is found in list" would be nice. One could use List::Util any { }, but that doesn't get across the intent of the code as quickly as "if $var in ('one', 'two', 'three')" does.

Yes, you could use smartmatch, but a few people have already pointed out why smart match may not have been the best idea: https://blogs.perl.org/users/brian_d_foy/2011/07/rethinking-smart-matching.html "in" wouldn't suffer from the magic. One side is a scalar, the other side is a list. Smart match, unless its inputs are sanitized, can do unexpected things. Breaking smart match's features into multiple operators could solve its problems by removing the need to cover those cases in smart match.

On the topic of stealing things from other languages, I'd really, really like to see an "is" operator. "if $var is HASH", "if $var is Class::Something". Doing "if ( blessed $var && $var->isa( 'Class::Something' ) )" or "if ( ref $var eq 'HASH' )" is less clear.

to be clear, Perl already has a `in` when you are talking about a list iterator, its `for my $item (@list) { #do stuff }`, but I really like the `if` form idea. Something like `$something->do() if $item in @list`!

> Why introduce a more limited version of a feature that already exists?

By all accounts, the smartmatch operator is unwieldy and full of dark corner cases. Introducing a small bit of its functionality in a simple and more limited way actually sounds to me like a jolly good idea!

I support 'in'. Checking if something is in a set is a very common operation and it is atomic to my mind. This is the way my mind works and when I need to write a grep or use a library for this it introduces a mismatch between thinking and the code. Smartmatch is overdone and having something more specialized makes sense for me - just like having a 'method' keyword indicating that a sub is a method - it is a step into self-documenting code.

While I generally would like an 'in' comparison operator, the example you've shown compares string equality. What about numbers?

The 'in' iteration syntax seems to be just a shorthand so you can omit the parenthesis, so I don't see the point. Plus, things like

for my $foo in $bar { ...

Does that use a scalar $bar or a hash %bar?

Well, sort does string sorting by default and takes an optional subroutine reference (with the magical variables $a and $b) to allow for a custom sort. How about an "in" operator that does string comparison (ie "eq") by default but can take a subroutine reference--again with the magic variables $a and $b--that tells the operator when two elements are equal (so, you would have "$foo in{$a$b} @bar" as a stand-in for part of smart matching).

@Jack Maney: How is that solution different from grep?

Perl's smartmatch operator *is* its "in" operator (given a scalar-array comparison). To want for a Pythonic "in" is to want for Python's type system in place of Perl's:

>>> 1 in [1]
True
>>> 1 in ["1"]
False
>>> 1 in [True]
True
>>> "1" in [True]
False

Which may be nicer depending on your temperament, and can be achieved in Perl by using smart match in conjunction with wrapper classes to delineate between scalar subtypes.

I think I would also like to be able to do


if keys %hash in @array

meaning if any key in in the hash matches an element of the array..., I currently find that hard to express, or at least hard to remember how to express.

Leave a comment

About Alberto Simões

user-pic I blog about Perl. D'uh!