REBOL3 tracker
  0.9.12 beta
Ticket #0002120 User: anonymous

Project:

Previous Next
rss
TypeWish Statusreviewed Date1-Mar-2014 19:43
Versionr3 master CategoryMezzanine Submitted byfork
PlatformAll Severitymajor Priorityurgent

Summary EXPR mathematical expression evaluator obeying ordinary precedence
Description Reviewing the discussions and arguments on the internet, there are a few things people *always* say. Perhaps not number one, but certainly in the top 3 is "why does Rebol not use normal precedence, like the 'rest of the world' agrees upon". (*cough*they don't actually agree*cough*)

Debates quickly spiral out of control and become off-topic. Rebol-language defenders usually begin by arguing that simpler rules are actually better, and are central to the design of a system with interesting composition. Then people say that's out of touch, and going against convention means your language will always be obscure.

Then the argument becomes ever-more abstract. That one shouldn't be slaves to complexity just because everyone else is doing it. Or that when shifting around decisions in order to carve up "complexity space", it helps to be reasonable about the actual value preserving a specific convention has, for the cost it has on other areas of the design.

Right answer, wrong time to be presenting it. Forums of absolute beginners or JavaScript programmers, instead of being revealed the cool things, quickly fill up with noise. The number of people who have immediately set the "Bozo Bit" on Rebol for the response to this issue is probably in the thousands:

http://en.wikipedia.org/wiki/Bozo_bit#Dismissing_a_person_as_not_worth_listening_to

New answer. The FIRST response to someone showing a precedence example they don't like, is simple:

"Oh, you mean you want math precedence and not simplified precedence? Just use EXPR if you're doing math. Rebol is paradigm neutral; you can use and define what you want. In fact, want to see something else cool...?"

The fact that years of this debate happening and no one just sitting down and writing the EXPR implementation is ridiculous. Of course, there are a lot of questions about what it would do, besides obey mathematical precedence...

values: [2 3 4]
expr [1 + pick values 1 * pick values 2]

You're probably going to ask how EXPR is supposed to know that it's not supposed to multiply 1 by 3 from the pick values 2... and then pick the 4 out of values and add it to 1 to get 5.

WHO CARES! Make it do one thing, the thing they asked for. Obey mathematical precedence. Do a pre-phase on the block passed in. Translation:

expr [1 + pick values 1 * pick values 2]
=>
(1 + ((pick values 1) * (pick values 2)))

If it generates something confusing, again: who cares? Just don't do your additions before your multiplications and stuff like that:

expr [1 + pick values 1 + 2 * pick values 2]
=>
(1 + ((pick values 1) + (2 * (pick values 2))))

If they want to be more explicit, let them parenthesize their function calls in the source. (That's the other top 3 question.)

expr [1 + (pick values (1 + 2)) * (pick values 2)]
=>
(1 + ((pick values 1 + 2) * (pick values 2))))

Just no more "deep" explanations until people know enough about the language to care enough to know why it's different.

To attack philosophy, start with easier things like carving up the lexical space. Get them to understand why being able to type a/b and get division is not as useful as having things like http://example.com not need quotes. That's concrete and has quick wow factors. Trying to come up with examples of the value of foregoing traditional precedence is way harder to knock out of the park quickly.
Example code
;-- Without EXPR

>> 1 + 2 * 3
== 9


;-- With EXPR

>> expr [1 + 2 * 3]
== 7

Assigned ton/a Fixed in- Last Update26-Jan-2015 07:49


Comments
(0004285)
BrianH
1-Mar-2014 20:44

"normal precedence, like the 'rest of the world' agrees upon"

The problem here is that the rest of the world most definitely does not agree on precedence rules. They vary widely even between programming languages, and are the subject of much heated debate between their communities. We can't just use the mathematical precedence rules, because the math rules don't have ASCII multiplication operators and does division with horizontal lines, and that's just for a start. Mathematical notation has been under debate for thousands of years with no signs of letting up soon.

I'm not discouraging you here, the rationale for this is good. Rebol-like precedence is rare outside of Rebol-like languages and we would benefit from a way to shut down complaints about that. We just need to be specific about the precedence rules you want here, and exactly which operators are to be supported, because there is no such thing as "normal" precedence rules. You have to specify the whole set of operators, and what precedence they are supposed to have relative to each other, and what precedence not-operator expressions have in all this.

As a suggestion, consider this treatment of the non-operator expressions: Have normal function arguments be taken at a lower priority than any operators (which would all have to be keywords). If an operator is seen in the input stream, that means you have run out of parameters, and if you didn't have enough this is an error. If you run out of parameters early, this is an error. Get-word arguments would be able to break these rules, letting the operator word just be a word value instead of a keyword (so you can use QUOTE). I'm leaning towards lit-word arguments having the same precedence rules as normal ones, with the operator keywords simply not being usable as lit-word arguments without quoting them in a paren, just to reduce ambiguity.

As for the operator precedence itself, the standard math operators tend to be pretty consistently mul/div first, add/sub next, but after that there is very little agreement between programming languages. You'd have to look at them and decide. Fortunately we just have equivalences, relative equivalences, and logical operators. At least we don't have to deal with anything postfix, and prefix are the function calls above.

We also have to decide what precedence set-words would have.
(0004286)
fork
1-Mar-2014 21:19

These arguments are coming from JavaScript and C people... not Haskell/Lisp people. Copy JavaScript:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence

People coming back with feedback about "you could have done that better" aren't going to be Rebol people, because they won't use it. Modifications worth doing are anything which make them get off the topic.

The point isn't in the minutiae. It's "why don't you do ANYTHING close to what a REASONABLE person would expect". Show them you can be sort of what they think is reasonable, then immediately change the subject!
(0004287)
BrianH
1-Mar-2014 21:35

Oh, sorry to hear that, precedence in C-like languages tends to suck really bad. Hopefully we can do something a little closer to Modula-3, it has better precedence rules than the rest of the Pascal family and the entire C family. It's a good thing we don't have to do as many levels.

We might be able to do something simpler and just assume that only operators (that we know about) have precedence (that we decide on ahead of time), and just do a simple rewriting pass changing the operators to their corresponding prefix functions (they all have them), and have the rewriter put everything between the operators into parens, just in case. QUOTE would need to be a prefix operator. Then, we wouldn't have to rewrite DO while we're at it. This could be a static transform, even doable in a compiler like Red, even doable in a mezzanine function in Rebol if it comes down to that.
(0004288)
fork
1-Mar-2014 22:32

I think most people will be happy if the rules for addition, subtraction, division, and multiplication work as they expect. It's a sticking point. If you have a better chart to copy which covers that, then it's probably fine.

People just really stick on this [1 + 2 * 3]. Might seem funny how the house of cards of their programming world collapses every day, yet they care about that. But maybe that's *exactly* why they react so strongly; in their languages that's the one thing they can count on. Using a language that breaks the one thing they trust might just be the last straw to send them screaming!

...

"There is something you need to understand about showing people Future Things. You have to be careful. It's a lot like if you are dealing with someone who has never had a grape before. When you give them their first grape you must be 100% sure it's not a sour one...because if it is sour, then every time they're asked if they want a grape after that they will say no." -æ-
(0004289)
abolka
1-Mar-2014 22:50

Here's two references for Modula-3's precedence rules;

- http://radx.ru/images/1.html#idx.153 (that's from the original language definition)
- http://monet.cs.columbia.edu/modula3/tutorial/www/m3_56.html
(0004290)
BrianH
1-Mar-2014 23:08

OK, so based on the numbering of that last link, we can do levels 6 through 11, and put QUOTE in at number 5. The rest would be handled by normal Rebol precedence simply by not being rewritten. We need to handle parens too, because if we don't the stuff in parens would have normal Rebol precedence. Parens would be lower precedence than anything, except parens after a QUOTE would not be rewritten.
(0004297)
fork
4-Mar-2014 23:10

If I wrote it, it wouldn't be as good as if you wrote it, but so does that mean I have to write something crappy for you to correct before it happens?

If that is the case, please look forward to my terrible pull request implementation of EXPR... designed solely to provoke you into making a good one :-)
(0004298)
BrianH
4-Mar-2014 23:18

