Rye’s base dialect has no special forms so all code evaluates in exactly the same manner based just on types of words in a block.
Different types of words, and nothing else, do affect evaluation precedence, so understanding these basic rules will help you understand the code.
There are three word types that take their first argument from the left:
; dot-words - pin to immediate left, right-to-left
subtract: ?_-
12 .subtract 6 .subtract 4
; right-to-left: 12 .subtract (6 .subtract 4) = 12 .subtract 2 = 10
; op-words (bridges) - left-to-right
12 - 6 - 4
; left-to-right: (12 - 6) - 4 = 6 - 4 = 2
; pipe-words (walls) - wait for left side to fully evaluate
inc 10 |* 10
; wall effect: (inc 10) * 10 = 11 * 10 = 110
Dot-words (like .inc or .upper) pin to the immediate value on their left. When chained, they evaluate from right to left.
subtract: ?_-
12 .subtract 6 .subtract 4
; .subtract 4 pins to 6 → 2
; .subtract 2 pins to 12 → 10
; returns: 10
inc 10 .print
; .print pins to 10, prints 10
; inc then gets 10, returns 11
Op-words (operators like + - * / and angle-bracket words like <concat>) bridge two values. When chained, they evaluate from left to right.
12 - 6 - 4
; (12 - 6) - 4 = 2
"a" <concat> "b" <concat> "c"
; ("a" <concat> "b") <concat> "c" = "abc"
Pipe-words (like |* or |print) act as a wall. No expression passes through - everything on the left must fully evaluate first.
inc 10 |* 10
; wall: inc 10 = 11, then 11 * 10 = 110
; compare with op-word:
inc 10 * 10
; * bridges 10 and 10: inc 100 = 101
You can mix dot-words, op-words, and pipe-words to control exactly how expressions evaluate:
inc 10 * 10
; op-word * bridges 10 and 10: inc 100 = 101
inc 10 |* 10
; pipe-word |* is a wall: 11 * 10 = 110
13 + 14 .print |print
; .print pins to 14, prints 14
; |print waits for 13 + 14, prints 27
When in doubt, parentheses give you explicit control:
( 12 - 6 ) - 4
; result: 2
12 - ( 6 - 4 )
; result: 10
Note: Expressions inside parentheses are not affected by walls outside them.
Set-words and mod-words have even higher priority than pipe-words, meaning they capture everything that follows until the end of expression (including pipe-words).
x:: 12 - 6 - 4
; x = 2 (captures the whole expression)
x:: inc 10 |* 10
; x = 110 (captures the whole expression)
Left set-words (mod-words) capture the value from left in the same manner as pipe-words do:
12 - 6 - 4 ::x
; x = 2 (captures the result)
101 ::x + 1 |+ 2 |* 3 ::y
; x = 101, y = 312
; ::x captures 101, ::y captures the final result
You can use both set/mod-words and left set/mod-words together:
x:: 101 + y:: 1 |+ 2 |* 3
; x = 110, y = 9
; y:: captures the pipe expression (9)
; x:: captures 101 + 9 = 110
In summary: dot-words evaluate right-to-left, op-words and pipe-words evaluate left-to-right, and set/mod-words have higher priority, capturing their respective expressions.