This is PerlMonks "Mobile"

Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

szabgab has asked for the wisdom of the Perl Monks concerning the following question:

Given a function using signatures like this:
use strict; use warnings; use 5.020; use feature 'signatures'; no warnings 'experimental::signatures'; sub hello($name, $age) { print "$name\n"; }
I am looking for a way to list the variables it is expecting during run time. Using the solution from this post using
B::Deparse->new->coderef2text(\&hello);
I managed to write some code that works for me that I can turn into a CPAN module, but I wonder if there is already one that does that and I missed it?

Replies are listed 'Best First'.
Re: Introspecting function signatures
by LanX (Saint) on Mar 05, 2021 at 15:53 UTC
    Hi Gabor

    The monastery's authority for such questions is dave_the_m and IIRC we already briefly talked about introspection here.

    Regarding a (robust) API:

    IIRC this is depending on the version of Perl, early versions compiled code into the function block to expand @_, later versions had dedicated OP-Codes for that. ( I could dig up that info from emails, if Dave doesn't show up)

    so this could either boil down to inspecting the OP-Tree with B::Concise or calling a method from B (on a B::CV node most likely)

    In any case, B::Deparse is written in Perl, so you can always look into it and diff different versions to locate how the info is extracted.

    Whatever the result it would be nice if such an API was added to Sub::Util when it's not experimental anymore.

    HTH :)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    PS: This message will self-implode ASA Dave shows up ;-)

Re: Introspecting function signatures
by dave_the_m (Monsignor) on Mar 05, 2021 at 20:31 UTC
    The general feeling was that the signature is an internal implementation detail of the subroutine, and that things outside of a subroutine shouldn't be relying on the ability to inspect it. For example, a sub that's part of a documented API in a CPAN module might, in a new release, switch back from using a signature to "manually" processing @_, because it turns out to be more convenient for achieving some new functionality added to to sub.

    Introspection of the initial opcodes in a sub is fragile, and might break in new releases of perl. It won't work at all prior to 5.26, which introduced the argcheck/argelem/argdefelem ops, and the structure of the optree changed in 5.30. And (assuming I get my perl core mojo back at some point), there will be large changes happening to signatures in the future, reflected by big changes in the opcodes. And further changes when optimisation is added.

    Dave.

      Thanks, this is what I was playing with: perltest. I would need the introspection of the function signatures to be able to provide dependency injection. Any suggestion in that direction? Specifically the run function. Would any of the modules that provide signature be a better idea?
        I had a quick glance at that repo, and have no idea what it does apart from the fact that it's supposed to be similar to Pytest, about which I know nothing. So could you explain further the use case?

        Dave.

Re: Introspecting function signatures
by Bod (Parson) on Mar 06, 2021 at 22:55 UTC

    Please forgive what I feel sure verges on a stupid question...but...

    I *think* I have some understanding of what you are typing to do. Although it is right at the farthest edge of understanding... But why do you want to? There are well tested existing Test::Most and Test2::Suite and similar modules. What does this approach to testing achieve that these existing solutions don't?

    I thought it was a deliberate part of the design of Perl that the functional code and the tests for it were kept distinct and separate.

      I am not sure where this idea came from, that the python tests are included in the modules. They are all separated in files that are called test_SOMETHING.py.

      As of why is this better, there are a number of things that AFAIK Test::Most does not support - for example

      • running individual, independent test functions (e.g. subtests) on their own
      • having a fixtures that will run before and after each subtest.

      Test2::Suite - as far as I understand it is primarily a new harness and it also provides a front-end similar to the one provided by Test::More world (ok, is, like, subtest, etc.) This module is an alternative front-end using Test2 behind the scenes.