Already working on it, in my head at least. With the precedence rules decided on above. Not my next PR though.
(0004386)
fork
24-Mar-2014 12:41

There is an implementation that exists to possibly borrow from, pointed out by @rebolek

http://rebol2.blogspot.cz/2013/07/mathematical-expression-dialect-parser.html

Date User Field Action Change
26-Jan-2015 07:49 abolka Code Modified -
26-Jan-2015 07:49 abolka Status Modified submitted => reviewed
16-Nov-2014 10:43 fork Code Modified -
16-Nov-2014 10:43 fork Description Modified -
24-Mar-2014 12:41 fork Comment : 0004386 Added -
4-Mar-2014 23:18 BrianH Comment : 0004298 Added -
4-Mar-2014 23:10 fork Comment : 0004297 Added -
1-Mar-2014 23:08 BrianH Comment : 0004290 Added -
1-Mar-2014 22:50 abolka Comment : 0004289 Added -
1-Mar-2014 22:33 fork Comment : 0004288 Modified -
1-Mar-2014 22:32 fork Comment : 0004288 Added -
1-Mar-2014 21:42 BrianH Comment : 0004287 Modified -
1-Mar-2014 21:37 BrianH Comment : 0004287 Modified -
1-Mar-2014 21:35 BrianH Comment : 0004287 Added -
1-Mar-2014 21:24 BrianH Comment : 0004285 Modified -
1-Mar-2014 21:19 fork Comment : 0004286 Added -
1-Mar-2014 21:10 BrianH Comment : 0004285 Modified -
1-Mar-2014 21:09 BrianH Comment : 0004285 Modified -
1-Mar-2014 21:08 BrianH Comment : 0004285 Modified -
1-Mar-2014 20:50 BrianH Comment : 0004285 Modified -
1-Mar-2014 20:45 BrianH Comment : 0004285 Modified -
1-Mar-2014 20:44 BrianH Comment : 0004285 Added -
1-Mar-2014 19:43 fork Ticket Added -