Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression precedence in Rebol and Smalltalk

Rebol and Smalltalk's expression evaluating precedences have some similarity, both of them are very simple.

Rebol's evaluation order, according to clauses in http://rebol.com/r3/docs/concepts/math-precedence.html, is:

  • Expressions are evaluated from left to right.
  • Operators take precedence over functions.

And Smalltalk, In Smallbalk-80 (Bluebook) page 30:

  1. Unary expressions parse left to right.
  2. Binary expressions parse left to right.
  3. Binary expressions take precedence over keyword expressions.
  4. Unary expressions take precedence over binary expressions.
  5. Parenthesized expressions take precedence over unary expressions.

Rebol's function call is similar to Smalltalk's unary expression, but there precedences related to binary operators are reversed. I find this a bit annoying when switch between those two languages.

My question is, why Rebol and Smalltalk take different design choice? I don't think it is arbitrary.

like image 517
Xin Wang Avatar asked Aug 07 '15 05:08

Xin Wang


1 Answers

The size of the lists suggest one big difference, which is Rebol's goal of simplicity. 2 rules is less than 5, and all things being equal that's better...unless a specific advantage is shown to having five.

Going further with that: having two rules is probably more than would have been ideal. Yet allowing infix operators at all is a kind of grudging compromise. People expect if a > b [...] and not if greater? a b [...] most of the time. (You can write either in Rebol.)

Given that Rebol and Smalltalk are different languages entirely the question is sort of hard to answer of "why". But in the area of "what"...one relevant thing would be "where did the complexity go?" For instance, Rebol needs grouping precedence; so if that's not being managed by the evaluation rules, where is it?

"Special" treatment in Rebol doesn't tend to come from characteristics like the arity of a function. Instead, the "specialness" comes from the unique dispatch of types of the values themselves. So for example, parentheses aren't mentioned at all in Rebol's precedence list because parenthesized groups are a concrete type of list, known as a PAREN! (I call them GROUP!...that's another discussion.)

>> foo: [(1 +) ((a) [b c] d) ()]

>> length? foo
== 3

>> paren: second foo
== ((a) [b c] d)

>> length? first paren
== 1

>> pick foo 3
== ()

They live in the structure of your homoiconic code. So when the evaluator gets to finding (a b c) it treats it as if you had written do [a b c].

An upshot of this is that you can use parentheses to simulate the effects of precedence, without needing a special "precedence rule" for parentheses. It simply falls out for 1 + (2 * 3) that + cannot fulfill its arguments until (2 * 3) gets evaluated, and it all works out to 7.

(Note: While that's what the default evaluator does with parens, they can be used for other purposes. See COMPOSE and PARSE for a couple of important ones that are in the box. But as with the other value types in Rebol you can bend them to your own purposes in your own dialects.)

So really it just boils down to having shifted the necessary functionality around a bit onto the values of different types. An advantage of doing it that way is the generation of reusable parts for alternative evaluation (or data) models.

like image 70
HostileFork says dont trust SE Avatar answered Sep 20 '22 23:09

HostileFork says dont trust SE