Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PPC 0022 Metaprogramming API #25

Merged
merged 11 commits into from
Dec 7, 2023
Merged

PPC 0022 Metaprogramming API #25

merged 11 commits into from
Dec 7, 2023

Conversation

leonerd
Copy link
Contributor

@leonerd leonerd commented Sep 21, 2022

No description provided.

@trapd00r
Copy link

I love this. Excellent!

#### `has_package`

```perl
$bool = meta::has_package($name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding my here and further on in the code examples would be better.

Copy link

@wolfsage wolfsage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will have to think more about it later but seems good

rfcs/rfc-metaprogramming.md Outdated Show resolved Hide resolved
rfcs/rfc-metaprogramming.md Outdated Show resolved Hide resolved
$metapackage->remove_symbol($name);
```

Removes a symbol. Nothing is returned.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the symbol doesn't exist?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should return a boolean on success and the developer can choose to ignore it. Otherwise, we'd wind up with a lot of code like:

if ( $metapackage->has_symbol($name) ) {
    $metapackage->remove_symbol($name);
}

rfcs/rfc-metaprogramming.md Outdated Show resolved Hide resolved
Copy link

@Ovid Ovid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a great start! I have a few comments.

$metapackage->remove_symbol($name);
```

Removes a symbol. Nothing is returned.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should return a boolean on success and the developer can choose to ignore it. Otherwise, we'd wind up with a lot of code like:

if ( $metapackage->has_symbol($name) ) {
    $metapackage->remove_symbol($name);
}

$metasymbol = $metapackage->get_symbol($name);
```

Returns a meta-symbol object instance to represent the symbol within the package, if such a symbol exists. If not an exception is thrown.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have it just return nothing?

if ( my $metasymbol = $metapackage->get_symbol($name) ) {
    ...
}

Otherwise, we'd be littering our code with a bunch of evals or try/catch or has_symbol checks when it's not necessary, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I thought about that - I guess there's situations you want it either way around. Sometimes you want to optionally work on a symbol if it's there; other times you definitely expect it to be there and want an error if it isn't.

If it just silently returns undef then code like this would fail:

$metapackage->get_symbol('&func')->set_prototype('($$$)');

Or rather, it would fail with the rather nonobvious "Can't call method "set_prototype on an undefined value" rather than some slightly more meaningful message about whatever package name it was not containing a '&func' symbol.

Since we don't want ((I think?)) two sets of methods having "get or throw" vs "get if exists otherwise return undef" semantics, we should decide which one we want here. As you point out it's always possible to make an optional one out of a throwy one; it's also possible to make vice-versa. If the method just returned undef if the symbol doesn't exist, one could always:

($metapackage->get_symbol('&func') or die "Package does not have a &func symbol")
   ->set_prototype('($$$)');

Though it does involve a bit of repeating the name. Plus it feels very 1980s "return undef and set errno" technology. We have exceptions now - should we not use them?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see providing both a throwing and a non-throwing method, whether a missing symbol is exceptional depends on the caller's circumstances.

I suggest different methods here rather than a flag both in having a method that "does one thing", and for better tool support, I know Coverity for example is confused by sv_utf8_downgrade() which takes a flag to decide whether to throw and complains that only some callers check the return value.

In this case the caller always saves the return value, but for a throwing method wouldn't need to check its truthiness.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could see an analogous find_symbol('&func') which would return undef, but I agree that having that and get_symbol side-by-side might be confusing (or clunky). If we go with exceptions, I won't cry :)

