I'm new to perl... could someone help me understand why perl eval behave like this:
eval with array or list: pass
eval with list + or do: pass
eval with array + or do: return value is not the expected result, it's taking the last element.
80> eval{(1,2,3)} or do {}
Useless use of a constant (2) in void context at reply input line 1.
$res[34] = 3
81> eval{[1,2,3]} or do {}
$res[35] = [
1,
2,
3
]
82> eval{(1,2,3)}
$res[36] = [
1,
2,
3
]
83> eval{[1,2,3]}
$res[37] = [
1,
2,
3
]
You need to start by studying Perl's concept of context.
The short version is that operators are evaluated in list, scalar or void context. The context of an operator is determined by the operator of which it is an operand.
In list context, an operator may return any number (0 or more) scalars.
In scalar context, an operator must return exactly one scalar (no more, no less).
In void context, the scalars returned by an operator are discarded.
Operators can and do and return different values depending on the context. Any operator that nominally returns multiple scalars must necessarily return something different in list context and scalar context.
Now that you've studied Perl's concept of context, I'll cover how it applies to the list/comma operator.
To do that, we'll look at these two statements.
my #a = (1,2,3);
my $s = (1,2,3);
Note that all ( ) does is change precedence like ( ) in mathematics. It doesn't result in any code. It doesn't create any kind of data structure.
In the first case, we have a list assignment operator. It evaluates its right-hand side operand in list context. This means that 1,2,3 is evaluated in list context.
In list context, 1,2,3 evaluates each item of the list in list context, and returns every scalar produced. As such, it returns 1, 2 and 3.
In the second case, we have a scalar assignment operator. It evaluates its left-hand side operand in scalar context. This means that 1,2,3 is evaluated in scalar context.
In scalar context, 1,2,3 evaluates each item but the last in void context, then evaluates the last item in scalar context, and returns the scalar produced by the last time. As such, it's effectively short for do { 1;2;3 }, and it returns 3.
Finally, let's examine the context of each operator in the expressions you provided.
The perl debugger evaluates provided code in list context.
or imposes a scalar context on its left-hand side operand.
[ ] evaluates its initializaing expression in list context.
eval propagates its context to the last statement of the block.
eval{(1,2,3)} or do {}
# Order Context Operator Produces
# ----- ------- ------------- --------
# 6 list or 3
# 5 scalar eval 3
# 4 scalar , 3
# 1 void 1 <nothing>
# 2 void 2 <nothing>
# 3 scalar 3 3
# - list do <not evaluated>
eval{[1,2,3]} or do {}
# Order Context Operator Produces
# ----- ------- ------------- --------
# 7 list or ref to array
# 6 scalar eval ref to array
# 5 scalar [] ref to array
# 4 list , 1 and 2 and 3
# 1 list 1 1
# 2 list 2 2
# 3 list 3 3
# - list do <not evaluated>
eval{(1,2,3)}
# Order Context Operator Produces
# ----- ------- ------------- --------
# 5 list eval 1 and 2 and 3
# 4 list , 1 and 2 and 3
# 1 list 1 1
# 2 list 2 2
# 3 list 3 3
eval{[1,2,3]}
# Order Context Operator Produces
# ----- ------- ------------- --------
# 6 list eval ref to array
# 5 list [] ref to array
# 4 list , 1 and 2 and 3
# 1 list 1 1
# 2 list 2 2
# 3 list 3 3
The code snippets in the question seem to run in Reply (a REPL shell), so in list context.
Let's start from claryfing the context aspect of this, a crucial concept in Perl. From eval
In both forms, the value returned is the value of the last expression evaluated inside the mini-program; a return statement may also be used, just as with subroutines. The expression providing the return value is evaluated in void, scalar, or list context, depending on the context of the eval itself.
So if the return of eval is assigned to a scalar then the (last) expression in the block is evaluated in the scalar context. If the eval is or-ed (with the return of the doblock for example, like here), it is scalar context again.
In such a case the comma operator behaves as
In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value.
While comma is evaluating and throwing values away it acts in void context (those values aren't used for anything), and those are the warnings we see:
perl -wE'$val = eval { (7, 8, 9) }'
prints
Useless use of a constant (7) in void context at -e line 1.
Useless use of a constant (8) in void context at -e line 1.
since the first two values are discarded while the last one does get used. Same for
perl -wE'eval { (7, 8, 9) } or do { 1 }'
and for the same reason, as 9 gets or-ed with the return value of do.
If nothing at all were to be done with this
perl -wE'eval { (7, 8, 9) }'
then we would get
Useless use of a constant (7) in void context at -e line 1.
Useless use of a constant (8) in void context at -e line 1.
Useless use of a constant (9) in void context at -e line 1.
(But in the environment used in the question, which is a REPL shell, this gets assigned to an array, unlike the snippet from a one-liner above. Such list context is discussed next.)
So these warnings are from the comma operator, while the context for its behavior is supplied by the context the eval is in.
Now, if the eval's return is used in a list context, like passed to a map or assigned to an array, like it is in the environment used in the question, then the list context inside the block makes the comma behave as
In list context, it's just the list argument separator, and inserts both its arguments into the list.
So that list (7, 8, 9) gets orderly returned and there are no warnings.
There is one more case to clarify, with [7, 8, 9] -- now the [ ] are the constructor for an anonymous array so the comma operator inside is in the list context and "inserts" its arguments into the list, which is used to build an array ref. No reasons for warnings.
The fun part: when 1 is an element of the list there is no warning about it being a useless constant etc! Like, for
perl -wE'eval { (7, 1, 9) }'
we get
Useless use of a constant (7) in void context at -e line 1.
Useless use of a constant (9) in void context at -e line 1.
The reason being that 1 is (apparently) special-cased this way so that one can do things like
1 while ...
Thanks for Dave Mitchell for letting me know about why 1 is excluded from warnings.
Thanks to ikegami for informing about debugger/REPL and its list context.
Related
The difference between arrays and lists and between list and scalar context have been discussed in the Perl community quite a bit this last year (and every year, really). I have read over articles from chromatic and friedo, as well as this recommended monks node. I'm trying now to understand the goatse operator, documented in perlsecret.
Here is some code I used to study it:
# right side gets scalar context, so commas return rightmost item
$string = qw(stuff junk things);
say $string; # things
# right side gets list context, so middle is list assigned in scalar context
$string = () = qw(stuff junk things);
say $string; # 3
# right side gets list context, so creates a list, assigns an item to $string2, and
# evaluates list in scalar context to assign to $string
$string = ($string2) = qw(stuff junk things);
say $string; # 3
say $string2; # stuff
I think I have come far enough to understand all of the list and scalar context workings. The comma operator in scalar context returns its right side, so the first example simply assigns the last item in the comma expression (without any commas) to $string. In the other examples, the assignment of the comma expression to a list puts it in list context, so a list is created, and lists evaluated in scalar context return their size.
There are 2 parts that I don't understand.
First, lists are supposed to be immutable. This is stressed repeatedly by friedo. I guess that assignment via = from list to list distributes assignments from items in one list to items in the other list, which is why in the second example $string2 gets 'stuff', and why we can unpack #_ via list assignment. However, I don't understand how assignment to (), an empty list, could possibly work. With my current understanding, since lists are immutable, the size of the list would remain 0, and then assigning the size to $stuff in examples 2 and 3 would give it the value 0. Are lists not actually immutable?
Second, I've read numerous times that lists don't actually exist in scalar context. But the explanation of the goatse operator is that it is a list assignment in scalar context. Is this not a counter-example to the statement that lists don't exist in scalar context? Or is something else going on here?
Update: After understanding the answer, I think an extra pair of parentheses helps to conceptualize how it works:
$string = ( () = qw(stuff junk things) );
Inside the parens, the = is an assignment to an 'aggregate', and so is a list assignment operator (which is different from the scalar assignment operator, and which should not be confused with "list context"; list and scalar assignment can happen in either list or scalar context). () does not change in any way. = has a return value in Perl, and the result of the list assignment is assigned to $string via the left =. Assignment to $string gives scalar context to the RHS (everything in the parens), and in scalar context the returned value of the list assignment operator is the number of items in the RHS.
You can put the RHS list assignment into list context instead:
($string) = ( () = qw(stuff junk things) );
According to perlop list assignment in list context returns the list of assigned lvalues, which here is empty since there is nothing to be assigned to in (). So here $string would be undef.
You misunderstand. Lists evaluated in scalar context do not get their size. In fact, it is all but impossible to have a list in scalar context. Here, you have a scalar assignment with two operands, a scalar variable on the left, and a list assignment on the right (given scalar context by the scalar assignment). List assignments in scalar context evaluate to the number of items on the right of the assignment.
So, in:
1 $foo
2 =
3 ()
4 =
5 ('bar')
2, a scalar assignment, gives 1 and 4 scalar context.
4, a list assignment, gives 3 and 5 list context, but nevertheless is itself in scalar context and returns appropriately.
(When = is a list assignment or a scalar assignment is determined purely from the surrounding syntax; if the left operand is a hash, array, hash slice, array slice, or in parentheses, it is a list assignment, otherwise it is a scalar assignment.)
This treatment of list assignments in scalar context makes possible code like:
while ( my ($key, $value) = each %hash ) {
where list-context each is an iterator that returns (in list context) one key and value for each call, and an empty list when done, giving the while a 0 and terminating the loop.
It helps to remember that in Perl, assignment is an expression, and that you should be thinking about the value of the expression (the value of the assignment operator), not "the value of a list".
The value of the expression qw(a b) is ('a', 'b') in list context and 'b' in scalar context, but the value of the expression (() = qw(a b)) is () in list context and 2 in scalar context. The values of (#a = qw(a b)) follow the same pattern. This is because pp_aassign, the list assignment operator, chooses to return a count in scalar context:
else if (gimme == G_SCALAR) {
dTARGET;
SP = firstrelem;
SETi(lastrelem - firstrelem + 1);
}
(pp_hot.c line 1257; line numbers are subject to change, but it's near the end of PP(pp_aassign).)
Then, apart from the value of the assignment operator is the side-effect of the assignment operator. The side-effect of list assignment is to copy values from its right side to its left side. If the right side runs out of values first, the remaining elements of the left side get undef; if the left side runs out of values first, the remaining elements of the right side aren't copied. When given a LHS of (), the list assignment doesn't copy anything anywhere at all. But the value of the assignment itself is still the number of elements in the RHS, as shown by the code snippet.
First, "list" is an ambiguous term. Even the question uses it to refer to two different things. I suspect you might be doing this without realizing it, and that this is a significant part of the cause of your confusion.
I shall use "a list value" to denote what an operator returns in list context. In contrast, "the list operator" refers the operator EXPR,EXPR,EXPR,... also known as "the comma operator"[1].
Second, you should read Scalar vs List Assignment Operator.
I guess that assignment via = from list to list distributes assignments from items in one list to items in the other list, which is why in the second example $string2 gets 'stuff', and why we can unpack #_ via list assignment.
Correct.
I've read numerous times that lists don't actually exist in scalar context.
That wording is very ambiguous. You seem to be talking about list values (which are found in memory), but scalar context only exist in the code (where operators are found).
A list/comma operator can be evaluated in scalar context.
A list value can't be returned in scalar context.
Scalar context is a context in which an operator can be evaluated.
A operator evaluated in scalar context cannot return a list. It must return a scalar. Loosely speaking, you could say a list can't be returned in scalar context.
On the other hand, a list/comma operator can be evaluated in scalar context. e.g. scalar(4,5,6). Every operator can be evaluated in any context (though it's not necessarily useful to do so).
But the explanation of the goatse operator is that it is a list assignment in scalar context.
It includes one, yes.
List values and list assignment operators are two different things. One's a value. The other is a piece of of code.
A list assignment operator, like every other operator, can be evaluated in scalar context. A list assignment operator in scalar context returns the number of scalars returned by its RHS.
So if you evaluate () = qw(a b c) in scalar context, it will return three, since qw() placed three scalars on the stack.
However, I don't understand how assignment to (), an empty list, could possibly work.
Just like the assignment ($x,$y) = qw(stuff junk things) ignores the third element returned by the RHS, () = qw(stuff junk things) ignores all elements returned by the RHS.
With my current understanding, since lists are immutable, the size of the list would remain 0
Saying "the size of the list would remain zero" for ()=qw(a b c) is like saying "the value of the scalar will remain 4" for 4+5.
For starters, there's question of which list you're talking about. The LHS returned one, the RHS returned one, and the assignment operator might return one.
The list value returned by the LHS will be 0 in length.
The list value returned by the RHS will be 3 in length.
In scalar context, the list assignment operator returns the number of scalars returned by RHS (3).
In list context, the list assignment operator returns the scalars returned by LHS as lvalues (empty list).
lists are supposed to be immutable.
If you're thinking in terms of list mutability, you took a wrong turn somewhere.[2]
Notes:
The docs call EXPR,EXPR,EXPR,... two instances of a binary operator, but it's easier to understand as a single N-ary operator, and it's actually implemented as a single N-ary operator. Even in scalar context.
It's not actually true, but let's not go any further down this wrong turn.
I'm new here. After reading through how to ask and format, I hope this will be an OK question. I'm not very skilled in perl, but it is the programming language what I known most.
I trying apply Perl to real life but I didn't get an great understanding - especially not from my wife. I tell her that:
if she didn't bring to me 3 beers in the evening, that means I got zero (or nothing) beers.
As you probably guessed, without much success. :(
Now factually. From perlop:
Unary "!" performs logical negation, that is, "not".
Languages, what have boolean types (what can have only two "values") is OK:
if it is not the one value -> must be the another one.
so naturally:
!true -> false
!false -> true
But perl doesn't have boolean variables - have only a truth system, whrere everything is not 0, '0' undef, '' is TRUE. Problem comes, when applying logical negation to an not logical value e.g. numbers.
E.g. If some number IS NOT 3, thats mean it IS ZERO or empty, instead of the real life meaning, where if something is NOT 3, mean it can be anything but 3 (e.g. zero too).
So the next code:
use 5.014;
use Strictures;
my $not_3beers = !3;
say defined($not_3beers) ? "defined, value>$not_3beers<" : "undefined";
say $not_3beers ? "TRUE" : "FALSE";
my $not_4beers = !4;
printf qq{What is not 3 nor 4 mean: They're same value: %d!\n}, $not_3beers if( $not_3beers == $not_4beers );
say qq(What is not 3 nor 4 mean: #{[ $not_3beers ? "some bears" : "no bears" ]}!) if( $not_3beers eq $not_4beers );
say ' $not_3beers>', $not_3beers, "<";
say '-$not_3beers>', -$not_3beers, "<";
say '+$not_3beers>', -$not_3beers, "<";
prints:
defined, value><
FALSE
What is not 3 nor 4 mean: They're same value: 0!
What is not 3 nor 4 mean: no bears!
$not_3beers><
-$not_3beers>0<
+$not_3beers>0<
Moreover:
perl -E 'say !!4'
what is not not 4 IS 1, instead of 4!
The above statements with wife are "false" (mean 0) :), but really trying teach my son Perl and he, after a while, asked my wife: why, if something is not 3 mean it is 0 ? .
So the questions are:
how to explain this to my son
why perl has this design, so why !0 is everytime 1
Is here something "behind" what requires than !0 is not any random number, but 0.
as I already said, I don't know well other languages - in every language is !3 == 0?
I think you are focussing to much on negation and too little on what Perl booleans mean.
Historical/Implementation Perspective
What is truth? The detection of a higher voltage that x Volts.
On a higher abstraction level: If this bit here is set.
The abstraction of a sequence of bits can be considered an integer. Is this integer false? Yes, if no bit is set, i.e. the integer is zero.
A hardware-oriented language will likely use this definition of truth, e.g. C, and all C descendants incl Perl.
The negation of 0 could be bitwise negation—all bits are flipped to 1—, or we just set the last bit to 1. The results would usually be decoded as integers -1 and 1 respectively, but the latter is more energy efficient.
Pragmatic Perspective
It is convenient to think of all numbers but zero as true when we deal with counts:
my $wordcount = ...;
if ($wordcount) {
say "We found $wordcount words";
} else {
say "There were no words";
}
or
say "The array is empty" unless #array; # notice scalar context
A pragmatic language like Perl will likely consider zero to be false.
Mathematical Perspective
There is no reason for any number to be false, every number is a well-defined entity. Truth or falseness emerges solely through predicates, expressions which can be true or false. Only this truth value can be negated. E.g.
¬(x ≤ y) where x = 2, y = 3
is false. Many languages which have a strong foundation in maths won't consider anything false but a special false value. In Lisps, '() or nil is usually false, but 0 will usually be true. That is, a value is only true if it is not nil!
In such mathematical languages, !3 == 0 is likely a type error.
Re: Beers
Beers are good. Any number of beers are good, as long as you have one:
my $beers = ...;
if (not $beers) {
say "Another one!";
} else {
say "Aaah, this is good.";
}
Boolification of a beer-counting variable just tells us if you have any beers. Consider !! to be a boolification operator:
my $enough_beer = !! $beers;
The boolification doesn't concern itself with the exact amount. But maybe any number ≥ 3 is good. Then:
my $enough_beer = ($beers >= 3);
The negation is not enough beer:
my $not_enough_beer = not($beers >= 3);
or
my $not_enough_beer = not $beers;
fetch_beer() if $not_enough_beer;
Sets
A Perl scalar does not symbolize a whole universe of things. Especially, not 3 is not the set of all entities that are not three. Is the expression 3 a truthy value? Yes. Therefore, not 3 is a falsey value.
The suggested behaviour of 4 == not 3 to be true is likely undesirable: 4 and “all things that are not three” are not equal, the four is just one of many things that are not three. We should write it correctly:
4 != 3 # four is not equal to three
or
not( 4 == 3 ) # the same
It might help to think of ! and not as logical-negation-of, but not as except.
How to teach
It might be worth introducing mathematical predicates: expressions which can be true or false. If we only ever “create” truthness by explicit tests, e.g. length($str) > 0, then your issues don't arise. We can name the results: my $predicate = (1 < 2), but we can decide to never print them out, instead: print $predicate ? "True" : "False". This sidesteps the problem of considering special representations of true or false.
Considering values to be true/false directly would then only be a shortcut, e.g. foo if $x can considered to be a shortcut for
foo if defined $x and length($x) > 0 and $x != 0;
Perl is all about shortcuts.
Teaching these shortcuts, and the various contexts of perl and where they turn up (numeric/string/boolean operators) could be helpful.
List Context
Even-sized List Context
Scalar Context
Numeric Context
String Context
Boolean Context
Void Context
as I already said, I don't know well other languages - in every language is !3 == 0?
Yes. In C (and thus C++), it's the same.
void main() {
int i = 3;
int n = !i;
int nn = !n;
printf("!3=%i ; !!3=%i\n", n, nn);
}
Prints (see http://codepad.org/vOkOWcbU )
!3=0 ; !!3=1
how to explain this to my son
Very simple. !3 means "opposite of some non-false value, which is of course false". This is called "context" - in a Boolean context imposed by negation operator, "3" is NOT a number, it's a statement of true/false.
The result is also not a "zero" but merely something that's convenient Perl representation of false - which turns into a zero if used in a numeric context (but an empty string if used in a string context - see the difference between 0 + !3 and !3 . "a")
The Boolean context is just a special kind of scalar context where no conversion to a string or a number is ever performed. (perldoc perldata)
why perl has this design, so why !0 is everytime 1
See above. Among other likely reasons (though I don't know if that was Larry's main reason), C has the same logic and Perl took a lot of its syntax and ideas from C.
For a VERY good underlying technical detail, see the answers here: " What do Perl functions that return Boolean actually return " and here: " Why does Perl use the empty string to represent the boolean false value? "
Is here something "behind" what requires than !0 is not any random number, but 0.
Nothing aside from simplicity of implementation. It's easier to produce a "1" than a random number.
if you're asking a different question of "why is it 1 instead of the original # that was negated to get 0", the answer to that is simple - by the time Perl interpreter gets to negate that zero, it no longer knows/remembers that zero was a result of "!3" as opposed to some other expression that resulted in a value of zero/false.
If you want to test that a number is not 3, then use this:
my_variable != 3;
Using the syntax !3, since ! is a boolean operator, first converts 3 into a boolean (even though perl may not have an official boolean type, it still works this way), which, since it is non-zero, means it gets converted to the equivalent of true. Then, !true yields false, which, when converted back to an integer context, gives 0. Continuing with that logic shows how !!3 converts 3 to true, which then is inverted to false, inverted again back to true, and if this value is used in an integer context, gets converted to 1. This is true of most modern programming languages (although maybe not some of the more logic-centered ones), although the exact syntax may vary some depending on the language...
Logically negating a false value requires some value be chosen to represent the resulting true value. "1" is as good a choice as any. I would say it is not important which value is returned (or conversely, it is important that you not rely on any particular true value being returned).
I read about scalars arrays and list. I am not sure what is meant by list. For example, (5, apple, $x, 3.14) is a list, but what is the variable actually referencing the list?
Are lists just a way to initialize arrays or is it the known data structure?
How do you reference a list in Perl?
The same as you do with anything else - with the reference operator \. See perlreftut and perlref.
my $x;
\(5, 'apple', $x, 3.14)
The expression returns
(
\ 5,
\ "apple",
\ undef,
\ 3.14
)
which is not that useful.
For example, (5, apple, $x, 3.14) is a list, but what is the variable actually referencing the list?
There is none. It is an anonymous value.
Not every value needs a variable to hold it - literals are also an important part of programs.
Are lists just a way to initialize arrays or is it the known data structure?
Read Perl array vs list.
There are three different basic data structures in Perl.
Hashes: These are key/value pairs.
Arrays: These are ordered values.
Scalars: This is a single value.
Hashes:
my %employee = (
"A001" => "Albert",
"A002" => "Bob",
"B003" => "Gary",
);
print "$employee{A001}\n"; #Prints "Albert"
print "$employee{B003}\n"; #Prints "Gary"
Arrays:
my #fruit = ("Apple", "Orange", "Banana");
print "$fruit[0]\n"; #Prints "Apple"
print "$fruit[2]\n"; #Prints "Banana"
Scalars:
my $age = "None of your business";
print "You're $age years old\n"; #Prints "You're None of your business years old
A List is merely a list of items. For example, #fruit is an array. However, I set my array to equal a list containing the names of fruits.
Technically, a list is unchangeable while an array is a data structure that can be modified.
for my $color ("red", "green", "blue") {
print "$color is an item from my list\n";
}
In the above, my for loop advances through a list:
my #list = ("red", "green", "blue");
for my $color (#list) {
print "$color is a member of my array\n";
}
The above is pretty much the same code, but now my for loop advances through an array.
On a really basic level I think understanding what an operator is helps.
This can be summed up by saying anything which is not a value, is an operator.
What is the list operator?
,
How does the list operator work?
The list operator evaluates the value on the left, then evaluates the value on the right. If the value on the right of itself also has a list operator, the associativity of the operator means the evaluations will continue until no more list operators appear or end of line.
#!usr/bin/perl
use warnings;
use strict;
my #namedlist = 1, my #namedlist2 = 2;
print #namedlist , #namedlist2;
12
Once you understand the list operator, you can then deal with the real issue of your problem:
context
For example, print supplies list context to its arguments. It expects a list, not a singular value, so it supplies the list context.
Now we know that the [], and {} operators, are the reference to an anonymous array constructor, and reference to anonymous hash constructor respectively, but I think few realise that before these there was only the list constructor operator. The list constructor operator is
()
Why does this matter? Well, because the list operator , does not know about context. It just evaluates and discards, evaluates and discards.
Supply the context by wrapping a list operator with a list constructor (), and now the list constructor captures the evaluations of the list operator so that it can return a list.
Of course you will be using the assignment operator = to assign the newly constructed list returned by the list constructor (), to a named list holder. Such as an array or a hash.
my #list = (one, 1, two, 2);
my %associatedlist = (three, 3, four, 4);
So a list is a series of evaluated values captured by the list constructor, and then usually assigned into a named list holder.
This is apparent through the reverse engineering of the reference to list constructors, [] and {}.
There being a difference between the two reference to list constructors, highlights their use as operators, perhaps descending from earlier usage of a similar operator?
The reference to list constructers, must be explicitly stated through the use of either the reference to the anonymous array constructor [], or reference to the anonymous hash constructor {}.
The list constructer () is constructing a list of values which are then generally assigned to either a named array or named associated array. Though the assignment operator = does not distinguish between its leftvalue and rightvalue, it just attempts to assign the right to the left, if the contexts are incompatible or the list sizes are of differing lengths, it then proceeds to compliment your handiwork to STDOUT accordingly.
useless use of constant in void context at roughly 1 foot from keyboard.pl
The Perl defined function (and many others) returns "a Boolean value".
Given Perl doesn't actually have a Boolean type (and uses values like 1 for true, and 0 or undef for false) does the Perl language specify exactly what is returned for a Boolean values? For example, would defined(undef) return 0 or undef, and is it subject to change?
In almost all cases (i.e. unless there's a reason to do otherwise), Perl returns one of two statically allocated scalars: &PL_sv_yes (for true) and &PL_sv_no (for false). This is them in detail:
>perl -MDevel::Peek -e"Dump 1==1"
SV = PVNV(0x749be4) at 0x3180b8
REFCNT = 2147483644
FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
IV = 1
NV = 1
PV = 0x742dfc "1"\0
CUR = 1
LEN = 12
>perl -MDevel::Peek -e"Dump 1==0"
SV = PVNV(0x7e9bcc) at 0x4980a8
REFCNT = 2147483647
FLAGS = (PADTMP,IOK,NOK,POK,READONLY,pIOK,pNOK,pPOK)
IV = 0
NV = 0
PV = 0x7e3f0c ""\0
CUR = 0
LEN = 12
yes is a triple var (IOK, NOK and POK). It contains a signed integer (IV) equal to 1, a floating point number (NV) equal to 1, and a string (PV) equal to 1.
no is also a triple var (IOK, NOK and POK). It contains a signed integer (IV) equal to 0, a floating point number (NV) equal to 0, and an empty string (PV). This means it stringifies to the empty string, and it numifies to 0. It is neither equivalent to an empty string
>perl -wE"say 0+(1==0);"
0
>perl -wE"say 0+'';"
Argument "" isn't numeric in addition (+) at -e line 1.
0
nor to 0
>perl -wE"say ''.(1==0);"
>perl -wE"say ''.0;"
0
There's no guarantee that this will always remain the case. And there's no reason to rely on this. If you need specific values, you can use something like
my $formatted = $result ? '1' : '0';
They return a special false value that is "" in string context but 0 in numeric context (without a non-numeric warning). The true value isn't so special, since it's 1 in either context. defined() does not return undef.
(You can create similar values yourself with e.g. Scalar::Util::dualvar(0,"").)
Since that's the official man page I'd say that its exact return value is not specified. If the Perl documentation talks about a Boolean value then then it almost always talks about evaluating said value in a Boolean context: if (defined ...) or print while <> etc. In such contexts several values evaluate to a false: 0, undef, "" (empty strings), even strings equalling "0".
All other values evaluate to true in a Boolean context, including the infamous example "0 but true".
As the documentation is that vague I would not ever rely on defined() returning any specific value for the undefined case. However, you'll always be OK if you simply use defined() in a Boolean context without comparing it to a specific value.
OK: print "yes\n" if defined($var)
Not portable/future proof: print "yes\n" if defined($var) eq '' or something similar
It probably won't ever change, but perl does not specify the exact boolean value that defined(...) returns.
When using Boolean values good code should not depend on the actual value used for true and false.
Example:
# not so great code:
my $bool = 0; #
...
if (some condition) {
$bool = 1;
}
if ($bool == 1) { ... }
# better code:
my $bool; # default value is undef which is false
$bool = some condition;
if ($bool) { ... }
99.9% of the time there is no reason to care about the value used for the boolean.
That said, there are some cases when it is better to use an explicit 0 or 1 instead of the boolean-ness of a value. Example:
sub foo {
my $object = shift;
...
my $bool = $object;
...
return $bool;
}
the intent being that foo() is called with either a reference or undef and should return false if $object is not defined. The problem is that if $object is defined foo() will return the object itself and thus create another reference to the object, and this may interfere with its garbage collection. So here it would be better to use an explicit boolean value here, i.e.:
my $bool = $object ? 1 : 0;
So be careful about using a reference itself to represent its truthiness (i.e. its defined-ness) because of the potential for creating unwanted references to the reference.
How do I define a secondary ordering to the Heap::Simple interface in Perl?
The documentation states that the constructor takes a code reference to define
the order, so you can specify any sort method you like:
my $heap = Heap::Simple->new(order => \&sort_method);
Every time two keys need to be compared, the given code reference will be called like:
$less = $code_reference->($key1, $key2);
This should return a true value if $key1 is smaller than $key2 and a false
value otherwise. $code_reference should imply a total order relation, so it
needs to be transitive.
By "secondary ordering" I assume you mean that a second comparison is used if
the first one shows the values to be equal. Let's say the first comparison is
of values found via the "method1" method, and the second comparison is of
values from "method2". So, if by method1 the values are different, return
that result, and otherwise fall back to method2:
sub sort_method
{
my ($val1, $val2) = #_;
my $result = ($val1->method1 <=> $val2->method1)
||
($val1->method2 <=> $val2->method2);
return 1 if $result == -1;
}
If method1 and method2 return strings instead of numeric values, simply use
the cmp operator instead of <=>. You can use anything you like, as long
as the operator returns the right values. Most sort functions like using the
values -1, 0 and 1 to indicate whether value1 is less than, equal to, or
greater than value2, but this module likes 1 to mean val1 < val2, so after
gathering the -1, 0, 1 result, one then returns 1 if the result is -1 (where
value1 is less than value2).
First of all, you write a function that takes two of the objects you want to put in the heap, and returns a true value if the first one is smaller than the second, and false otherwise.
Then supply that as a coderef to Heap::Simple.
The example from the Heap::Simple docs is as follows:
use Heap::Simple;
sub more { return $_[0] > $_[1] }
my $heap = Heap::Simple->new(order => \&more);
$heap->insert(8, 3, 14, -1, 3);
print $heap->extract_top, " " for 1..$heap->count;
print "\n";
# Will print: 14 8 3 3 -1