What's wrong with this Perl boolean syntax? - perl

I have hack I need to employ under these conditions:
It's the last page of data.
It's not the first page, either.
There's not a page-size-even number of data items.
So I tried this code:
my $use_hack =
$last_page_number == $current_page_number and
$page_number != 1 and
$total_items % $items_per_page != 0;
And I keep getting this warning Useless use of numeric ne (!=) in void context about the last condition and it's evaluating true when $total_items % $items_per_page = 0.
say 'NOT EVEN' if $total_items % $items_per_page != 0; #works properly, though...
I've tried various combinations of parentheses to get it right, but nothing seems to work.

Okay, operator precedence. and has almost the lowest precedence of any operator in Perl, so Perl was evaluating the expression in a weird order. Switching to && instead got me correct results. Blarg.
The More You Know.
EDIT:
As Philip Potter pointed out below, Perl Best Practices (p.70) recommends always using &&,||, ! for boolean conditions - limiting and or and not for control flow because of their low precedence. (And it even goes so far as to say to never use and and not, only or for fallback logic.)
Thanks, everybody!

Enclose the RHS in parenthesis:
my $use_hack = (
$last_page_number == $current_page_number and
$page_number != 1 and
$total_items % $items_per_page != 0);
Assignment (=) is having higher precedence when compared to and operator. You can take a look at the Perl Operator Precedence.

Related

Comparing Multiple File Types in an if Statement

I am importing a file into a function using [filepath, name, ext]=fileparts(thisFile);. I would then like to use a series of if statements that will operate on the file depending on its type; however, come files will have the same initial set up and so I would like to be able to include them all in an if statement. My current implementation: elseif (ext == '.s3p'). If I put in something like: elseif (ext == '.s2p' || '.s3p') the compiler whines,
Operands to the || and && operators must be convertible to logical scalar values.
You see my logic. Is there anything that I can do to make this work?
Thank you in advance!
You probably want strcmp, not ==. With a==b you get element-wise comparison. So you get a logical vector as result; and if a and b have different number of characters you get an error.
The fact that the output of == is a logical vector of element-wise comparisons is what causes the m-lint message. || and && require scalar arguments.
Lastly, in (ext == '.s2p' || '.s3p') you probably meant (ext == '.s2p' || ext == '.s3p').
Combining all of the above:
elseif strcmp(ext,'.s2p') || strcmp(ext,'.s3p')
For clarity and readability, you may prefer to use the ismember function with a cell array of the extensions to compare with:
elseif ismember(ext, {'.s2p' ,'.s3p'})
or, as pointed out by Cris Luengo,
elseif any(strcmp(ext, {'.s2p', '.s3p'}))
Better yet, instead of a series of elseif statements you may prefer to use switch, which implicitly applies strcmp / ismember for each case:
switch ext
case {'sp2', 'sp3'}
% Do stuff
case {'aaa', 'bbb'}
% Do stuff
otherwise
error('Unrecognized extension')
end

special compare in MATLAB

Hi I'm trying to achieve this:
for i=1:maxaps
for j=1:length(num2)
**if (isequal(sortedCell(i),txt2(j)) && sortedCell(i)~=0)** %important line
rssi2sorted(i)=rssi2(j); %I don't think we need matching part
break;
end
end
end
and I receive this error:
??? Undefined function or method 'ne'
for input arguments of type 'cell'.
Error in ==> sortingmethod at 116
if
(isequal(sortedCell(i),txt2(j))
&& sortedCell(i)~=0)
if I try like this:
for i=1:maxaps
for j=1:length(num2)
**if (isequal(sortedCell{i},txt2(j)) && sortedCell(i)~=0)** %important line
rssi2sorted(i)=rssi2(j); %I don't think we need matching part
break;
end
end
end
the elements can't be compared because of the format:
>> sortedCell{1}
ans =
00:1e:58:f4:15:f7
>> txt2(6)
ans =
'00:1e:58:f4:15:f7'
any recommendations on how to fix this?
Thanks!
I believe that the issue is actually with this part (the ne that your error refers to):
sortedCell(i)~=0
You're comparing a cell, rather than its contents, to zero. You should use:
sortedCell{i}~=0
EDIT:
If the question is not about the error message, but rather how to compare strings, just use strcmp (never use ==, eq, or isequal to compare strings):
if strcmp(sortedCell{i},txt2(j))
...
end
I don't know what the && sortedCell{i}~=0 part you've added is for, but you can add it back if needed.
strcmp also take cell arrays as inputs (see the documentation) so you may be able to get rid of on of your for loops. I don't know what your code does, but maybe you you could use something like this:
for j=1:length(num2)
c = strcmp(sortedCell,txt2(j));
if any(c)
rssi2sorted(c)=rssi2(j);
break;
end
end
use strcmp (of strcmpi ignoring case) to test is strings are the same, isequal is for testing if values are numerically equal. e.g.
if ( strcmp(sortedCell{i},txt2(j)) && sortedCell(i)~=0 )

