Re: 1 vs "1"
by davorg (Chancellor) on Sep 12, 2001 at 18:52 UTC
|
You can't. Perl scalars can be used both as numbers
and strings. Perl converts between the two internally
and seamlessly.
Actually, that's not completely true. You might be
able to do some deep XS magic to find out whether the
string slot or the number slot in the SV has been used,
but I'm guessing that you don't really want to go
there :)
--
<http://www.dave.org.uk>
Perl Training in the UK <http://www.iterative-software.com>
| [reply] [Watch: Dir/Any] |
Re: 1 vs "1"
by suaveant (Parson) on Sep 12, 2001 at 18:49 UTC
|
| [reply] [Watch: Dir/Any] |
Re: 1 vs "1"
by dragonchild (Archbishop) on Sep 12, 2001 at 19:11 UTC
|
It sounds like you're trying to do something in C, not Perl. If the string you're passing is an integer, then it's an integer, not a string!
I'm not trying to be dense, but that's the way Perl looks at things. If you want to pass integers in, but treat them as strings, the easiest way I can think of it to pass a second variable in that would tell you if this scalar is to be viewed as an integer or string.
Of course, I would personally write two functions, one for integers and one for strings. Then, you decide outside the function which to do. Right now, you've got a function doing two different things. Make each do one thing and one thing well.
You can tell this really easily if your function has the form:
sub foo {
my ($a, $b, $c) = @_;
if ($a == 1) {
# Do something
} else {
# Do something else
}
}
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] [Watch: Dir/Any] [d/l] |
Re: 1 vs "1"
by ariels (Curate) on Sep 12, 2001 at 19:24 UTC
|
package types;
use Inline C => <<'END_C';
int is_iv(SV *x) {
return SvIOKp(x) != 0;
}
int is_nv(SV *x) {
return SvNOKp(x) != 0;
}
int is_pv(SV *x) {
return SvPOKp(x) != 0;
}
END_C
1;
But I'm not sure I'd recommend doing this! Perl users expect to have all integers autostringified when needed. Also, I wouldn't try it on magic "double valued scalars" (which have different string and numeric values), like $!.
| [reply] [Watch: Dir/Any] [d/l] |
Re: 1 vs "1"
by nardo (Friar) on Sep 12, 2001 at 19:14 UTC
|
On another note, whenever I preview this, I have to re-add the "1" in the title, as it disappears from the input box. Is this a bug?
Yes. The resulting html is:
<INPUT TYPE="text" name="node" value="1 vs "1"">
The quote before the second 1 ends the value property. In other cases quotes get replaced with " which displays it correctly in the textbox so it shouldn't be too difficult to fix this. | [reply] [Watch: Dir/Any] [d/l] |
Re: 1 vs "1"
by George_Sherston (Vicar) on Sep 12, 2001 at 19:36 UTC
|
I was staggered to learn how non-simple this seemingly simple problem is. Staggered, but also educated. This thread was a big help.
§ George Sherston | [reply] [Watch: Dir/Any] |
Re: 1 vs "1"
by Jeff Connelly (Acolyte) on Sep 13, 2001 at 03:18 UTC
|
You may be able to exploit the ~ operator, it has deep
knowledge of Perl's internals. For example:
$string = "1";
$integer = 1;
print ~$string; # Prints an extended character
print ~$integer; # Prints 4294967294
Much easier than messing with perlguts. But there's
one caveat: using ~ on a string with extended characters
results in ASCII characters; that is ~chr(205)
is "2". Assuming your definition of "string" does not
include extended characters (only ASCII), you should be
able to get away with a function like this:
sub is_integer
{
return (~$_[0] =~ m/^[0-9]+$/) ? 1 : 0;
}
print "1 ", is_integer(1), "\n"; # 1 ok
print "'1' ", is_integer('1'), "\n"; # 0 ok
print "chr(205) ", is_integer(chr(205)),"\n"; # 1 not ok
That said, be careful with this power. You don't want
to confuse your users. Problems occur when reading data
from files or console, as everything read is a string unless
explically changed via +0. This also doesn't work for
floating point. But sometimes it may have useful uses.
Hope this helps,
Jeff Connelly
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: 1 vs "1"
by Caillte (Friar) on Sep 12, 2001 at 20:50 UTC
|
A limited method, but one that could be built on is to use
+0. Using an eval like the example below will return 0 if
fed a string containing no numeric characters or the number 0
so, something like this could be a start:
foreach my $var ('0', '-112.04', 'qwerty') {
$var2 = eval '$var+0';
if($var eq '0' or $var2) {
print "Is an number\n";
} else {
print "May not be an number\n";
}
}
$japh->{'Caillte'} = $me; | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: 1 vs "1"
by MZSanford (Curate) on Sep 12, 2001 at 19:55 UTC
|
not that i suggest this, but i bet Devel::Peek could be used to find out if the value passed is an IV/NV or PV ... but once again, not really suggested.
my own worst enemy
-- MZSanford
| [reply] [Watch: Dir/Any] |
Re: 1 vs "1"
by riffraff (Pilgrim) on Sep 13, 2001 at 00:27 UTC
|
You could also force the string to be looked at as a string, by,
for example, prepending a character in front of it:
$a=1;
func($a); # a number
func("x$a"); # now a string
riffraff
| [reply] [Watch: Dir/Any] [d/l] |
(jeffa) Re: 1 vs "1"
by jeffa (Bishop) on Sep 12, 2001 at 19:02 UTC
|
| [reply] [Watch: Dir/Any] |
|
my $number = 1;
my $string = "1";
how would you tell which is a string and which is a
number. I don't think your solution addresses this.
Oh, and your regex to check for floating point numbers
could use some work too :)
--
<http://www.dave.org.uk>
Perl Training in the UK <http://www.iterative-software.com> | [reply] [Watch: Dir/Any] [d/l] |