How to tell if a subroutine arg is a constant

Discussion in 'Perl Misc' started by jonnytheclown, Feb 24, 2005.

  1. Is there an easy way to test if a subroutine argument is a constant.

    I know it can be done by trying to assign to the specific element in @_
    within an eval and testing for an exception but this is a tad ugly -
    not to mention inefficient.
     
    jonnytheclown, Feb 24, 2005
    #1
    1. Advertising

  2. jonnytheclown wrote:
    > Is there an easy way to test if a subroutine argument is a constant.
    >
    > I know it can be done by trying to assign to the specific element in @_
    > within an eval and testing for an exception but this is a tad ugly -
    > not to mention inefficient.


    Not sure what you mean by "constant" in this context. Can't you simply
    use the ref() function?

    sub myfunction {
    for (@_) {
    print "$_ is a constant\n" unless ref;
    }
    ...
    }

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Feb 24, 2005
    #2
    1. Advertising

  3. I'm trying to detect if the caller passed in a literal or a scalar
    variable - nothing to do with references, e.g.

    foo('xyz');

    versus...

    $v = 'xyz';
    foo($v);

    If the caller uses the first syntax then the subroutine will not be
    able to modify the argument. If the second syntax is used then the
    argument can be modified within the subroutine.
     
    jonnytheclown, Feb 24, 2005
    #3
  4. jonnytheclown wrote:

    > If the caller uses the first syntax then the subroutine will not be able
    > to modify the argument. If the second syntax is used then the argument
    > can be modified within the subroutine.


    If you just want to make sure you can change the value, you could use
    prototypes to tell perl you want a reference:

    phaylon@hamlett:~> perl -Mstrict -Mwarnings
    sub test (\$) { # prototyped
    print "@_\n";
    }
    my $a = 10;
    test($a);
    test(13);
    ^D
    Type of arg 1 to main::test must be scalar (not constant item) at - line
    6, near "13)"
    Execution of - aborted due to compilation errors.

    hth,phay

    --
    http://www.dunkelheit.at/
    That is not dead, which can eternal lie,
    and with strange aeons even death may die.
    -- H.P. Lovecraft
     
    Robert Sedlacek, Feb 24, 2005
    #4
  5. Also sprach jonnytheclown:

    > Is there an easy way to test if a subroutine argument is a constant.
    >
    > I know it can be done by trying to assign to the specific element in @_
    > within an eval and testing for an exception but this is a tad ugly -
    > not to mention inefficient.


    This appears to be impossible from pure Perl (at least when avoiding the
    method you outlined). With a very little bit of C however, it's easy:

    #! /usr/bin/perl -l

    use Inline C => <<EOC;
    int is_readonly (SV *sv) {
    return SvREADONLY(sv) != 0;
    }
    EOC

    print is_readonly("string");
    print is_readonly($s = "string");
    __END__
    1
    0

    Tassilo
    --
    use bigint;
    $n=71423350343770280161397026330337371139054411854220053437565440;
    $m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
     
    Tassilo v. Parseval, Feb 24, 2005
    #5
  6. jonnytheclown wrote:

    > Is there an easy way to test if a subroutine argument is a constant.


    Scalar::Util::readonly

    > I know it can be done by trying to assign to the specific element in @_
    > within an eval and testing for an exception but this is a tad ugly -
    > not to mention inefficient.


    I would suspect there's something wrong with the API of any subroutine
    that needs this information.
     
    Brian McCauley, Feb 24, 2005
    #6
  7. Thanks for the Scalar::Util pointer - just what I needed.

    As to why I want it...

    I want to build in variant behaviour to an object method so I can
    differentiate between...

    $o->foo(-abc, ...);

    and

    $o->foo(...);

    Without placing restrictions on the callers first real arg provided it
    is not a literal starting with '-'. If that makes sense.
     
    jonnytheclown, Feb 24, 2005
    #7
  8. jonnytheclown

    Ala Qumsieh Guest

    jonnytheclown wrote:

    > Thanks for the Scalar::Util pointer - just what I needed.
    >
    > As to why I want it...
    >
    > I want to build in variant behaviour to an object method so I can
    > differentiate between...
    >
    > $o->foo(-abc, ...);
    >
    > and
    >
    > $o->foo(...);
    >
    > Without placing restrictions on the callers first real arg provided it
    > is not a literal starting with '-'. If that makes sense.


    Not quite.
    So, in your application, you will never have this scenario:

    my @opts = '-abc';
    $o->foo(@opts, @more_args);

    ?

    --Ala
     
    Ala Qumsieh, Feb 24, 2005
    #8
  9. jonnytheclown

    Mintcake Guest

    If the caller wanted to pass -abc as a variable (as in your example)
    then it wold be treated as such. What would not be allowed is if the
    caller did not want the -abc to to be treated as a special case - in
    which case simply not accidently passing -abc as a literal should do
    the trick. What I'm saying is that -abc would only be treated as a
    special case if it was coded as a literal - and that is entirely under
    the programmers control.
     
    Mintcake, Feb 28, 2005
    #9
  10. Mintcake wrote:

    > If the caller wanted to pass -abc as a variable (as in your example)
    > then it wold be treated as such. What would not be allowed is if the
    > caller did not want the -abc to to be treated as a special case - in
    > which case simply not accidently passing -abc as a literal should do
    > the trick. What I'm saying is that -abc would only be treated as a
    > special case if it was coded as a literal - and that is entirely under
    > the programmers control.


    Yeah, but it's still a real ugly API.
     
    Brian McCauley, Mar 1, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark Drummond

    Passing a list as an arg to a subroutine

    Mark Drummond, Mar 7, 2006, in forum: Perl
    Replies:
    2
    Views:
    2,307
    Thomas Wasell
    Mar 9, 2006
  2. n00m
    Replies:
    5
    Views:
    396
  3. Replies:
    3
    Views:
    124
    Tad J McClellan
    Mar 21, 2009
  4. Replies:
    7
    Views:
    179
  5. Replies:
    21
    Views:
    308
    Barry Schwarz
    Mar 5, 2014
Loading...

Share This Page