in reply to How do I check if a scalar in @_ is writable?

You can see if a scalar is read-only by using Scalar::Util::readonly. (That's the same as the Util routine several other people have mentioned, but the module was renamed, and now comes with recent versions of perl.)

However, I think you API is rather poor, and changing the API would relieve the need to check for read-only parameters. In general, you should only modify your parameters when you have /very/ good reason, because it isn't what your users expect.

Instead of taking in a name, a url, and a body, and refering them soley by their entries in @_, copy them into variables in your subroutine, and return the modified body.

Not only does this make your function behave the way callers are (more likely to) expect it to work, it makes the body of your function read more clearly. I noticed you refer to your paramters in the comments as "name", $url, and $body. So, taking from your lead...

#!/usr/bin/perl -w use strict; use warnings; use HTML::Entities; sub sanitize { my($name, $url, $body) = @_; # no name? $name ||= "anonymous"; # add missing protocol in $url if ($url && $url !~ /^\w+:/) { $url = "http://" . $url } # add missing protocol in link in $body $body =~ s{\[(.*?)\]}{ my $x = $1; if ($1 !~ /^\w+:/) { if ($1 =~ /\@/) { "[mailto:$x|$x]"; } else { "[http://$x]" } } else { "[$x]" } }gex; # don't let people put in html $body = HTML::Entities::encode($body); # Return modified body. return $body; } my $body = "Mail me at [bugs\@microsoft.com]."; my $url; my $name; $body = sanitize("", $url, $body); print $body, "\n";

Now, the varibles that are not assigned to in the mainline of the program aren't modified. You can pass in whatever you want in $name, without worring about if it's writable, because your copy of it will be. The API of your sub is more like it's users probably expect.

If you really want to not change the API of your function, so that you don't have to modifiy the existing callers, you can, near the return line, check for not defined wantarray, that is, if your sub is being called in void context (it's return value isn't being assigned anywhere), and do a $_[2]=$body.


Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

Replies are listed 'Best First'.
Re: Re: How do I check if a scalar in @_ is writable?
by beppu (Hermit) on Oct 27, 2003 at 23:22 UTC
    Yeah, I admit that the API is shitty, but I was just amusing myself with @_ aliasing when I found this error. I was the only user of this little subroutine, anyway, and it wasn't part of any library I was going to distribute or anything.

    Thanks for the tip on Scalar::Util::readonly(), and thanks to everyone else for their comments.