How to tell if a subroutine arg is a constant

J

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.
 
G

Gunnar Hjalmarsson

jonnytheclown said:
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;
}
...
}
 
J

jonnytheclown

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.
 
R

Robert Sedlacek

jonnytheclown said:
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
 
T

Tassilo v. Parseval

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
 
B

Brian McCauley

jonnytheclown said:
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.
 
J

jonnytheclown

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.
 
A

Ala Qumsieh

jonnytheclown said:
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
 
M

Mintcake

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.
 
B

Brian McCauley

Mintcake said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top