Distinguishing string and numerical context?

D

Damian

Is there anyway to tell, for a function thats being called in a scalar
context, weather it's expected to return a string or a number? sorta
like localtime, which returns a number and returns a string if you put
"". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

It some how *knows* if it's being used with a string (concatenated) or
not, orta like an array seems to know too.

Thanks for any help.
 
B

Ben Morrow

Damian said:
Is there anyway to tell, for a function thats being called in a scalar
context, weather it's expected to return a string or a number? sorta
like localtime, which returns a number and returns a string if you put
"". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

You can create such values with Scalar::Util::dualvar. Those default
to string, though, like $!; if you need them to default to number
you'll have to write a pretty simple bit of XS.

Ben
 
W

Walter Roberson

:Is there anyway to tell, for a function thats being called in a scalar
:context, weather it's expected to return a string or a number? sorta
:like localtime, which returns a number and returns a string if you put
:"". before it like:

:[damian@me ~]# perl -e 'print localtime(), "\n";'
:321512201044210
:[damian@me ~]# perl -e 'print "". localtime(), "\n";'
:Thu Jan 22 01:15:39 2004

:It some how *knows* if it's being used with a string (concatenated) or
:not, orta like an array seems to know too.

You have misinterpreted. localtime() does not return a number in
that first example. When you invoke localtime() like that within
print, print is supplying a list context, and localtime() is returning
a list value which print is kindly jamming together due to the default
element separator being the empty string.

$ perl -e '$,="|";print localtime,"\n"'
43|57|3|22|0|104|4|21|0|

In your second example, the "". supplies a scalar context, and
localtime() reacts accordingly.

$ perl -e 'print scalar(localtime),"\n"'
Thu Jan 22 03:59:13 2004
 
A

Anno Siegel

Ben Morrow said:
Damian said:
Is there anyway to tell, for a function thats being called in a scalar
context, weather it's expected to return a string or a number? sorta
like localtime, which returns a number and returns a string if you put
"". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

You can create such values with Scalar::Util::dualvar. Those default
to string, though, like $!; if you need them to default to number
you'll have to write a pretty simple bit of XS.

True, and probably what the OP wanted to know, but this isn't what
happens with localtime.

The OP has misinterpreted the results. The difference isn't numeric
vs. string context, it's array vs. scalar context. The first example
calls localtime() in array context, so it returns a list of numbers
(sec, min, ...). Printing runs them all together, so the result looks
like one big number. The second example calls it in scalar context
(the "." operator), so localtime returns its result as a string.

Anno
 
D

Damian

Anno Siegel said:
Ben Morrow said:
Damian said:
Is there anyway to tell, for a function thats being called in a scalar
context, weather it's expected to return a string or a number? sorta
like localtime, which returns a number and returns a string if you put
"". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

You can create such values with Scalar::Util::dualvar. Those default
to string, though, like $!; if you need them to default to number
you'll have to write a pretty simple bit of XS.

True, and probably what the OP wanted to know, but this isn't what
happens with localtime.

The OP has misinterpreted the results. The difference isn't numeric
vs. string context, it's array vs. scalar context. The first example
calls localtime() in array context, so it returns a list of numbers
(sec, min, ...). Printing runs them all together, so the result looks
like one big number. The second example calls it in scalar context
(the "." operator), so localtime returns its result as a string.

Thank you for pointing that out. I even did al ittle test to be sure:

$ perl -e 'print localtime(), "\nLocaltime Array:\n[".
join("][",localtime()), "]\n";'
345922201044210
Localtime Array:
[34][59][2][22][0][104][4][21][0]

I had always thoguht it returned the time in seconds, silly me.
 
D

Damian

Damian said:
Anno Siegel said:
Ben Morrow said:
Is there anyway to tell, for a function thats being called in a
scalar context, weather it's expected to return a string or a
number? sorta like localtime, which returns a number and returns a
string if you put "". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

You can create such values with Scalar::Util::dualvar. Those default
to string, though, like $!; if you need them to default to number
you'll have to write a pretty simple bit of XS.

True, and probably what the OP wanted to know, but this isn't what
happens with localtime.

The OP has misinterpreted the results. The difference isn't numeric
vs. string context, it's array vs. scalar context. The first example
calls localtime() in array context, so it returns a list of numbers
(sec, min, ...). Printing runs them all together, so the result
looks like one big number. The second example calls it in scalar
context (the "." operator), so localtime returns its result as a
string.

Thank you for pointing that out. I even did al ittle test to be sure:

$ perl -e 'print localtime(), "\nLocaltime Array:\n[".
join("][",localtime()), "]\n";'
345922201044210
Localtime Array:
[34][59][2][22][0][104][4][21][0]

I had always thoguht it returned the time in seconds, silly me.

Bah, I was mixing it with timelocal(), which takes a localtime-type
array and spits out the time in raw seconds. Sorry its 3am...
 
B

Brian McCauley

Ben Morrow said:
Damian said:
Is there anyway to tell, for a function thats being called in a scalar
context, weather it's expected to return a string or a number? sorta
like localtime, which returns a number and returns a string if you put
"". before it like:

[damian@me ~]# perl -e 'print localtime(), "\n";'
321512201044210
[damian@me ~]# perl -e 'print "". localtime(), "\n";'
Thu Jan 22 01:15:39 2004

Other's have pointed out the question actaully wanted to ask is about
scalar v list not numeric v string context however...
You can create such values with Scalar::Util::dualvar. Those default
to string, though, like $!; if you need them to default to number
you'll have to write a pretty simple bit of XS.

If calculating the string value is inexpensive (or if the string value
is usually what's wanted anyhow) then Scalar::Util::dualvar certainly
the way to do it.

If calculating the string value is expensive (e.g. a database lookup)
and rarely necessary then you may want to consider deferring
stringification by returning an object that has '0+' and '""' overload
semantics.
[ speaking of Scalar::Util::dualvar ]. Those default to string,
though, like $!;

I'm sorry I don't understand what you mean by that.

use Scalar::Util qw( dualvar );
my $q = dualvar(3,'three');
$! = 3;
print 'dualvar defaults to ', $q^$q eq '0' ? 'numeric' : 'string',"\n";
print '$! defaults to ', $!^$! eq '0' ? 'numeric' : 'string',"\n";
__END__
dualvar defaults to numeric
$! defaults to numeric

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
 
B

Ben Morrow

Brian McCauley said:
Ben Morrow said:
[ speaking of Scalar::Util::dualvar ]. Those default to string,
though, like $!;

I'm sorry I don't understand what you mean by that.

Sorry, I was implicitly falling into the same confusion as the OP wrt
localtime and print (see Anno's post). I was thinking the difference
between

perl -le'my $x = dualvar 3, "three"; print $x'
three

and

perl -le'print localtime'
<number>

was due to localtime returning a number-with-a-string-representation
rather than a string-with-a-numeric-representation; in fact it is due
to localtime returning a list (which happens to be of numbers).

I keep getting bitten by this :(. print gives *list* *context*,
dammit!

Ben
 
A

Anno Siegel

Brian McCauley said:
print 'dualvar defaults to ', $q^$q eq '0' ? 'numeric' : 'string',"\n";

....ah, the simple answer to the number-or-string question, at least in
one of its guises. I keep forgetting that. Have you been using it
for long? I thought there was a bug in earlier versions that kept it
from working.

Anno
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top