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

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.

Replies are listed 'Best First'.
Re: Can you spot the problem?
by jonadab (Parson) on Mar 10, 2004 at 14:17 UTC
    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").

    Right. Where did you get the idea that the bitwise or operator is numerical in this sense? It's not. None of the bitwise operators are. I think this is the crux of the problem, the reason why whoever wrote the code originally (was that you? the OP didn't say who it was) thought it would work: apparently he was under the impression that the bitwise operations are exclusively numeric in nature, imposing a numeric context on their operands. I don't know where he got this notion, but it's wrong; Perl5's bitwise operators are not numeric operators; they also work on strings.

    Random breakage is exactly what the current | operator's behaviour causes

    Perhaps, but...

    However what we have now is just as bad since Perl programmers are used to strings containing numbers acting like numbers.

    No, strings don't act like numbers, normally. Whoever told you that was trying to oversimplify *way* too much (probably trying to avoid explaining context, but context is the most important thing to understand about Perl, so leaving it out of the explanation was misguided and lead you into the misunderstanding we're now sorting out). Strings act like strings, normally.

    The only time strings ever get converted automagically into numbers is in numeric context. Sure, if you use a numeric operator like + they'll get converted, because the numeric operators supply a numeric context to their operands, but that's not at all the same as expecting them to get converted any time you do anything with them in any context at all. The fact that the string "looks" like a number doesn't have a great deal to do with its getting converted, either. In numeric context, the string "George" will get converted to a number (which, as it turns out, will be 0), though this will generate a warning since the conversion isn't "clean". If in any given situation you wouldn't expect "George" to be treated as a number, don't expect "123" to be treated as a number either; it won't be, because it's a string.

    Would you expect "123" to change into 123 if you assigned it to a scalar, tested it with the defined operator, or passed it as an argument to an arbitrary user-defined function? No? Then why did you think it would get changed into a number if you performed a bitwise operation on it? Were you under the impression that the bitwise operators supplied a numeric context to their arguments? They don't, and why would they? We use them on strings at least as much as on numbers. It wouldn't make sense for them to supply numeric context. This is not "random breakage" to my way of thinking; none of the bitwise operators ever impose a numeric context on their arguments, nor should they. If we had a set of bitwise operators that _only_ work on numbers, as is planned in Perl6, then they _would_ impose a numeric context, of course, but Perl5's bitwise operators are not exclusively numeric.

    You know, when I go back and read this thread, it occurs to me that I'm probably coming across as argumentative. I honestly did not intend to be. I was just trying to understand where you were coming from, why you thought the code should work, and what expectations Perl was breaking. (And, meanwhile, if I could help someone understand Perl better, so much the better.) I think I understand now, but it's possible that I've still missed a subtle point or two. Anyway, I think the basic issue is that whoever wrote the code doesn't think in Perl, but thinks in another language and translates to Perl. This is normal; most programmers think in whatever language they know best and translate to other languages. And yes, Perl being what it is needs to be able to work for people who think in another language (more on this next paragraph), so the move to separate numeric bitwise operators in Perl6 is probably an important step (even though it won't matter for people who think in Perl and understand context implicitely). I think I now understand (well, mostly) why this is a useful change. (Before, I was ambivalent about it.) All of that to say, I wasn't just being argumentative; I was also learning something :-)

    As far as Perl's needing to work for people who think in other languages... all languages to some extent have this need, but Perl6 needs it especially, because if we *ever* hope to get all the hundreds of thousands of C programmers out there switched over to a language that supplies things like garbage collection, Perl6 is the best hope. But they won't switch over if the barrier to entry requires them to think in Perl before they can start doing stuff -- and, in fact, this is the thing that originally attracted me to Perl5; I read two chapters of the Camel book and was writing code that not only worked but was _useful_, not some Hello World exercise. So now, having spent the whole thread trying to explain why Perl5 is the way it is, I'm talking about how glad I am that Perl6 will be better.


    ;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print
      Perl5's bitwise operators are not numeric operators; they also work on strings.

      I know they also work on strings. I've been using and teaching Perl for nearly ten years now ;-)

      All I mean by calling it a numerical operator is that if you give it a number you get a bitwise numerical operation. It performs a numerical operation (and a different string operation if you give it a string).

      No, strings don't act like numbers, normally.

      ...

      The only time strings ever get converted automagically into numbers is in numeric context.

      Yes, this is the point I was trying to get across :-) Numerical context is exactly the thing that does make strings containing numbers act like numbers. This is the essence of what causes confusion with these operators for some Perl programmers.

      Perl developers are used to the operator defining whether a scalar is treated as a string or a number. Want to add two numbers together use "+" and Perl will treat them as numbers. Want to combine two scalars use "." and Perl will treat them as strings.

      Operators where numbers and strings would do different things (e.g. equality) are normally given different names (eq and ==).

      This is an excellent piece of design by Larry because it makes the operation completely explicit. You don't have to force a particular context on your scalars. You don't have to know whether they contain a number or a string. Perl just DWIM.

      The bitwise operators are the only place where this doesn't apply. You have two separate bits of functionality - numerical bitwise operations and string bitwise operations - with the same names. The numerical and string bitwise operations are even documented separately in perlop.

      They do exactly the opposite of Perl's other operators. Rather than changing the type of the scalar depending on the function, they change the function depending on the type of the scalar.

      In my opinion this was a mistake. Just like forcing people to disambiguate equality like this:

      0+$foo == $bar # guarantee numerical equality "$foo" == $bar # guarantee string equality $foo == $bar # it depends...

      would be a mistake.

      Perl programmers are used to scalars and operators that DWIM. The bitwise operators often don't without extra work to coerce one of their arguments.

      Then why did you think it would get changed into a number if you performed a bitwise operation on it?

      I don't think that.

      Would you expect "123" to change into 123 if you assigned it to a scalar, tested it with the defined operator, or passed it as an argument to an arbitrary user-defined function? No?

      Of course not.

      Then why did you think it would get changed into a number if you performed a bitwise operation on it?

      I don't.

      Were you under the impression that the bitwise operators supplied a numeric context to their arguments?

      Nope.

      We use them on strings at least as much as on numbers. It wouldn't make sense for them to supply numeric context. This is not "random breakage" to my way of thinking;

      It's not "random breakage" in the sense that the current behaviour is the way the language is defined. However, unless your careful to make all bitwise operations explicitly on numbers or strings, it can lead to code that behaves in radically different ways depending on the scalars it is called with.

      none of the bitwise operators ever impose a numeric context on their arguments, nor should they

      Just to be clear I am not suggesting that the bitwise operations should force a numeric context :-)

      What I am saying is that the decision to have one operator that does two completely different things depending on whether it is given a number or a string goes against the DWIM design of the rest of Perl.

      0+$foo | $bar # guarantee numerical bitwise or "$foo" | $bar # guarantee string bitwise or $foo | $bar # ... it depends

      This can cause confusion and the OP is an instance of this confusion.

      . I was just trying to understand where you were coming from, why you thought the code should work, and what expectations Perl was breaking.

      Ahhh. I think I see the source of confusion. I don't think that the code as written should have worked (it obviously doesn't). However I do think that the code "makes sense". By that I mean that the intent of the developer was clear (assuming you understand bitwise operations).

      The mistake that was made was not realising that you needed to coerce one of the strings into a number to get a numerical bitwise-or rather than a string bitwise-or.

      This may be, as you suggested, because they're used to a language where this would be the only possible interpretation.

      However since I've seen experienced Perl developers make the same sort of mistake (myself included) this can't be the only reason confusion arises.

      The design of Perl encourages you to forget about the difference between strings and numbers because the various operators will DWIM. Unfortunately the bitwise operators are one place where this doesn't happen - and that is another reason why people often make this sort of mistake.

      Hopefully making some vague sort of sense :-)

        The bitwise operators are the only place where this doesn't apply.
        Nope.
        #!/usr/bin/perl -l $_ = "a"; $_ ++; print; $_ == $_; $_ ++; print; __END__ b 1

        Abigail