develooper Front page | perl.perl5.porters | Postings from June 2021

Re: Not an OO RFC, take 2

Thread Previous | Thread Next
From:
Chris Prather
Date:
June 21, 2021 00:01
Subject:
Re: Not an OO RFC, take 2
Message ID:
CAEFJ16_2d9WQVYR6u4d1PgFji1Nj+HD1df-G5n+SJg9HqxbvKA@mail.gmail.com
I'll try to be a bit less prosaic this time and leave the literary
criticism behind. Maybe.

Taking a cue from Nicholas, I've re-organized your email to make my reply
more coherent. You basically ask the same question several different ways
because (I assume) you think there's a communication error on your part ... I'm
pretty sure the communication error is coming from us (or me).

Also you describe yourself as a Perl programmer willing to change jobs
before learning
another language so I'm going to assume (possibly wrongly) you don't
have a lot of
experience with many object systems other than the plethora Perl has built on
it's primitives. If this is true, you're working at a disadvantage.
Perl's simplicity warps
the conversation around the primitives in OO.

On Sun, Jun 20, 2021 at 1:30 PM mah.kitteh via perl5-porters
<perl5-porters@perl.org> wrote:

Let's clear the easiest issue out of the way first:

> I thought about this. I would suggest that things be named as clearly as possible. None of the OOP solutions in perl use clear names:
>
> * bless
> * Moose
> * Util::H2O
> * Zydaco
> * Co/Corinna
> * Object::Pad

The proposal is for this to be named `use feature 'class'`. I can't
think how that could be clarified, but I think we all welcome suggestions.

Now to the real discussion.

> What would it take for us to go from "bless" to Corinna?

The conceptual framework behind bless + packages starts from a fundamentally
different place than Corinna. Corinna starts with objects as primitives, not
hashrefs and packages. You can't get there from here.

>
> It is clear you care. I suppose what I am suggesting is, can we start with addressing the insufficiency of "bless"? It is necessary in what it does, but not sufficient - so in the list of "OOP things we need" how far does "bless" take us? What is missing that "bless" _should_ do; what things in the "OOP things we want list" does bless not address and are not at all appropriate for it to handle? That's what I mean "incremental".
>
> So what do we want:
>
> * more intelligent composition (@ISA) [notable this also requires a 'signatures' component for dispatch/polymorphism]
> * better "introspection"
> * data encapsulation
>
> What else?

While Perl's primitives can emulate a multitude of different systems ...
they're all going to have the same fundamental flaws because they can only be
assembled the same ways. Much the way a cake is more than butter, eggs, sugar,
and flour; an object is a discrete synergy beyond the sum of its parts. Perl
is a stewpot of many different flavors, but it simply cannot bake.

If you prefer an architectural metaphor: we're asking for prairie style housing,
and you're saying how do we build that out of slabs of concrete?

> Maybe a good MVP would be, for example, the introduction of the keyword "class" that is has a well defined behavior defined in terms of "bless", "package", and "parent". "class" would be constrained by the current vision of Corinna, as well.  I am not so naive as to suggest "let's implement class then see where we're at". I am suggesting, "is there a way to implement 'class' that is a natural progression from package/bless/parent and a singular step forward?" Furthermore, does it allow us a path forward to the other "general" goals? Or something that would represent a huge improvement and opening up of options - all from a single "class" keyword.

> What can be done to get the best of both worlds?

I'm pretty convinced you cannot have both, because the existing tooling in Perl
is not fit for purpose. Perl has no concept of Records[1], or user-defined data
structures. Perl has five (or seventeen if you read perlapi) kinds of data
structure that can be blessed into an object. Those are the only kinds you can
have.

In my opinion the next natural step from Perl's current object model is to
make Objects a primitive in the language, and Classes as a new type of block to
describe them. The `class` keyword simply cannot be a new kind of `bless`
because it has no relationship to the old kind of `bless`. It's more like a new
kind of `package`, which makes some sense and is probably the logic Larry (or
whomever) used when they decided packages could stand in for classes when Perl
5.000 was being designed.

