| 147 | == Alternative syntax == |

| 148 | |

| 149 | Another possibility for syntax is this: |

| 150 | {{{ |

| 151 | expr ::= atom |

| 152 | | expr atom -- Application |

| 153 | | expr dot_occ -- TDNR invocation |

| 154 | | ... |

| 155 | |

| 156 | atom ::= var -- Unchanged |

| 157 | | '(' expr ')' |

| 158 | | ... |

| 159 | |

| 160 | -- dot_occ is a lexeme of form ".v" |

| 161 | }}} |

| 162 | Here the form ".v" is a lexical token. The two forms `(f x)` and `(x .f)` are application and TDNR invocation respectively. Both forms associate to the left, so `x .f 3 .g 7 5` means `(((((x .f) 3) .g ) 7) 5)`. This means that you can stack up successive TDNR invocations without parens: |

| 163 | {{{ |

| 164 | m .lookup key |

| 165 | .snd |

| 166 | .reverse |

| 167 | }}} |

| 168 | which means `reverse(snd (lookup m key))`. And that in turn means the same as |

| 169 | {{{ |

| 170 | reverse . snd . (\m -> lookup m key) $ m |

| 171 | }}} |

| 172 | There is something odd about this, however. We'd really like to write |

| 173 | {{{ |

| 174 | x .reverse |

| 175 | .filter isEven |

| 176 | .map double |

| 177 | }}} |

| 178 | but that doesn't work because the list is `filter`'s ''last'' argument, not its first. Maybe you should be able to write |

| 179 | {{{ |

| 180 | x .reverse .(filter isEven) .(map double) |

| 181 | }}} |

| 182 | (Of course the spaces can be omitted). And that would be fine provided we allowed this: |

| 183 | {{{ |

| 184 | expr ::= atom | expr atom |

| 185 | | expr dot_occ |

| 186 | | expr '.(' var expr1 .. exprn ') |

| 187 | ... |

| 188 | }}} |

| 189 | where `f .(g x)` means `(g x f)`. The oddness here is that the TDNR invocation can "look inside" the `.(..)` to see the function at the head. (And it had better BE a function, too.) |

| 190 | |

| 191 | I think this is probably worth it, although it's a little odd. |