in reply to Re: Precedence design question...'x' & arith
in thread Precedence design question...'x' & arith

I ask, because it strikes me as one of those things that would be a really bad idea. It's easy to look at //= and know, "Oh, I better be using Perl 5.10 or newer.

And I was just thinking yesterday about how perl made // and operator while in other languages it was the lead-in to a comment and how perl has no syntactic multi-line comment blocks.

But if you saw:

' ' x $a * $b;
You would have to know that for that to work, you'd have to be in perl 5.20 or newer, as it throws an error if you try to multiple a string times an integer.

It's not like you have a choice. You say :

it's really hard to look at an operator and have to worry that code that uses it might break due to precedence changes between Perl versions.
But the fact is you wouldn't. If you had an expression like the above, it would be broken and not work pre-pV20 (or whatever). If you are using such a construct in your current perl -- my question was how are you doing it? Could you give some examples of how you use the current behavior to produce useful code?

Replies are listed 'Best First'.
Re^3: Precedence design question...'x' & arith
by ww (Archbishop) on Jul 05, 2013 at 13:25 UTC

    Making a string, the space in your example, be the result of (numerical) multiplication seems like nonsense to me. If my code said

    my $foo = 'bar'; my $aaa = 3; # to avoid sort's special vars, $a & $b my $bbb = 2; my $result = $foo * ($aaa *$bbb); say "\$result is: $result"; =head Argument "bar" isn't numeric in multiplication (*) at D:\_wo\1042598.p +l line 11. $result is: 0 =cut

    and I didn't get an anguished squawk from the compiler, I would be horrified. In fact, I'm semi-horified that this is only a warning, rather than a fatal error.


    If you didn't program your executable by toggling in binary, it wasn't really programming!

      Absolutely. I agree! And that is the point.

      The integer operators like '*', '%', and "/" have no place being applied to a string. They only apply to other numbers. Thus I proposed that those operators have higher precedence so that all the integer ops would go away and all we would be left with was the "x' (the string repeat operator).

      i.e

      'a' x 3 => 'aaa' 'a' x 3*2 => 'aaa' * 2 ==> error You can never combine the math operators with strings (unless the string happens to be a number) ex: '2' x 3*2 = 222*2 => 444, but that's a pretty unclear way to multiply +222 by 2.
      That is why, I suggested the math ops be gotten out of the way first.

      If 'x' was commutative like '*', then we could say

      [sic] 3*2 x ' '
      And get our answer, But the 'x' is not commutative -- you can't switch the order of the operands. It always uses the left side as the string to be acted upon and always uses the right side as the count. Thus it only makes sense to reduce any numeric expression on the right side before applying it to the string on the left.

      Unfortunately, perl put 'x' in the same class as '*' and uses left to right evaluation. Since you are operating on 2 different data types in the same expression, it is common to perform evaluation on the same typed operands first, then apply that to the other operand.

      Example -- in 'C', the string operations are always done separately from the integer ops by virtue of the string ops being separate functions. It would be a natural evolution from C's syntax (which perl's is said to derive from), to do the integer ops first then pass result to the C function:

      a=2*3;str=' ';while (a--) strcat(str,str);
      You could not easily have a bad situation like ' ' x 2 * 3 in 'C', because the integer count construction is always done first, and the result passed to the string op.
      "In fact, I'm semi-horrified that this is only a warning, rather than a fatal error"
      Me too!... I make all warnings fatal w/trackback. You can just ""use warnings 'all=>FATAL'; I got a bit more involved and wrote an 'ExceptionHandler' that handles errors, warnings and signals.
      use ExceptionHandler;
      # then I can:
      Register_Traceback; #default is to register traceback for #SIGDIE & SIGWARN
      and setup handlers to dump a trace-back and quit:
      Regsister_Traceback('QUIT') #(control-\) So if I get stuck in an infinite loop somewhere, pressing ctl-\ instead of ctl-c will give me a traceback before exiting. Optio +nally the trackback registration can take a pointer to your own routine to call. Based on the return value of your own coded handler, Perl will then take an action based on the setup: <code> # sig, callback|disposition # disposition = sign-bit=exit immediate # = (0) = exit # = 1-7 if (devel){stack trace} + ignore "X" times + exit # = 0x10 = message/nomessage # = 0x20 = 0=count in bottom nibble, 1=noexit # = callback and status returns above val for further # = processing
      So my warning handler could ignore some warnings, and return 0x21 for count in bottom nibble 1=noexit for those warnings, but die on others.

      What some people don't get about my code -- is that there is that debug and error handling make up to 50% of some of my programs. I'm far more likely to make an error than not, and my progs are sufficiently complex they need smart self-diagnostics or I'm screwed. Just like another answer writing made some crazy assumptions about my *debug* code's indentation routine. I didn't go into the fact that it was in a debug routine because I didn't think it was pertinent to a discussion of string v. numeric operand precedence.

      A good article to read about language power and design which fairly well points out reasoning for removing the parens from my original example and strengthening perl's expressiveness to increase code clarity and power, can be read at: http://hillside.net/plop/2010/papers/gunther-2.pdf where he talks about domain specific additions to a language such as ruby or python. He left out perl, but he hints at a reason:

      However, analyzing the relevant literature 33, 44, 27, 49, 11, 9 reveals that there are several design principles of DSLs, such as abstraction to make domain concepts explicit programming language constructs, absorption to integrate implicit and common domain knowledge in the DSL, or compression to yield a concise domain notation.
      Perl suffers a lack of inherent abstraction and absorption allowing integration of implicit and common knowledge. -- Example:
      ' ' x 3*2
      Anyone who knows perl fairly well, knows that the above fails to abstract the concept of allowing 6 repeats of space. If it produced a valid result that was different (Suppose strings were automatically treated as base 64 -- then it might make sense to multiple a string by a numeric operand. But such is not the case. As it is, a logical design would require the integer operands to be evaluated first because not doing so leaves a semantic void in the language. Rather than being an expression with meaning, the syntax is wasted due to ill-prioritized precedence rules.

      I'm saying those can be fixed without harming backwards compat, since they don't express valid constructs in earlier versions of the language.

      make sense?

        Seems to me that you are -- in some large part -- setting up strawmen to knock down. For example, in your first example in the parent node, you say:

        001: 'a' x 3 => 'aaa' 002: 'a' x 3*2 => 'aaa' * 2 ==> error ...

        and in your last example (from which I won't even quote your global indictment of Perl) you appear to be objecting to the failure of the snippet to DWIW (that's do what I WANT; do what I mean is a different critter.)

        ' ' x 3*2

        Simple parens cure what you see as a problem requiring revision of the language:

        C:\>perl -E "my $foo = 'a'; say 'a' x (3*2); say 'hey, goombatz!';" aaaaaa hey, goombatz!

        Sorry, I may be convinced eventually, but so far, I don't think you've made your case.


        If you didn't program your executable by toggling in binary, it wasn't really programming!

Re^3: Precedence design question...'x' & arith
by tobyink (Canon) on Jul 05, 2013 at 20:18 UTC

    "You would have to know that for that to work, you'd have to be in perl 5.20 or newer, as it throws an error if you try to multiple a string times an integer."

    It only complains if you have numeric warnings switched on (which they are not by default) - and that's only a warning, not an exception, unless you enable fatal warnings.

    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name