what is the return value type of !1 ?

S

shul

Hi,

I am curious. If I take !1 and put it into an array or hash, what
lives in that position?

I know that !1 is false, which can be represented by () or 0.

Well if I do this

my @arp = 1 .. 4;

my $len= $#arp;
print "length is $len\n";

my $out1 = ! 1;
push(@arp, $out1);
print "$arp[4]\n";
my $len= $#arp;
print "length is $len\n";

well clearly the @arp array is longer is longer, but I dont get
anything printed when I try to print
print " the value is $arp[4]\n";

it just prints

"the value is "

So what is that object at position $arp[4]?

What operator will identify what lives at $arp[4]?

Note if I push a new thing on to @arp it goes to the next position $arp
[5].

shouldn't it be 0 or maybe it really its just () ?

This came up while I was reading a article which discussed different
ways of selecting unique elements of an array, which used a ! operator
together with ++ on a hash.
 
T

Tim McDaniel

I am curious. If I take !1 and put it into an array or hash, what
lives in that position?

The same thing as if you put it into a scalar ...
I know that !1 is false, which can be represented by () or 0.

That can be stated more precisely. Luckily, "man perlsyn" does.
There are actually 5 things that are treated as false in a boolean
context, and !(something true) has a special value:

Truth and Falsehood

The number 0, the strings '0' and '', the empty list "()", and
"undef" are all false in a boolean context. All other values are
true. Negation of a true value by "!" or "not" returns a special
false value. When evaluated as a string it is treated as '', but
as a number, it is treated as 0.
but I dont get anything printed when I try to print
print " the value is $arp[4]\n";

it just prints

"the value is "

Well, you do get something: the null string, but that's a rather
pedantic statement. In
print " the value is $arp[4]\n";
With $arp[4] in the double-quoted string, it's evaluated as a string,
so as "man perlsyn" says, "it is treated as ''".

Answers to variants you didn't ask about:

By default, using it in print on its own is in string context too, so

$ perl -e '$x = !1; print "This false is <", $x, ">\n"'
This false is <>

But if you force a numeric context:

$ perl -we '$x = !1; print "This false is <", $x+0, ">\n"'
This false is <0>

Note the difference between that and this:

$ perl -we '$x = ""; print "This false is <", $x+0, ">\n"'
Argument "" isn't numeric in add at -e line 1.
This false is <0>

That is, !1 really is a special false, as "man perlsyn" says:
"" gives a warning message that !1 doesn't.
 
S

shul

Negation of a true value by "!" or "not" returns a special
false value. When evaluated as a string it is treated as '', but
as a number, it is treated as 0.

That is what I needed! A special false value!

It is a 'special false value', that when evaluated is interpreted in
context as string or number.

Now I can analyze that algorithm to think about the context :).

Thanks!

MItchell
 
I

Ilya Zakharevich

Negation of a true value by "!" or "not" returns a special
false value. When evaluated as a string it is treated as '', but
as a number, it is treated as 0.

That is what I needed! A special false value!

BS.

Hope this helps,
Ilya
 
I

Ilya Zakharevich

That can be stated more precisely. Luckily, "man perlsyn" does.

.... wrongly (as goes with the most of current Perl docs)...
There are actually 5 things that are treated as false in a boolean
context, and !(something true) has a special value:

Truth and Falsehood

The number 0, the strings '0' and '', the empty list "()", and
"undef" are all false in a boolean context. All other values are
true.
Wrong.

Negation of a true value by "!" or "not" returns a special
false value. When evaluated as a string it is treated as '', but
as a number, it is treated as 0.

There is nothing especially "special" about the returned value (unless
one noticed that it is the same value for all statements returning FALSE).

Hope this helps,
Ilya
 
X

Xho Jingleheimerschmidt

Ilya said:
There is nothing especially "special" about the returned value (unless
one noticed that it is the same value for all statements returning FALSE).

It seems somewhat special to me. It is defined, and has a length of
zero, but unlike the empty string it does not trigger an 'Argument ""
isn't numeric' warning message when used as a number.

How else would you describe a value that has these three properties?

Xho
 
T

Tim McDaniel

