So, to me, boolean logic makes complete sense in this particular domain.
Boolean logic is a natural way to solve the problem.
A recursive or iterative solution would also be
natural. The OP however instead attempted to
combine the individual bits of the four parts of the
address (only, they didn't combine quite the way he
expected). I'd wager that the person who wrote
this code has spent significant time working with
a relatively low-level third-generation language such
as C. (Especially, since it came off a non-Perl
mailing list originally, but you can tell also from
the style of the code.)
The problem for me is that you get bitten by Perl's DWIMary. In Perl you're trained think that Perl will do the "right thing" when given things that look like numbers.
Yeah, but in Perl you're not trained to write code like
that. The code in question looks distinctly like it
was written by a C programmer. (C programmers play
weird tricks with bitwise operations all the time.)
There are much more Perlish ways to solve the problem,
not least of which is to use Regex::Common.
I stand by my statement that in some respects I agree
with the poster who said the code doesn't make sense;
particularly, it may not make immediate sense to a
Perl programmer with little background in C (and
languages like C).
I can completely see your point of
view, and it's nothing I'd start a religious war
over, but I do think it's arguable.
It does depend on your perspective. I suppose the
guy who wrote the code thought it made sense. (Of
course, he also thought it would work...) But I
don't think it's surprising that to flyingmoose,
a Perl programmer, it didn't make sense. And, in
a way, he's right. After three readings I understood
why the author thought the code would work, but on
the other hand, fundamentally he's using a bitwise
operation to accomplish a logical operation. That
is, he's doing bitwise-or of four numbers together in
order to figure out whether all of them (logical and)
meet a certain condition. Assuming for the moment
that we apply tye's two-stroke fix that makes the
code work as intended, it still only works because of
certain bit-related properties of the numbers in
question (centering around the fact that 256 is a
power of 2). You can see why someone might view
this as unintuitive.
As far as an IP address being under the hood a single
four-byte number, if the code used pack/unpack or
something to convert the four numbers into a single
four-byte number, or a hex representation, and then
operated on that, I would consider that a (not the,
but a) natural solution. In fact, for certain more
complex IP-address calculations, especially having
to do with network masks, that might even be _the_
natural solution. But the code in question doesn't
treat the IP address as a four-byte number; it
doesn't really do anything even _similar_ to treating
it as a four-byte number. If anything, it tries to
treat it as N sets of four bits, and checks to see
whether N is more than 8. That's a completely
different approach from treating it as a single
32-bit number.
So, in conclusion, flyingmoose is not smoking crack
(or, at least, if he is, you can't tell that from
the node in question).
;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
| [reply] |
Assuming for the moment that we apply tye's two-stroke fix that makes the code work as intended, it still only works because of certain bit-related properties of the numbers in question (centering around the fact that 256 is a power of 2).
In this particular domain each number should be a single byte. The bit related property isn't arbitrary or coincidental - it's the very essence of the thing we're testing for. To me it's an obvious property that or-ing them together should result in a number less than 256. To others it may not be.
You can see why someone might view this as unintuitive.
Of course. It's a completely reasonably attitude. Just not a universal one.
To others, myself included, using a bitwise numerical or is a completely intuitive solution. Whether somebody find it obvious or not is going to be dependent on their experience.
I too would use Regexp::Common, but only because I loathe reinventing wheels. Are the regexpes that Regexp::Common::net uses internally any more or less "intuitive" that the other solutions offered? This, of course, depends on how familiar you are with Perl's regular expressions. It also depends on the domain you're playing with.
I still think the real problem is with the behaviour of the | operator in Perl. This is one of the very few places where the difference between a string containing a number and a number makes a real difference.
With all the other numerical operations numbers and strings containing numbers are treated the same way. It's only the bitwise operators that are treated differently. This, in my opinion, was a poor design choice and doesn't fit in with the way the rest of Perl is organised (eq vs ==, . vs +, etc.) I imagine this is one of the reasons the numerical and string bitwise operators are being separated out in Perl 6.
For example, the difference between the bitwise string and numerical operators has caught me out when I was manipulating preference values that were being represented as bit masks. Comparing different preferences sometimes worked and sometimes didn't, depending on whether preferences got injected into the system as strings or numbers. Since the injection of values happened a long way from the comparisons it took a heck of a long time to figure out what was going on.
(For those about to chime in and say bitmasks were a poor choice for preference values - I quite agree. We were manipulating values from a third party application.)
So, in conclusion, flyingmoose is not smoking crack (or, at least, if he is, you can't tell that from the node in question).
I never accused anybody of smoking crack.
Ignoring the reinventing the wheel issue, and just comparing the bitwise and comparison solutions, on some days I might even agree that the comparison solution was a better design choice.
However I do disagree that the original solution "does something that doesn't even make sense". It makes perfect sense - it's just that Perl in this particular instance does something that most developers wouldn't expect.
| [reply] [d/l] [select] |
I still think the real problem is with the behaviour of the | operator in Perl. This is one of the very few places where the difference between a string containing a number and a number makes a real difference. With all the other numerical operations
Whoah, hold on. Where on earth did you get the idea
that bitwise operations are numerical operations?
They're not. Bitwise operations operate in an
arithmetic fashion, yes, but they operate on sequences
of bits; what the arrangement of the bits represents
is not a key feature of the bitwise operation, and it
is not reasonable to assume that they necessarily
represent numbers. Often (perhaps even usually) they
represent characters, either in ASCII or unicode.
Doing a bitwise operation in strings (especially XOR
or a left or right shift, but sometimes and and or an
or) is quite a common operation, one that we would
*not* want to have randomly break if one of the strings
happens to contain digit characters by some coincidence.
Sure, if you have separate bitwise operators for
working on strings versus numbers, that would be fine.
In Perl6, that will work out, no problem.
But you absolutely don't want to just make the bitwise
operators that we have in Perl5 magically numerify
their arguments. That would be exceedingly bad.
That seems to be what the person who wrote the code
expected to have happen; where he came up with such
an absurd idea is quite beyond me. Like I said,
it took me three readings to figure out why the
author expected it to work. Why it didn't work was
somewhat more obvious. Figuring out why
the author expected it to work took more time,
significantly more time, than subsequently figuring
out why his expectations were broken.
;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
| [reply] |