Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Accessing a scalar value in another subroutine?

by Anonymous Monk
on Sep 23, 2012 at 19:15 UTC ( #995235=perlquestion: print w/ replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks.

I'm writing an OO perl program and I would like to create a "docstring", which describes the purpose of the method, then in a help method, access the docstring of each respective method in a manner similar to:
my ($method) = shift; print $method::docstring;


...rather than awkwardly use a series of if/elsif/else statements. Is there a convenient approach to this problem?

Thanks.

Comment on Accessing a scalar value in another subroutine?
Download Code
Re: Accessing a scalar value in another subroutine?
by Anonymous Monk on Sep 23, 2012 at 19:36 UTC
    Hi.

    For example:

    sub method1 { my $self = shift; my $docstring = "Prints information about X, Y, and Z"; # ... } sub help { my $self = shift; my $method = shift; # Note: The following approach does not work. # I tried inserting the package name before the method name, i.e., + $package_name::method::docstring, but that too was unsuccessful. + # print $method::docstring, "\n"; } <br/> <br/> Thanks.
      I doubt this is a good idea $docstring is only initialized after method1 is called for the first time.

      So you won't be able to inspect the docstring in advance.

      But if that's OK for you you might wanna try PadWalker::peek_sub.

      UPDATE:

      Nope doesn't help, lexical are reset to undef after the function-scope is left.

      DB<135> sub tst { my $doc="bla" } => 0 DB<136> PadWalker::peek_sub(\&tst) => { "\$doc" => \undef } DB<137> tst() => "bla" DB<138> PadWalker::peek_sub(\&tst) => { "\$doc" => \undef }

      Cheers Rolf

Re: Accessing a scalar value in another subroutine?
by LanX (Canon) on Sep 23, 2012 at 19:50 UTC
    TIMTOWTDI

    DB<114> sub doc { return } => 0 DB<115> sub tst { doc q/blab bla bla/; return "tst" } => 0 DB<116> use B::Deparse => 0 DB<117> print B::Deparse->new()->coderef2text(\&tst) { doc('blab bla bla'); return 'tst'; }

    The book Perl Hacks showed another approach, I can't recall the details, IIRC something with attributes which assign a text to a hash with subnames as keys.

    Cheers Rolf

Re: Accessing a scalar value in another subroutine?
by BrowserUk (Pope) on Sep 23, 2012 at 20:08 UTC
    I'm writing an OO perl program and I would like to create a "docstring", which describes the purpose of the method, then in a help method, access the docstring of each respective method

    What is the purpose? Who are you providing this help to?

    Are you suggesting that for a programmer -- who else would use this information -- to get help on how to use a particular method in their program, they first write another program that calls the help method with the name of the method they actually want to call?

    Why would anyone do this rather than just look up the documentation; or -- heavens forfend -- look at the source?

    To my eyes, this looks like the most fatuous piece of O'Woe (Order of Worshipful Over Engineers) rubbish I've seen in a long time.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    RIP Neil Armstrong

      To my eyes, this sound like the most fatuous piece of O'Woe (Order of Worshipful Over Engineers) rubbish I've seen in a long time.

      Considering that both Python and Common Lisp employ docstrings for the users of a class, I don't think "rubbish" would be an accurate term to describe my aspiration. I was merely asking if it was possible since a series of if/elsif/else constructs would have been less than elegant.
        Considering that both Python and Common Lisp employ docstrings for the users of a class,

        Could you demonstrate an example of their use?


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        RIP Neil Armstrong

        don't feed the trolls!

        Yes. I read the docs; but would still like to a see an example of actual, practical use.

        The only example I've seen that makes any logical sense at all (to me), is the ability to query the information in a repl.

        But that extremely limited-use facility, does not justify burdening the runtime with the overheads it imposes, in a language who's runtime has facilities designed to support it.

        Emulating that limited-use facility in a language the does not have runtime facilities to support just imposes addition runtime costs for no conceivable benefits.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        RIP Neil Armstrong

Re: Accessing a scalar value in another subroutine?
by tobyink (Abbot) on Sep 23, 2012 at 20:39 UTC

    Why do you want to do this rather than just use POD? ("I heart Python" is not a good reason.)

    That having been said, there's actually a really easy way to do this for object-oriented code (i.e. subs designed to be called as methods rather than functions).

    use v5.14; package Foobar { sub new { bless [] => shift; } sub quux { return "documentation" unless @_; say "The method has been called!"; } } my $obj = Foobar->new; $obj->quux; # calls the method print Foobar::quux(); # prints the documentation
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      > Why do you want to do this rather than just use POD?

      POD is normally used to describe the public API of a module and many people oppose weaving POD snippets close to subs.

      Furthermore automatically finding the corresponding POD-part for a function isn't trivial.

      Docstrings OTOH are closely tied and great for introspection in an interactive system, like REPLs or applications with embedded scripting.

      I'm inspecting LISP docstrings in emacs every day when browsing thru functions.

      Cheers Rolf

        If you are hell-bent on doing that, and having doc-strings for your functions, the following style may be to your taste:

        use vars %documentation; sub doc($$) { my ($for,$doc) = @_; $documentation{ $for } = $doc; }; doc('mysub1',<<'=cut'); =head2 C<< mysub1 >> This documents mysub1. An example: mysub1(); =cut sub mysub1 { ... }; doc('frobnicate',<<'=cut'); =head2 C<< frobnicate >> This documents frobnicate. An example: frobnicate(); =cut sub frobnicate { ... };

        You will note from history that this style never caught on.

        If you adhere to a strict documentation style, you may simply parse the POD and extract the function definitions from that. Using "docstrings" and parsing the module documentation are equivalent in that sense.

        Furthermore automatically finding the corresponding POD-part for a function isn't trivial.

        Yes, it is absolutely trivial, provided the pod actually documents the function. Pod::Select/Pod::Coverage ...

Re: Accessing a scalar value in another subroutine?
by james2vegas (Chaplain) on Sep 24, 2012 at 07:48 UTC
    Perhaps something like this, using Attribute-Handlers and putting the attribute in UNIVERSAL, which would, obviously, be optional:

    package DocString; use Attribute::Handlers; use Data::Dumper; no warnings 'redefine'; our $docstrings; # sub Doc :ATTR(CODE) { sub UNIVERSAL::Doc :ATTR(CODE) { my ($package, $symbol, $referent, $attr, $data, $phase, $filename, + $linenum) = @_; $docstrings->{ $package }{ *{$symbol}{NAME} } = "@$data"; } # you could also have a docstring function exported from this module t +hat, given a package # and a sub returns # $DocString::docstrings->{$pkg}{$sub}); 1;

    which could be used like this:

    package Forble; use strict; use warnings; use DocString; sub veeblefaz :Doc("This method does the 2nd kind of veeblefaz operati +on!") { # this can be called from elsewhere, with the appropriate package +and sub names print Dumper($DocString::docstrings->{+__PACKAGE__}{veeblefaz}); + } 1;
Re: Accessing a scalar value in another subroutine?
by LanX (Canon) on Sep 24, 2012 at 09:50 UTC
    Here the solution from "Perl Hacks". It's freely downloadable from O'Reilly
    package Attribute::Docstring; use strict; use warnings; use Scalar::Util 'blessed'; use Attribute::Handlers; my %doc; sub UNIVERSAL::Doc :ATTR { my ($package, $symbol, $referent, $attr, $data, $phase) = @_; return if $symbol eq 'LEXICAL'; my $name = *{$symbol}{NAME}; $doc{ $package }{$name} = $data; } sub UNIVERSAL::doc { my ($self, $name) = @_; my $package = blessed( $self ) || $self; return unless exists $doc{ $package }{ $name }; return $doc{ $package }{ $name }; } 1;
    application
    package Counter; use strict; use warnings; use Attribute::Docstring; our $counter :Doc( 'a count of all new Foo objects' ); sub new :Doc( 'the constructor for Foo' ) { $counter++; bless {}, shift; } sub get_count :Doc( 'returns the count for all foo objects' ) { return $counter; } 1;

    Cheers Rolf

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://995235]
Approved by Perlbotics
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (11)
As of 2014-09-21 15:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (172 votes), past polls