... wrongly (as goes with the most of current Perl docs)...


Wrong.

I would like to learn more about Perl, so would you please explain
what is correct?
There is nothing especially "special" about the returned value
(unless one noticed that it is the same value for all statements
returning FALSE).

Well, as the examples showed, the value prints as a null string --
but, unlike "", it does not throw a warning under "-w" when used in
arithmetic. I don't know of any other value that has those
properties. Why do you write that it's not "special"?
 
T

Tad J McClellan

Tim McDaniel said:
I would like to learn more about Perl, so would you please explain
what is correct?


I dunno if this is what Ilya had in mind, but the empty list
is most certainly not a false value.

Boolean context is a (special kind of) scalar context

unless ( warn wantarray ? "list context\n" : "scalar context\n" ) {
print "false value\n";
}

(prints only "scalar context")

and

there's no such thing as a list in scalar context (perlfaq4.pod)

eg.

unless ( () ) {
print "false value\n";
}

There is no empty list there, merely some parenthesis.

(parens are not a "list constructor". You very often see lists in
parens but that is for precedence reasons.
)
 
T

Tim McDaniel

I dunno if this is what Ilya had in mind, but the empty list
[glossed in snipped text as "()" from "man perlsyn"]
is most certainly not a false value.

Boolean context is a (special kind of) scalar context

unless ( warn wantarray ? "list context\n" : "scalar context\n" ) {
print "false value\n";
}

(prints only "scalar context")

and

there's no such thing as a list in scalar context (perlfaq4.pod)

eg.

unless ( () ) {
print "false value\n";
}

There is no empty list there, merely some parenthesis.

If it's not a list, what is it? It's not a reference typeglob
filehandle &c &c ... how can it be a scalar if there's no value in
there? What's its value? A few tests suggests it evaluates to
an undefined value, but is that stated somewhere?
 
U

Uri Guttman

TJM> I dunno if this is what Ilya had in mind, but the empty list
TJM> is most certainly not a false value.

it kind of is in a special way. look at this known idiom (and this is
documented somewhere)

if ( my( $foo, $bar ) = get_foobar() ) {

if the sub returns an empty list (and it will be called in list
context), then the assigned list will become false. this isn't really a
list in scalar context but does work and i use it.

perldata covers this:

List assignment in scalar context returns the number of elements
produced by the expression on the right side of the assignment:

$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count

This is handy when you want to do a list assignment in a Boolean
context, because most list functions return a null list when finished,
which when assigned produces a 0, which is interpreted as FALSE.


so the empty list itself isn't a false value but it coerces to one when
used as in the above cases and will become false.

uri
 
T

Tad J McClellan

Ben Morrow said:
This is correct.


This code doesn't demonstrate what you think it does. wantarray tells
you what context the *currently executing sub* was called in, so you
need something like

sub ctx {
warn defined wantarray ? wantarray ? "LIST" : "SCALAR" : "VOID";
}

unless (ctx) {
warn "false value";
}


I had it written that way for testing, then replaced the sub
with wantarray directly.

I should have left it the way it was. :)

I've pointed out before that I don't think this way of looking at things
is helpful.


It is if you read the sentence that follows it in the FAQ.
(and if you know what the "comma operator" is.)

I would say 'evaluating a list in scalar context evaluates
every element but the last in void context, then evaluates the last in
scalar context and returns that'.


I would say 'when evaluating what looks like a list in scalar context
you are really evaluating the comma operator'

and then maybe add your description of the comma operator's behavior.

There is *something* there. If the parens were only there for
precedence, they could safely be omitted, which they can't:

~% perl -e'unless ( () ) { 1 }'
~% perl -e'unless ( ) { 1 }'
syntax error at -e line 1, near "( ) "
Execution of -e aborted due to compilation errors.
~%


Yeah, I tried that before posting too, but it just confused me...

While this is generally true, () is special (under some circumstances:
the parsing of parens in Perl is very complicated and context-
dependant). It represents the empty list, which evaluates to undef in
scalar context:

