The Future of Perl 5

No, I'm not speculating about where Perl 5 is going, but I was imagining a few minor (hah!) features that would make life much simpler.

In fact, I was imagining a minimalist OO system with optional typing.

The following is a simple LRU cache in Moose:

package Cache::LRU {
    use Moose;
    use Hash::Ordered;
    use MooseX::Types::Common::Numeric qw/PositiveOrZeroInt/;
    use namespace::autoclean;

    has '_cache' => (
        is      => 'ro',
        isa     => 'Hash::Ordered',
        default => sub { Hash::Ordered->new },
    );
    has 'max_size' => (
        is      => 'ro',
        isa     => PositiveOrZeroInt,
        default => 20,
    );

    sub set {
        my ( $self, $key, $value ) = @_;
        if ( $self->_cache->exists($key) ) {
            # delete the key and set it later to ensure it's the
            # most recently used
            $self->_cache->delete($key);
        }
        elsif ( $self->_cache->keys >= $self->max_size ) {
            # key doesn't exists, so make room for it
            $self->_cache->shift;
        }
        $self->_cache->set( $key, $value );
    }

    sub get {
       my ( $self, $key ) = @_;
       $self->_cache->get($key)
    }

    __PACKAGE__->meta->make_immutable;
}

And to use it:

my $cache = Cache::LRU->new( max_size => 100 );
$cache->set($key,$value);
$cache->get($key);

The set($key,$value) method removes the oldest value if the cache size is greater than the max size. Then we delete our key and set it again (puts it at the top of the stack). Setting the max_size to zero disables the cache.

Here's the same code in my imagined future of Perl 5, with a class keyword. It also has method, has, and self (unshown) keywords, but only in the class body. It also has private and public attributes, and optional typing.

class Cache::LRU {
    use Hash::Ordered;
    my       $x        = Hash::Ordered->new; # private
    has UInt $max_size = 20;                 # default

    method set ( $key, $value ) {
        if ( $x->exists($key) ) {
            $x->delete($key);
        }
        elsif ( $x->keys > $max_size ) {
            $x->shift;
        }
        $x->set( $key, $value );
    }
    method get ($key) { $x->get($key) }
}

The devil, of course, exists in the details, but it's so much simpler and easier to read. The bigger the class, the easier it is to read. Whether that could ever be implemented is a different story, particularly having lexically scoped keywords (e.g., keywords that only exist in a scope they'd be useful in).

What would you like to see in the future of Perl 5? And what mistakes did I make in the above?

14 Comments

Using all the stuff Damian showed off at TPC-DC 2017 or by actually adding to the core?

The big thing I've wanted for a while is native iterables / generators. With native iterables, the

while ( defined( my $line = <$fh> ) ) { ... }

becomes simply

for my $line ( <$fh> ) { ... }

(and no performance slowdown while Perl tries to read the entire file into an array).

I tried making this as a tie, but the internals do not allow it to work in all the places that arrays need to work (for performance reasons, mostly). https://github.com/preaction/Tie-Iterator#why-a-core-iterator

Isn't this exactly what cperl/perl11 does?

class MyBase {
  has $a = 1;
}
class MyClass is MyBase :open {
  has $b = 1;
}

my $o = new MyClass;
# ... some possible side-effects with the type of $o
$o->a;      # oelem $o, 'a';
$o->b;      # oelem $o, 'b';

my MyBase $o1 = new MyClass;
$o1->b;     # compile-time error

my MyClass $o2 = new MyClass;
$o2->b;     # $o2->[1]  - $o2 is known to be MyClass

$o = new MyClass;   # and directly afterwards:
$o->a;      # $o2->[0]  - $o is known to be MyClass

http://perl11.org/cperl/perlclass.html

What would you like to see in the future of Perl 5?

I would go for proper exception handling. Both providing try/catch/throw (or similar) keywords, and getting the core to generate object exceptions for errors instead of strings.

I'd love it if sub signatures finally became non-experimental.

I'd give Salvador Fandiño's suggestion for exception handling in the core a slightly higher priority than an object system.

The benefit of an object system in the core would be a significantly reduced threshold for beginners to do OO Perl, and to do it right. If I consider all the stuff I'm using today in Moose, and how to fit that into the picture, then the difference in readability is shrinking. There's the ro trait which is missing in your future code, but also handles, which you could use to delegate the get method to the cache, and lazy, and so much more. I guess that some key/value list of traits shouldn't be avoided.

... And what mistakes did I make in the above?

I wonder why you're asking? Well, Setting the maxsize to zero disables the cache. isn't true. There's always one object in the cache after the first set operation. And you can't disable an existing cache because maxsize is readonly. Also, LRU in your case means "Least recently updated" which might not be a very efficient policy.

  • I'd like to be able to do
    my %foo{@keys} = @vals;
    
    instead of
    my %foo;
    @foo{@keys} = @vals;
    
  • I'd love for function signatures to handle types.

I see your example sounds like Rakudo.

IIRC, Moose is what we bring OO system from Rakudo to Perl 5.

Isn't it what Moxie should once become?

@Diab

  1. +1
  2. Method::Signatures isn't it what?

+1 to OO classes and optional type checking in core. It would save time, effort and errors, and give more standardised, readable code (while still letting you TIMTOWTDI)

I gave it much thought before, mostly when I wondered why did so much effort was given to something like "postfix dereferencing" that is nothing more than syntactic sugar (or, to my taste, syntactic salt) rather than a proper object system, Class::MOP or otherwise. Since I am not a C programmer, and am not familiar with perl internals, I can only base my opinion on other people's efforts. And judging by that, it seems there is no way of actually accomplishing this with the current resources and incentives.

In other words, since the perl5porters is a small, focused team of volunteers and (from what I understand) the perl internals are too much of a mess to be able to allow for such a large project to be undertaken, and especially considering that a lot (most? all?) of Perl 5 in production isn't going to use it anytime soon, I don't think we'll (ever) see such a system being implemented in core perl.

Hi Ovid, your LRU example is indeed lovely syntax, I'd certainly use it - and I'm not a Moose user, I like the original bless-based Perl 5 object system. For my own amusement, I wrote a bless-based version. It's shorter than your original Moose version, although of course I had to write a new function which Moose does for you.

But is anyone likely to implement "class" syntax in Perl 5 anytime soon? If not, it's just a pipe dream, isn't it?

Finally, I note that the "method" syntax is already available in Perl 5 via either Method::Signatures or (my preference) Function::Parameters as it acknowledges that functions (subroutines) outside objects are important too. But just as subroutine signatures are finally available in Perl 5.26, method signatures would be good too. Subroutine signatures, btw, are the big thing I've wanted in Perl 5 for 10 years, so I'm already very happy:-)

Leave a comment

About Ovid

user-pic Freelance Perl/Testing/Agile consultant and trainer. See http://www.allaroundtheworld.fr/ for our services. If you have a problem with Perl, we will solve it for you. And don't forget to buy my book! http://www.amazon.com/Beginning-Perl-Curtis-Poe/dp/1118013840/