```

Creates a new named symbol. If a value is passed it must be a reference to an item of the compatible type. This is required for adding subroutines (with the "&" sigil), but optional for the others which add variables. If no initialisation is provided for variables, an empty variable is created.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I think an exception is warranted if the symbol already exists.

Also, you wrote:

If a value is passed it must be a reference to an item of the compatible type. This is required for adding subroutines (with the "&" sigil)

If we skip the $value, then $metapackage->add_symbol('&foo'); could be used to create forward declarations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooh true, I had forgotten about forward declarations. I'll fix that up.

rfcs/rfc-metaprogramming.md Outdated Show resolved Hide resolved

(Inspired by `Sub::Util::set_subname`)

#### `prototype`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anything for signatures?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signatures are internal details of a sub, and should be equivalent to doing argument unpacking manually. Being able to read the signature breaks that equivalency, so I don't think it is a good idea.

The signature of a multi sub/method is something that would be public, since it participates in method resolution. If multi subs were added, then it would be appropriate to add a mechanism for reading the signature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I deliberately avoided signatures for now. Given all the other ideas we have in a bunch of places that's definitely a discussion I would like to open, but I don't think here and now is the place for it.

Comment on lines 363 to 367
* B::Hooks::EndOfScope

* B::CompilerPhase::Hook

It may be useful to add support for these kinds of abilities somewhere in core perl, but this metaprogramming RFC does not seem to be the place for them.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a fair point, but what about phases?

foreach my $phaser ( $metapackage->phasers('BEGIN') ) {
    ...
}

I'm not sure how useful this would be at the current time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phasers don't really belong to a package; they're not named methods within it. They belong to a scope of compilation. In the specific case of BEGIN phasers, they are executed as soon as they're parsed and not stored anywhere. Other phasers are stored in special places outside of the regular package-based symbol table.

Comment on lines 371 to 372
* Currently it is unspecified what the "add"-type functions will do if an existing item is already found under the proposed new name. Do they warn before replacing? Is it an error and the user must delete the old one first? Should we provide a "replace"-type function, for which it is an error for the original *not* to exist? Or maybe the semantic should be "add-or-replace" silently.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we would really want to throw an exception because we ignore warnings too often (imagine this in production code on a large system). Die early so the programmer knows to do defensive programming when they change the behavior of existing code, as opposed to adding code. If they really need to change the behavior, have separate methods?

$metapackage->replace_symbol('&foobar', sub {...});

I'm not entirely convinced by this. Just my first thoughts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah; it might be useful that add throws on attempts to clobber; then a replace that doesn't. But then presumably it's an error for that method to not find a thing to replace. So then do we need a ->add_or_replace_symbol as well which is happy with either preëxisting condition? We now have three possible cases for every add-like method.

It's no huge trouble to implement them all (as I expect they'd all be the same body implementation aliased three ways, using the ix to determine whether to throw if the name already does or does not exist); it just adds extra complication to the docs and things for users to understand.

Worth it? I'm not sure.

rfcs/rfc-metaprogramming.md Outdated Show resolved Hide resolved
#### `list_packages`

```perl
@metapackages = meta::list_packages($basename);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely this should permit the argument to be an object from above, or even:

@metapackages = meta::list_packages(meta::get_package($name))