~% perl -MDevel::peek -e'Dump scalar(())'
SV = NULL(0x0) at 0x281863d8
REFCNT = 2147483627
FLAGS = (READONLY)
~% perl -MDevel::peek -e'Dump undef'
SV = NULL(0x0) at 0x281863d8
REFCNT = 2147483627
FLAGS = (READONLY)
~%


.... and now I'm less confused.

Thanks!
 
P

Peter Makholm

Ben Morrow said:
Well, it's a dualvar, which is reasonably special. It is possible to
create an equivalent dualvar with

use Scalar::Util;

my $false = dualvar 0, "";

This is not quite the same value as I get with !1. The latter has bot
the IOK and NOK flags set but with dualvar I can only get one of these
flags set together with POK.

You can see it with Devel::peek::Dump() but I don't think I can come
up with a piece of perl code taht shows any oberserval difference.
XS-code could detect it though.

//Makholm
 
U

Uri Guttman

PM> This is not quite the same value as I get with !1. The latter has bot
PM> the IOK and NOK flags set but with dualvar I can only get one of these
PM> flags set together with POK.

PM> You can see it with Devel::peek::Dump() but I don't think I can come
PM> up with a piece of perl code taht shows any oberserval difference.
PM> XS-code could detect it though.

you seem to be wrong here. both have a string value set and POK as well.