But `class` also defines a Record, something `package` doesn't do. Nothing in
Perl really does; which is fair a lot of dynamic languages don't bother because
Most, like Perl, have hashes as primitive data structures.

You could argue that the concept of a Record is not Perlish. That might be a
correct argument. I'm not sure either of us gets to be the final arbiter of
that argument.

> I think focusing on proving a more sufficiently power "bless" using the keyword "class" would allow sever things; but most importantly focused discussion around defining what the "means" as a standalone capability. And once this is well defined (again, in terms of bless, etc); then I think you'll find a lot of support.

You're welcome to think that, but it's a fundamentally different discussion
than the one Corinna is having. The problem isn't that `bless` isn't powerful
enough, the problem is that Perl lacks the right primitives.

That's the starting point in the discussion of Corinna. That's the irreducible
piece that if you throw out everything else we still would need to discuss.
Even if you strip away everything else from Corinna you still need something
like (with apologies to John Harper[2]):
```
package LasersAndFeelings;

use strict;
use warnings;
use experimental 'class';
use experiemntal 'signatures';

use Games::Dice 'roll';

class Character {

    has $style;
    has $role;
    has $number;

    sub new($class, $s, $r) {
       $style = $s;
       $roll = $r;
       $number = roll '1d4+1';

       return bless(__INSTANCE__, $class);
    }

    sub attempt_move($s, $num_dice=1) {
        my $dice = [roll '1d6' x $num_dice];
        my $count = scalar grep { $_ > $number } $dice->@*;
        for ($count) {
            if ($count == $number) { return 'LASER FEELIGNS' } # !!!
            if (0) { return 'FAIL' }  # critical fail
            if (1) { return 'PARTIAL'} # complication
            if (2) { return 'SUCCESS' } # everything's fine
            if (3) { return 'BOON' } # critical success!
        }
    }
}

```
The bare minimum is a new kind of scope, a new kind of state, and a new kind of
reference to hold it.

(You might be asking about the `__INSTANCE__` that I've suddenly thrown in, no
it is not part of the Corinna proposal. Perl only has one kind of native object
construction protocol, `bless`, that takes a reference and a package name. Since
this is a new kind of reference I need some mechanism to access it, this
seemed the most straight forward.)

This is much more stripped down than the Corinna proposal because Curtis was
worried he needed to have feature parity with Moo/se otherwise people wouldn't
adopt the new system. In this discussion we don't seem to care about adoption
just the primitives that we can iterate on later, so I threw out everything but
what I saw as the bare minimum for classes and object primitives.

This is a good starting place though. Actually, no. The biggest lesson from
Moo/se was: There will always have a metaobject protocol, some places are lucky
that the protocol is formally defined and well documented. Whatever we build
needs to acknowledge this.

> As I said, my fear is not this "death" of Perl but the undeath. Moose/moo already created this weird schism with its DSL and runtime MOP framework. It also begat some weird ways to handle composition that seemed orthogonal to not only Perl, but Moose/moo itself. In practice it also made testing a nightmare.
>

I kinda need a [citation needed] here, I've been using Moo/se since 2007 in my
own projects and with a large number of other people and I've not found
testing anymore difficult. In some regards it's simpler because there's a
whole class of behavior I know is already tested for me (instantiation,
accessors, etc.).

Finally since there is a lot of yelling about the Elephant in the Room: Perl's
relative market share isn't a problem for perl5-porters. It's not a problem
perl5-porters can or should attempt to solve. A new object system with real
primitives won't give Perl the boost it needs to attract new developers.
Too many people remember 1999 Perl. After two decades of defending it,
I now believe
Perl's existing object system is a shambles and makes writing clean
scalable code
more difficult than it should be. We need to take the lessons we have
learned from Moo/se
and others and improve upon them. That's a problem perl5-porters can solve.

[1]: https://en.wikipedia.org/wiki/Record_(computer_science)
[2]: https://johnharper.itch.io/lasers-feelings

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About