Perl booleans, negation (and how to explain it)?

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).

How can I assign a boolean condition result to a scalar variable in perl?

I am doing the following, but it is not working properly:
my $enabled = $hash &&
$hash->{'key'} &&
$hash->{'key'}->{'enabled'} &&
$hash->{'key'}->{'active'};
Is this an acceptable way to assign a boolean value to a scalar variable?
My code is misbehaving in strange ways, as it is, and I believe it is because of this assignment. I have validated that the individual values exist for all of these keys and are set to a value.
P.S. Sorry for being a noob! I googled for ~10 minutes and couldn't find the answer anywhere.
The Perl boolean operators like &&, ||, and, or don't return a boolean value, they return the value of one of their arguments:
say 2 && 3;
outputs 3.
You can force it to a boolean with the double negation trick:
say !!(2 && 3);
# or
say not not 2 && 3;
outputs 1.

What's the difference between & and && in MATLAB?

What is the difference between the & and && logical operators in MATLAB?
The single ampersand & is the logical AND operator. The double ampersand && is again a logical AND operator that employs short-circuiting behaviour. Short-circuiting just means the second operand (right hand side) is evaluated only when the result is not fully determined by the first operand (left hand side)
A & B (A and B are evaluated)
A && B (B is only evaluated if A is true)
&& and || take scalar inputs and short-circuit always. | and & take array inputs and short-circuit only in if/while statements. For assignment, the latter do not short-circuit.
See these doc pages for more information.
As already mentioned by others, & is a logical AND operator and && is a short-circuit AND operator. They differ in how the operands are evaluated as well as whether or not they operate on arrays or scalars:
& (AND operator) and | (OR operator) can operate on arrays in an element-wise fashion.
&& and || are short-circuit versions for which the second operand is evaluated only when the result is not fully determined by the first operand. These can only operate on scalars, not arrays.
Both are logical AND operations. The && though, is a "short-circuit" operator. From the MATLAB docs:
They are short-circuit operators in that they evaluate their second operand only when the result is not fully determined by the first operand.
See more here.
& is a logical elementwise operator, while && is a logical short-circuiting operator (which can only operate on scalars).
For example (pardon my syntax).
If..
A = [True True False True]
B = False
A & B = [False False False False]
..or..
B = True
A & B = [True True False True]
For &&, the right operand is only calculated if the left operand is true, and the result is a single boolean value.
x = (b ~= 0) && (a/b > 18.5)
Hope that's clear.
&& and || are short circuit operators operating on scalars. & and | operate on arrays, and use short-circuiting only in the context of if or while loop expressions.
A good rule of thumb when constructing arguments for use in conditional statements (IF, WHILE, etc.) is to always use the &&/|| forms, unless there's a very good reason not to. There are two reasons...
As others have mentioned, the short-circuiting behavior of &&/|| is similar to most C-like languages. That similarity / familiarity is generally considered a point in its favor.
Using the && or || forms forces you to write the full code for deciding your intent for vector arguments. When a = [1 0 0 1] and b = [0 1 0 1], is a&b true or false? I can't remember the rules for MATLAB's &, can you? Most people can't. On the other hand, if you use && or ||, you're FORCED to write the code "in full" to resolve the condition.
Doing this, rather than relying on MATLAB's resolution of vectors in & and |, leads to code that's a little bit more verbose, but a LOT safer and easier to maintain.