develooper Front page | perl.perl5.porters | Postings from November 2016

Re: RFC: core sub signature introspection

Thread Previous | Thread Next
Sam Kington
November 25, 2016 05:13
Re: RFC: core sub signature introspection
Message ID:
On 24 Nov 2016, at 22:58, Zefram <> wrote:
> Sam Kington wrote:
>> Surely this is backwards? If anything, the fact that a sub's parameters
>> can be introspected makes it *easier* to change them, because you can
>> expect (some of) the code calling that sub to introspect the required
>> parameters and adjust its own behaviour accordingly, rather than
>> hard-coding which parameters it supplied?
> You're imagining a rather bizarre situation here.  You're supposing a
> change being made to the sub's calling interface that we would normally
> regard as an incompatible API change.  We do not generally expect calls
> to a sub to change between versions of the sub.  If you do expect them
> to change, based on metadata supplied with the sub, that would amount to
> a very strange API.

Oh, I totally agree that it would be really strange to have a sub that behaved this way, changing its behaviour depending on which version of the module you were using. I can’t think of a reason why you would ever write code like this in a production environment or a public CPAN module.

But bear in mind Aaron Crane’s example which started this sub-thread off:

[Aaron Crane:]
> [Zefram:]

>> It seems to me that this metadata isn't at all useful to other code
>> at runtime.
> Here's a sketch of one such use case:
> sub iterate ($array, $code) {
>    my $arity = cv_min_arity($code) or die;
>    my @values = @$array;
>    push @values, undef while @values % $arity;
>    $code->(splice @values, 0, $arity) while @all;
>    return;
> }
> iterate(\@array, sub ($x, $y, $z) { ... });

Now, the iterate sub here is merely saying “if you pass me a coderef, it must have a subroutine signature so I know what to pass to it”. I think that’s not unreasonable, in a world where subroutine signatures are introspectable, and it potentially opens up a whole new category of API design structures.

And you could plausibly write a CPAN module which had a function like iterate that took an arrayref and a coderef, and if the coderef had a subroutine signature it would introspect it and provide to it the number of arguments it wanted, but otherwise it would just pass one argument. So if you were expecting disparate elements, you might not bother with a signature and would let the default case happen; but if you were expecting key/value pairs, or 3-or-more element tuples, say, you might pass it a coderef with a signature like ($latitude, $longitude, $elevation) so e.g. iterate() took raw numbers spat out of a data stream and provided them to you in convenient named groups of 3.

Your response to that example was:
> arc's usage implies that the arity metadata would
> be part of the sub's API, and that change or withdrawal of the advertised
> arity would be an incompatible change that should not be made in a module
> update.  If use of the information is acceptable and the arity comes only
> from the signature, as arc proposed, then the use of a signature and the
> (minimum?) arity of the signature become such unchangeable parts of the
> API, with the adverse consequences that Abigail and I have described.

I must confess that when I initially replied to that part I probably misunderstood your point, and certainly misremembered Aaron’s example. I’m still not entirely sure what your objection is - almost entirely my reading comprehension failure. But this particular part of your most recent reply is clearer to me:

> Your "some of" exposes a problem.  If the calling interface does vary
> in this way, it would require *all* call sites to pay attention to the
> metadata that says which parameter goes where.  No hard-coded call would
> be safe.

I agree that if module version 1’s subroutine foo expects two parameters, and module version 2’s foo expects three parameters, then any code that calls module->foo(...) is in a spot of bother if it can’t introspect the parameters that the installed version of foo takes.

But what’s the alternative? Assuming that the calling code does indeed depend on said module being around, and that module has indeed changed its public API so dramatically, and the calling code can’t mandate a known-good version, it has to maintain its own lookup table of “version 1 expects two parameters, version 2 expects three parameters” etc., and probably refuse to work if it finds an installed version it doesn’t recognise.

In short, I don’t understand how a feature that lets code programatically determine the requirements of other bits of code, would lead to *less* flexibility, and more rigidity.

> To have such a bizarre API wouldn't really be actively harmful, it would
> just be an awful hassle to use.  But that is not the situation that we
> were discussing.

Then I do apologise for side-tracking the discussion. I must confess that I do not understand your objection to making subroutine signatures introspectable. Like you, I doubt this would ever be seriously used in production. But in IDEs, test frameworks and the likes, though, I can totally see a point.

And: isn’t the feature keyword precisely for things like this - experiments?


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About