in reply to Re^2: Can you spot the problem?
in thread Can you spot the problem?

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

Replies are listed 'Best First'.
Re^2: Can you spot the problem?
by adrianh (Chancellor) on Mar 07, 2004 at 17:37 UTC
    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.

      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
        Whoah, hold on. Where on earth did you get the idea that bitwise operations are numerical operations? They're not.

        I meant numerical as in takes a number as an argument (123) as opposed to a string ("123"). I thought this was obvious from the context.

        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.

        Which is exactly my point :-) Random breakage is exactly what the current | operator's behaviour causes, just from the other side. Numerical bit based operations and string based bit operations are equally useful - but munging them together in one operator is asking for trouble in a language that transparently translates between numbers and strings in most contexts.

        But you absolutely don't want to just make the bitwise operators that we have in Perl5 magically numerify their arguments.

        I agree completely. I don't think I ever suggested it. However what we have now is just as bad since Perl programmers are used to strings containing numbers acting like numbers.