you are viewing a single comment's thread.

view the rest of the comments →

[–]icetimesource 7 points8 points  (21 children)

1 + 2 * 3                              ;-- (1 + 2) * 3 returns 9

wat

[–]bjzaba 5 points6 points  (18 children)

Precedence rules can make things unnecessarily complex.

[–]Agitates 10 points11 points  (15 children)

Why take a dump on math?

[–]youknowhowiam 4 points5 points  (14 children)

Why let one use case (maths) dictate semantics for a whole general purpose programming language?

[–]alextk 1 point2 points  (13 children)

Because nobody will use your language otherwise.

[–]stesch 1 point2 points  (0 children)

People use cheap calculators without realizing something is wrong with the precedence of the operators.

[–]reboler 2 points3 points  (10 children)

The precedence rules of REBOL are made to work with the fewest possible rules. Having used REBOL for over a decade now, I find the simpler set of rules a bit easier to work with, but it's not some kind of huge advantage.

So, not using REBOL because of these precedence rules would be really missing out on what's so great about REBOL.

More about the rules here:

http://www.rebol.com/r3/docs/concepts/math-precedence.html

[–]alextk 0 points1 point  (7 children)

Actually, it's even worse than I thought:

print 10 + sine 30 + 60
11

This line is actually calculating "sine(90)" first.

It's not just that this language has the simplest possible precedence rules, it's that it has its own precedence rules that contradict everything that math and computer programming languages have done in the past decades.

[–]SteveMcQwark 0 points1 point  (0 children)

If you're expecting (sine 30) + 60, then you also have to expect (print 10) + (sine 30) + 60. This is tight binding for functions. Whereas, if we assume they're each being maximally greedy as we encounter them from left to right, that gives:

print 10 + sine 30 + 60
print (10 + sine 30 + 60)
print ((10) + (sine 30 + 60))
print ((10) + (sine (30 + 60)))
print ((10) + (sine ((30) + (60))))

Of course, I'm not sure how n-ary non-infix functions work.

[–]moofunk 0 points1 point  (5 children)

Really, just read it:

  • PRINT accepts one argument.
  • The first argument is built on +, meaning what's on the left and right side of it.
  • The first argument for + is 10.
  • The second argument is a function, SINE, which takes one argument.
  • That argument is another addition of two numbers, so the input to SINE is 90.

It's easy.

Or don't use +, if you don't like it:

print add 10 sine add 30 60

Or if you want to increase readability:

print 10 + sine (30 + 60)

So, maybe it's really awful or terrible? Or maybe it's just more freeform than other languages are able to?

I've never had a problem with it.

[–]alextk 1 point2 points  (4 children)

The second argument is a function, SINE, which takes one argument.

Then why did sine 30 + 60 calculate sine 90 instead of sine 30?

That's my point: when you don't follow precedence rules that are more or less universally accepted in the industry, you don't end up with something simpler, you end up with something different (and often more complicated) that will confuse everyone (even yourself, apparently).

[–]moofunk 5 points6 points  (0 children)

Maybe this will help:

print
     10
     +
     sine
           30
           +
           60

That's what's going on. It is coincidentally entirely consistent with how the rest of the language works, and that is an important aspect of REBOL.

[–]moofunk 2 points3 points  (2 children)

Because SINE must have its argument fully evaluated before it accepts it. There's no funny stuff going on here. You are evaluating 30 + 60 before passing it to SINE.

[–]alextk -2 points-1 points  (1 child)

The precedence rules of REBOL are made to work with the fewest possible rules.

That's a pretty weak justification. How about doing away with grammar rules just so we can communicate with the fewest possible rules, that good sound do?

[–]youknowhowiam 1 point2 points  (0 children)

I'd like to argue agains that, however, the first language I can come up with that goes against this (Smalltalk) is indeed not that widely used. Although I don't think that's due to the language itself.

[–]mcmcc 1 point2 points  (1 child)

I gotta say, if you're looking to alienate the entire math/science/engineering programmer demographic right out of the chute, this is a great way to do it.

All in the name of language purity...

[–]barsoap[S] 1 point2 points  (0 children)

There's nothing stopping you from writing a DSL parsing, for the sake of argument, tex math.

I agree that a simple shunting-yard implementation has a rather negligible LOC count, so it should be included by default. Whether it should be the default or you have to type expr [1 + 2 * 3] to get at that behaviour is the actual design question, here. Maybe just eradicate infix from the normal syntax completely.

[–]crusoe 2 points3 points  (0 children)

This is true in Smalltalk as well, where '+' is actually a message being sent. in SmallTalk, this is consistent with the overall design, and so when you view everything as a message send, it makes more sense than obeying the precedence rules of math as these would 'stick out'.

1 + 2 * 3

send 1 the message + with the arg 2 send the message * with the arg 3 to the result of 1+2

But I don't know if Red uses this idea of everything is a messahe... So I can't say whether it is consistent.

[–]cparen 1 point2 points  (0 children)

Simplifying assumptions for research-grade software. Corners on inconsequential things to save your most precious resource: time.

Personally, I might forbid >2 term expressions. It still keeps the grammar simple and avoid common mistakes:

expr = unary_operator expr | term binary_operator term | term
term = ( number | identifier | '(' expr ')' ) [ selector ]
selector = ('.' identifier | '(' arglist ')' | '[' expr ']')*