@metapackages = meta::list_packages($basename);
```

Returns a list of sub-packages within the given base package name, each as a meta-package object instance.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are none, would this return an empty list, or throw an exception? The action should be consistent with behaviour of get_symbol (whether undef or an excpetion) as raised by Ovid there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm inclined to differ. When you ask to "get a thing" you really expect to receive that thing, or die trying. Whereas, when you ask to list the possible things, it's quite valid to expect you might end up with nothing. List-returning methods can yield an empty list, whereas conceptually a scalar-returning method must return exactly one thing.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lack of sub-packages isn't exceptional, consider if you were recursively walking a package tree.

Requesting a specific symbol that doesn't exist might be though.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a useful pattern though, and even with use feature "try", it's neater when get_variable returns undef instead of throwing an exception.

my $variable = get_variable('$foo') // add_variable('$foo');

@leonerd leonerd changed the title RFC (TODO) Metaprogramming API RFC 0022 Metaprogramming API Oct 15, 2022
@leonerd leonerd marked this pull request as ready for review October 15, 2022 17:19
Copy link
Contributor

In its current state, I have to vote no.

There are many ways in which this does not match with perl's own understanding of its internals. has_package is nonsensical in any real sense. Nothing in this proposal mentions GLOBs, which do exist, for better or worse. Why is get_variable different from get_subroutine? What about file handles? Nobody likes them, but they exist and don't have a sigil.

I would love a world where bareword filehandles didn't exist, and where packages could be said to "exist". But making an API that doesn't understand perl as it actually exists does not seem like the way to do that.

@leonerd
Copy link
Contributor Author

leonerd commented Oct 16, 2022

There are many ways in which this does not match with perl's own understanding of its internals. has_package is nonsensical in any real sense.

Fair. That could either be solved by documentation ("This method is likely to return true in many cases you might not expect, so be careful"), or we could just skip it altogether and say that any package potentially does exist, and ->get_package autovivifies one if it previously didn't.

Nothing in this proposal mentions GLOBs, which do exist, for better or worse.

I did think about that. It could be possible to add a ->get_glob which returns a holder on a GV, and then the various ->get_symbol-type methods are just wrappers for fetching the appropriate slot out of a GV. Effectively something like the following:

method meta::package::get_symbol($name) {
  if($name =~ m/^\$(.*)/) { return $self->get_glob($1)->get_scalar_slot }
  elsif ...
}

I didn't want to complicate the user-visible API too much and have end-users have to think about globs, but maybe that should be exposed anyway but users encouraged to use the convenient wrapper ones...

Why is get_variable different from get_subroutine

A fair question. It probably doesn't have to be - perhaps they can both just be ->get_thing I just didn't have a good noun for what "thing" is. ;) They're not "symbol" because they could work on lexical variables, anon subs, all sorts of non-symbolic things.

What about file handles? Nobody likes them, but they exist and don't have a sigil.

Oooh fair. That further suggests that maybe the glob-shaped API as an intermediate step is the way forward.

I would love a world where bareword filehandles didn't exist, and where packages could be said to "exist". But making an API that doesn't understand perl as it actually exists does not seem like the way to do that.

Alright - I'm happy to make changes. As I said originally I didn't put a huge amount of thought into the first draft, so this sort of feedback is useful. Let me know what you think of the-above ideas and I'll have a bit of a rewrite.

@EvanCarroll
Copy link

EvanCarroll commented Jan 30, 2023

It seems as if there is pushback against the package existence test. There are two other packages that play in this sphere,

  • Package::Stash
  • Class::MOP::Package

Moreover, there are some other things mentioned that are needed imho, like Sub::Util's

As a point of endorsement for this RFC, if Package::Stash, Class::MOP::Package and Sub::Util can be rewritten as shims on meta:: it has my endorsement.

Are there any remaining questions or concerns to be resolved if the part of this proposal pertaining to package existence is dropped?


I'd also like to get the signature through something provided in meta::. That conversation can be shelved for now, but this came up for me immediately and it stings not having an answer there. https://stackoverflow.com/q/63836449/124486

@leonerd
Copy link
Contributor Author

leonerd commented Aug 15, 2023

I've adjusted several bits of wording, and added further thoughts about globs, etc.

I'd like to try to get a consensus on at least some of this, so I can begin actually writing code to try it out. A missing meta API is starting to get in the way of writing more interesting bits of behaviour around the new class feature, so I'd like to get something started somehow fairly soon; even if it's just sitting around as an external CPAN module initially.


*Note:* It is currently unspecified what happens if the reference refers to a lexical or anonymous variable, rather than a package one. This PPC does not specify any useful behaviour for such instances, but it's possible that future abilities may be added that become useful on lexical variables or anonymous containers.

#### `get_subroutine`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not obvious how this differs from get_variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah a fair question. I think originally I imagined it would want to be different because it returns a different class of meta- object to wrap the thing it refers to. But perhaps the same would be done for scalar/array/hash anyway, because maybe those metas have ways to operate on the structure of the underlying thing. Undecided.

But yes you're right, it doesn't have to be separate at all. Maybe best that it isn't - perhaps a single

$metavar = meta::for_reference( \$scalar | \@array | \%hash | \&code );

would suffice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

made another attempt in 409275e


Returns the meta-symbol representing the scalar slot of the glob. If the slot has not been allocated, returns `undef` or throws an exception.

Similar methods would exist for the other slot types; `array`, `hash`, `code` at least.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to normalize the entire API to use either code or subroutine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also worth noting globs also have IO and FORMAT slots.

Globs also have FILEHANDLE, NAME, PACKAGE, and GLOB, but those aren't really slots and are handled by other parts of this API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to normalize the entire API to use either code or subroutine.

Ahyes defiintely. I wrote the "code" ones quite late, when I was thinking about the GvCV macro; whereas "subroutine" comes from the original doc last year. I don't have any strong thoughts on one vs. the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also worth noting globs also have IO and FORMAT slots.

Globs also have FILEHANDLE, NAME, PACKAGE, and GLOB, but those aren't really slots and are handled by other parts of this API.

Yeah I couldn't easily think of some ways to interact with those, but yes it'd be good to have them represented too. I imagine they would fit by similar means - more methods named in "the obvious" way.

As I said to Evan:

Once there's a bunch of "plain boring objects" with "plain boring methods" on them, it's quite easy to imagine what new methods can be added for those things.


Similar behaviour to on meta-symbols.

#### `can_scalar`, `get_scalar`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having a single method that return an object or undef would be fine.

If we wanted a predicate method, has_* would be better than can_*.

Copy link
Contributor Author

@leonerd leonerd Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation for can came from $obj->can( 'method' ) either returning a coderef or undef.

I also felt that having a "get" form that throws an exception rather than returning undef makes for cleaner-looking code if you're not expecting to find things missing.

$pkg->get_package( "subpackage" )->get_symbol( '&funcname' )->get_whatever ...

If any of those are missing you get more obvious errors of the form "Package Thing does not contain a 'subpackage' package" rather than "Can't call method "get_package" on an undefined value at ...". Otherwise, you end up writing long chains like this with lots of manual error-checking:

(($pkg->get_package('subpackage') or die "Has no subpackage")
    ->get_symbol('&func') or die "Has no func"))
    ->...

It's far from a concern specifically about this meta stuff specifically, and more a more general consideration of what feels best for any kind of API with "get me a thing that might not exist" query functions in it, basically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can is named as such because it checks for methods. Methods are actions, so you check if something can do them. It's the wrong verb for this API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see - yes from that angle can is probably the wrong word here. I'm loathe to suggest has though, simply because I'd imagine a has would just return a true/false boolean. Whereas we're looking at

$metathing_or_undef = $metapkg->has_symbol( 'NAME' );
$metathing_or_die   = $metapkg->get_symbol( 'NAME' );

currently. I don't have any other good verb suggestions; unless we go for something more wordy. The following would make it very clear what the behaviour is (and also solve similar questions for add/remove) but seems probably overly verbose in the common case.

$metathing = $metapkg->add_if_missing( 'NAME' ); # throws if already present
$metathing = $metapkg->add_or_return( 'NAME' ); # silently returns it if already present

$metathing = $metapkg->get_or_undef( 'NAME' ); # returns undef if missing
$metathing = $metapkg->get_or_fail( 'NAME' ); # dies if missing

$metapkg->remove_or_fail( 'NAME' ); # dies if missing
$metapkg->remove_if_present( 'NAME' ); # silently ignores if missing

These names mostly suck. I was inspired by SQL's INSERT OR UPDATE ... but that fits the more wordy SQL.

As you can tell this part is still very much a WIP here ;)

#### `add_scalar`

```perl
$metasymbol = $metaglob->add_scalar;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this signature, it isn't possible to do the same thing as current exporters do. The slot is created and you can get a reference to it, but you can't inject an existing reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this signature, it isn't possible to do the same thing as current exporters do. The slot is created and you can get a reference to it, but you can't inject an existing reference.