perl -MDevel::peek -MScalar::Util=dualvar -le'print Dump !1; print Dump dualvar 0, "" ; $x = "" ;$x+0; print Dump $x'
SV = PVNV(0x8161018) at 0x815e290
REFCNT = 2147483647
FLAGS = (IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x8161008 ""\0
CUR = 0
LEN = 4

SV = PVNV(0x8161a38) at 0x8163248
REFCNT = 1
FLAGS = (TEMP,IOK,POK,pIOK,pPOK)
IV = 0
NV = 0
PV = 0x816f810 ""\0
CUR = 0
LEN = 4

SV = PVNV(0x8161a38) at 0x81771f8
REFCNT = 1
FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x816f810 ""\0
CUR = 0
LEN = 4

so both are '' and 0 at the same time. this is no different than caching
a converted value from string to/from a number. look at the third dump
which is a cached coercion. it is easy to make, just clunkier code

and this shows in detail how it caches the other possible value:


perl -MDevel::peek -le'; $x = "" ;print Dump $x; $x+0; print Dump $x'
SV = PV(0x8160048) at 0x8176d64
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0x8173208 ""\0
CUR = 0
LEN = 4

SV = PVNV(0x8161450) at 0x8176d64
REFCNT = 1
FLAGS = (IOK,NOK,POK,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x8173208 ""\0
CUR = 0
LEN = 4

note how the second dump adds IOK and NOK but the string stuff stays the
same.

so !0 and other dual false values aren't very special at all. you can
have dual values whenever you coerce a variable. it just happens that
perl's builtin false's will be in that dualform to begin with. and the
dualval function can even make the two values unrelated to each
other. !1 is just another case where perl will cache both data formats.

uri
 
I

Ilya Zakharevich


This one is wrong indeed...
There is nothing especially "special" about the returned value (unless
one noticed that it is the same value for all statements returning FALSE).

.... but here I was wrong: I forgot that + is different from ++. ++
does not warn when applied to an empty string (well, even on undefined
value!); but + does - UNLESS this empty string is what is known as
&sv_false in Perl-internal speak...

Thanks for all the people who finilly got through my defence lines and
convinced me to check my faulty memory!
Ilya
 
I

Ilya Zakharevich

There is *something* there. If the parens were only there for
precedence, they could safely be omitted, which they can't:

~% perl -e'unless ( () ) { 1 }'
~% perl -e'unless ( ) { 1 }'
syntax error at -e line 1, near "( ) "
Execution of -e aborted due to compilation errors.
~%

Having read and debugged perly.y, I won't think that any argument
about boundary cases based ONLY on perl syntax parser error messages
is very well-founded... Quite often the parser works "in this or that
way" not because

people wanted to make it work in this way,

but because

people did not find a way to convince the parser to work some other way...
While this is generally true, () is special (under some circumstances:
the parsing of parens in Perl is very complicated and context-
dependant). It represents the empty list, which evaluates to undef in
scalar context:

I think that keeping distinction between list and array is very
helpful, but sometimes one needs a different distinction: "lists as
constructed by comma operator", and "lists as returned by Perl
internal and XSUB functions".

Note that the second kind of lists cannot appear in scalar context.
The first one can; but AFAIK, the usual description DOES NOT specify
the result of evaluation of empty comma-list in scalar context...

Hope this helps,
Ilya
 
I

Ilya Zakharevich

I would like to learn more about Perl, so would you please explain
what is correct?

As other people explained, the list in scalar context is kinda fishy...

But what is very definitely wrong is the last part:

perl -wle "{package o; use overload q(\"\") => sub{q(one but false)},
q(0+) => sub {11}, bool => sub {} }"
-e "$v=bless [], o; printf qq(%d; %s; ), $v, $v; print q(FALSE) unless $v"

11; one but false; FALSE

Hope this helps,
Ilya
 
P

Peter Makholm

Uri Guttman said:
PM> This is not quite the same value as I get with !1. The latter has bot
PM> the IOK and NOK flags set but with dualvar I can only get one of these
PM> flags set together with POK.

you seem to be wrong here. both have a string value set and POK as well.

That is what I said. Both values has POK set. But !1 has both IOK and
NOK set but dualvar only one of them, just like you examples
shows. For some reason I didn't manage to come up with you third
example which shows that the !1-false isn't really sepcial.

//Makholm
 
U

Uri Guttman

PM> This is not quite the same value as I get with !1. The latter has bot
PM> the IOK and NOK flags set but with dualvar I can only get one of these
PM> flags set together with POK.
PM> That is what I said. Both values has POK set. But !1 has both IOK and
PM> NOK set but dualvar only one of them, just like you examples
PM> shows. For some reason I didn't manage to come up with you third
PM> example which shows that the !1-false isn't really sepcial.

well that is because dualvar is called DUALvar! it only sets the string
and integer parts and not the number (float) part. builtin false knows
that it is also a valid number (probably just zeroes out the float slot)
and so does !1 since that is the same. look at this variant:

perl -MDevel::peek -MScalar::Util=dualvar -le' print Dump dualvar 0.0, ""'
SV = PVNV(0x8161a38) at 0x8163248
REFCNT = 1
FLAGS = (TEMP,NOK,POK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x8173228 ""\0
CUR = 0
LEN = 4

dualvar on 0.0 sets NOK and not IOK. so it knows the internal parsed 0.0
is a number and DWIMs. it still only sets 2 of the possible 3 values.

so this is just a weakness on dualvar's part that it can only set the
number or integer slot. i can't seem to force that. it always sets the
string slot (POK).
the

uri
 
D

Dr.Ruud

Uri said:
perl -MDevel::peek -MScalar::Util=dualvar -le' print Dump dualvar 0.0, ""'
SV = PVNV(0x8161a38) at 0x8163248
REFCNT = 1
FLAGS = (TEMP,NOK,POK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x8173228 ""\0
CUR = 0
LEN = 4

dualvar on 0.0 sets NOK and not IOK. so it knows the internal parsed 0.0
is a number and DWIMs. it still only sets 2 of the possible 3 values.

so this is just a weakness on dualvar's part that it can only set the
number or integer slot. i can't seem to force that. it always sets the
string slot (POK).

No IOK either:

perl -MDevel::peek -wle'
my $x = 0.0; 0 if $x eq ""; print Dump $x;
'
SV = PVNV(0x94ee9f8) at 0x94bbcd4
REFCNT = 1
FLAGS = (PADBUSY,PADMY,NOK,POK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x94ccc70 "0"\0
CUR = 1
LEN = 35


With IOK:

perl -MDevel::peek -wle'
my $x = 0.0+0; 0 if $x eq ""; print Dump $x;
'
SV = PVIV(0x9e08308) at 0x9e07cd4
REFCNT = 1
FLAGS = (PADBUSY,PADMY,IOK,POK,pIOK,pPOK)
IV = 0
PV = 0x9e194a8 "0"\0
CUR = 1
LEN = 2


See also Data::peek::triplevar().
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top