Re: This is why Perl is so frustrating
by FunkyMonk (Bishop) on Jul 29, 2009 at 18:07 UTC
|
AM I MISSING A FUNDAMENTAL ASPECT OF LOGICAL OPERATIONS
yes :-(
($file ne ".") or ($file ne "..")
is always true. You want to process file when it's not-equal to '.' AND not-equal to '..':
($file ne ".") && ($file ne "..")
| [reply] [d/l] [select] |
|
|
| [reply] |
Re: This is why Perl is so frustrating
by MidLifeXis (Monsignor) on Jul 29, 2009 at 18:04 UTC
|
Assume that $file eq '.'
| (($file ne ".") or ($file ne "..")) |
| (('.' ne ".") or ('.' ne "..")) |
| ((FALSE) or (TRUE)) |
$file eq '..' is left as an exercise for the reader.
In general, if you have ((X <> A) || (X <> B)) (unless you have a dualstate quantum variable of some sort), you will end up with (TRUE || FALSE), (FALSE || TRUE), or (TRUE || TRUE), all of which reduce to TRUE.
Update: You may also want to see -X to test if a directory entry is actually a file that you can open.
--MidLifeXis
The tomes, scrolls etc are dusty because they reside in a dusty old house, not because they're unused. --hangon in this post
| [reply] [d/l] [select] |
Re: This is why logic is so frustrating (was This is why Perl is so frustrating)
by ELISHEVA (Prior) on Jul 29, 2009 at 18:11 UTC
|
If you wish to verify that "x" is neither one of two possibilities, then you have to verify that "x" is not "." and "x" is not "..". so ... what you want is
if (($file ne ".") and ($file ne "..")) { ...
Best, beth
| [reply] [d/l] |
|
|
Yes, I remember this all from school and my c programming days. True or False is always true unelss the bit flips due to cosmic background radiation or the butterfly effect:
http://xkcd.com/378/
| [reply] |
|
|
if ($x && !$x) {...}
was evaluating to true, two or three times per hour. | [reply] [d/l] |
Re: This is why Perl is so frustrating
by GrandFather (Saint) on Jul 29, 2009 at 20:51 UTC
|
for my $file (@filenames) {
next if $file =~ /^\.\.?$/;
...
}
note too the early 'exit' from the current loop iteration to avoid a level of nesting and make flow clearer.
True laziness is hard work
| [reply] [d/l] |
|
|
$file =~ /^\.\.?$/
Or $file =~ /^\.{1,2}$/ (which is easier to extend later if one decides also to treat ... and friends specially! :-) ).
| [reply] [d/l] [select] |
Re: This is why Perl is so frustrating
by jrsimmon (Hermit) on Jul 29, 2009 at 18:09 UTC
|
if (($file ne ".") or ($file ne ".."))
Will always be true, because no single value of $file can ever match both "." and "..". So yes, you are missing a fundamental aspect of logical operations.
Namely: For a given A != B, (!A or !B) == !(A && B), which will always be true for any single value.
Update:
Perhaps you should spend some time reading this article.
| [reply] [d/l] [select] |
|
|
Namely: For a given A != B, (!A or !B) == !(A && B), which will always be true for any single value.
ow.
You attached two conditions to (!A or !B) == !(A && B), but it's always true.
You refer some non-existent "single value" because you meant to talk about (V != A) or (V != B).
I believe you meant:
(A or B)
is equivalent to
!(!A and !B)
Because of that,
(V != A) or (V != B)
is equivalent to
!( (V == A) and (V == B) )
If A != B, the "and" is obviously false (since V can't have two different values at the same time), and the whole statement is therefore true. | [reply] [d/l] [select] |
|
|
Yeah, I changed which side of the statement I was adding the A != B qualifier, didn't clean it up well. Thanks for clarifying it.
| [reply] |
Re: This is why Perl is so frustrating
by toolic (Bishop) on Jul 29, 2009 at 18:08 UTC
|
Could you elaborate on your problem? If you are trying to avoid the special directories named '.' and '..', don't you want the 'and' logical operator instead of 'or'?
Keep in mind that readdir returns both files and all sub-directories, not just the specially-named ones. If you want to filter out all
directories, you can use -X. | [reply] |
Re: This is why Perl is so frustrating
by jdporter (Paladin) on Jul 29, 2009 at 18:15 UTC
|
substr outside of string at lane_changer.pl line 33.
I don't see $position, $length, $value being defined. Do you have use strict; use warnings; at the top of your program?
Even if those variables are defined somewhere in code you didn't show, it's hardly surprising that you'd get that error,
since they haven't been set to values corresponding to the length of the current $line.
Between the mind which plans and the hands which build, there must be a mediator... and this mediator must be the heart.
| [reply] [d/l] [select] |
Re: This is why Perl is so frustrating
by VinsWorldcom (Prior) on Jul 29, 2009 at 18:16 UTC
|
I'm not sure what you're trying to do - I'm guessing you want to skip the directories '.' and '..'. Assuming that, then I think you are "MISSING A FUNDAMENTAL ASPECT OF LOGICAL OPERATIONS".
You need to 'and', not 'or'. The way it's written (or), first time through, $file = '.', which makes the first half of the if statement false. However, $file = '.', so it can't equal '..', which makes the second part of the if statement true ($file ne '..' <==, yes, that's correct, because $file = '.'). Now you OR 1 and 0 and get a true condition; thus execute the if statement. | [reply] |
Re: This is why Perl is so frustrating
by talexb (Chancellor) on Jul 29, 2009 at 20:48 UTC
|
if (($file ne ".") or ($file ne "..")) {
with the more elegant
unless ( $file eq "." || $file eq ".." ) {
because it reads more naturally. In fact, since parsing the file is the only thing that's happening inside the loop, I would just skip the file entirely with
next if ( $file eq "." || $file eq ".." );
There might be responses to my post for calls to make a regular expression out of this, but it's not really necessary.
Alex / talexb / Toronto
"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds
| [reply] [d/l] [select] |
|
|
unless ($expression){
# do something
}
is never elegant. I'll always plump for
if (not $expression){
# do something
}
especially if, as in this case $expression includes some boolean arithmetic. I do use it for early exits from loops though. I can read
while (<$fh>){
next unless /\S/;
#
}
without too much trouble (as long as it's simple).
As soon as an expression has a not an and and an or in it I'm almost sure to get it wrong and it often points to a poor algorithm which some refactoring can fix. Either that or put it into sub so I can say
if (work_to_do($args)){
# do some work
}
and test the living daylights out of it.
Did I mention I've had awful trouble with boolean arithmetic? :-)
| [reply] [d/l] [select] |
|
|
if ( !$boolean1 and !$boolean2 ) {
harder to read, and therefore more difficult to comprehend, than
unless ( $boolean1 or $boolean2 ) {
I make this distinction because the original code was checking *two* conditions, not just one. I will agree that it's a saw-off when comparing
if ( !$boolean ) {
and
unless ( $boolean ) {
But for me, if I miss the tiny '!' character, then I have the logic backwards, which is a huge problem. I'm not going to miss the 'unless'.
Alex / talexb / Toronto
"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds
| [reply] [d/l] [select] |
Re: This is why Perl is so frustrating
by jwkrahn (Abbot) on Jul 29, 2009 at 19:49 UTC
|
You are also missing a couple of fundamental aspects of readdir. In order to get a file name readdir queries the file system and what returns is an actual file name with no newline or anything else added to it so using chomp is at best superfluous and at worst will damage the actual file name. And if you want to open a file with that name you have to remember that it is in $testdir and not the current directory like you seem to think it is.
| [reply] [d/l] |
Re: This is why Perl is so frustrating
by Marshall (Canon) on Jul 30, 2009 at 11:31 UTC
|
When you open a directory and read it, you get all the files in it. As you
see "." and ".." are files in every directory. A directory
is a file, so it could be that there are other sub-directories in your
test directory.
opendir(DIRHANDLE, $testdir) or die "couldn't open directory: $testdir
+";
@filenames = grep {-f "$testdir/$_"} readdir(DIRHANDLE);
closedir(DIRHANDLE);
What the grep addition does is filter the ouput of readdir so that
@filenames only winds up with filenames that are "normal files",
ie, not directories. Meaning that "." and ".." and any other sub-dirs
are excluded from the list! ergo, no need for the logic test on ne "."
and ".."! Of course you already see that the filenames are just the raw
names and the dir path needs to be prepended when you use those names, even in
this grep.
Perl grep is way cool and is often used to filter lists. If the last
statement in the grep evaluates to "true" the input on right is passed
to output on left.
another point: no need to use . concatenation op in many string cases. Perl
will interpolate a $var inside of double quotes (like die statement above) and
-f "$testdir/$_", the quotes are needed otherwise Perl would think that this is a division.
| [reply] [d/l] |
Re: This is why Perl is so frustrating
by eggmatters (Initiate) on Jul 29, 2009 at 18:09 UTC
|
"AM I MISSING A FUNDAMENTAL ASPECT OF LOGICAL OPERATIONS?"
Apparently, this happens:
$file = "."
if ($file ne "." ) (evaluates to true) or ($file ne "..") (evaluates to false)
false or true = true?
I thought that was &&
| [reply] |
|
|
Yes I got it backwards. Argghhh. Now I am eating some crow. Just so you know, we're under a massive heatwave and I have very little sleep with a newborn. This all makes me cranky and irritable and dyslexic and dumb. Sorry but Thanks for the prompt and helpful replies!! Perl is ok again!!
| [reply] |
|
|
| [reply] |
|
|
That would be the fundamental aspect of logical operations which you have missed.
(A||B) evaluates to true if either A or B are true.
(A&&B) evaluates to true if and only if (iff) A and B are both true.
| [reply] |