Oops, yes that probably wants to take the same optional reference to an existing thing, that the $metapackage->add_symbol has. I'll pop that in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed by b9f17b9

$bool = $metasymbol->is_subroutine;
```

Returns true in each of the four cases where the object represents the given type of symbol, or false in the other three cases.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, what about is_filehandle?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, what about is_filehandle?

Well currently the API doesn't have the shape to permit access to filehandles. But that's an easy extension that could be added later.

The point isn't to guarantee 100% coverage from the start; just to act as a enough of an initial shape to hang more onto later when we need it. Once there's a bunch of "plain boring objects" with "plain boring methods" on them, it's quite easy to imagine what new methods can be added for those things.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it can't be handled by the shape of this API, then the API seems wrong. And the shape seems to be the most important part to get right to begin with.

If symbols are only accessible via name with a sigil, then file handles won't ever be accessible. That probably indicates that the type needs to be able to be specified separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If symbols are only accessible via name with a sigil, then file handles won't ever be accessible. That probably indicates that the type needs to be able to be specified separately.

I thnik this probably also indicates that support for globrefs is necessary here; we can't just skim over it. The "ignore the GV and find me the variable slot" convenience methods might still be useful for common tasks but they can just be emulated in the .pm file if required (as the doc explains); they're just shortcuts around going via the GV.

So I think I'll reword it again to remove the bits about GVs being optional, and integrate that as part of the real API shape.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rewritten with globs as an inherent first-class concept (and hinting that the direct access to variables is a shortcut via those) in 422c342


Returns a meta-symbol object instance to represent the symbol within the package, if such a symbol exists. If not either `undef` is returned or an exception is thrown.

The exact type of symbol that is returned depends on the first character of the `$name` parameter - i.e. the sigil. Sigils of `*`, `$`, `@`, `%` and `%` respectively will return a meta-symbol representing a glob itself, or the scalar, array, hash or code slots from it.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"% and %"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops; a typo. Fixed in f6bce36

$metavar = meta::for_reference($ref);
```

