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

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?

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

    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!

      The initial question I came on here to ask was for someone to show me the usefulness of the current precedence -- how are they relying on it or using it in any production or cpan code.

      I'm not trying to convince anyone of anything -- as I can't say "we should do this", unless no one can come up code where the current precedence is used/useful/required -OR- how a change in precedence as I have outlined would cause a problem.

      Parens are a sign of either a complex statement OR insufficient strength in the grammar. Did you check out the pdf I pointed to (the references he quotes in the pdf point back to HERE on perlmonks..). Oddly enough, he quotes perlmonks in discussing good Domain Specific language design, but only has examples in python, scala, ruby and smalltalk. Here is someone who was familiar enough with perl that he could quote erudite discussions on perlmonks, yet didn't use in any of his examples.

      Qualities of good languages are generalization : reduce concepts by replacing a group of more specific cases with a common case.

      Compression -- Provide a consise language that is sufficiently verbose for the domain experts. -- Specifically the goal being to "reduce the amount of expressions or to simplify their appearance while the semantics are not changed" ...et al...

      The point here being to simplify the language in a way that loses none of its semantics, but simplifying the expressions.

      So far no one has offered any examples of how this change would cause problems. It's not like I'm new to perl -- I've been using it since the early 90's when P-III was just being replaced by P-IV. It took me forever to change out of the P4 style and move toward P5... I'm not someone who is highly open to change. But neither am I for killing a language for the sake of preserving for as a future archival language.

        Parens are a sign of either a complex statement OR insufficient strength in the grammar.

        Now there's a false dilemma. Unless you enforce a strict left-to-right evaluation order like Smalltalk, you have to choose how to break ties between different operators at different precedence levels. Even when you have operators at the same precedence level, you have to decide which executes first, depending on associativity and arity and the like.

        Without a single hard and fast expression evaluation order enforced by the grammar, you're going to have to make tradeoffs. Parentheses are also a sign that these tradeoffs aren't always right in every case.