Given a reference to a package variable or subroutine, returns a meta-object instance to represent it. If `$varref` is not a SCALAR, ARRAY, HASH or CODE reference, an exception is thrown.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You allow get_symbol to return a GLOB, but don't allow a globref to be passed in here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahyes; might as well allow GLOBrefs too. Fixed in 387d25b

$name = $metasymbol->name;
```

Returns the fully-qualified name for this symbol, including its sigil and package name. This would be equivalent to
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you get all the names, here and above?

I could see that as being relatively expensive, but that's true for for_reference() too for SCALAR, ARRAY and HASH references

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not too bad. You just walk the ->parent chain collecting up the names. I'm fairly sure core perl does that in places. Plus it doesn't matter if it's a bit expensive; you only need to do it in the accessor itself if actually requested. I could imagine most use-cases wouldn't need it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, I don't see a simple way to get from:

my $ref = \$My::Deep::Package::x; # 
my $metasymbol = meta::for_reference($ref);

to the position in the symbol table.

The scalar / array / hash doesn't include any name information that could be used to find the stash, so there's nothing to follow parent links on.

Perhaps objects from for_reference() don't support returning the name, which might be where I was confused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused, I don't see a simple way to get from:
...

Oh, hrm. I thought perhaps that package variables all reference their GV, but maybe they don't? Perhaps it's only CVs that allow an easy backward path back to the name + package.

If not, then I guess unless we add that then indeed doing a for_reference would have to just give you a meta-symbol around an "anonymous" variable. It might well have a name but we don't happen to know it.

Copy link
Contributor

We're likely to accept this PPC, although with a provision that the exact API is not settled yet. Since this will basically be a normal XS module, we can start by shipping some dev releases to CPAN to work towards a final API.

But in regards to CPAN, there is a complication. Permissions on CPAN are case insensitive, and the Meta module is already "taken". VELTZER has co-maint on the namespace, but does not have a Meta module. Instead, they have a dist named Meta that includes various modules under the Meta:: namespace. At the time of release, in 2002, they would not have been given permissions to the Meta namespace. But later, rules were introduced to require dist names match a package you have permission to. Older dists that hadn't followed this had their authors granted extra permissions to match their dist names.

I think it would be reasonable for us to take over this namespace. The author never actually used it, and is unlikely to ever do another release of their dist. And if they did want to do so, they could just rename the dist to match one of their modules. They don't need actual Meta namespace for anything.

This is something that should be discussed with PAUSE admins. Possibly @neilb can weigh in, as I know he was heavily involved in the dist name permissions resolution.

@leonerd
Copy link
Contributor Author

leonerd commented Sep 20, 2023

While awaiting PAUSE permissions for actual indexing, I went ahead and created the release tarballs anyway and uploaded them...

Initial placeholder version, unindexed due to permissions errors
https://metacpan.org/release/PEVANS/meta-0.001

Also devel version that actually has code:
https://metacpan.org/release/PEVANS/meta-0.001_001

@leonerd
Copy link
Contributor Author

leonerd commented Sep 21, 2023

PAUSE permissions have now been granted and reïndexed, so now this appears

https://metacpan.org/pod/meta

@leonerd
Copy link
Contributor Author

leonerd commented Sep 21, 2023

It seems like this document is close enough for initial experimental work, but there are still many unresolved comments and issues around it.

We've now enabled Issues on the PPCs repository.

Overall the process should be split more between comments on the PR vs Issues, in that the PR is about adding a proposed perl change. Just because a document is committed in the repository does not mean that the underlying idea it describes has been accepted as an idea. Comments on the PR should be reserved for surface-level issues to do with document formatting, spelling, clarity of language, etc... Wider thoughts about the validity of the idea itself can now be discussed by opening an issue, to discuss a PPC document.

Therefore, I think we should merge this document as it stands - its status is still marked "Exploratory". If people have comments about the actual ideas presented here, it would be best to open individual Issues (make sure to begin the issue title with "PPC 0022") so they can be looked at and tracked invididually.

@leonerd leonerd changed the title RFC 0022 Metaprogramming API PPC 0022 Metaprogramming API Dec 7, 2023
@book book merged commit 3b5d04b into main Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.