# Difference between revisions of "Terminator vs. separator"

From HaskellWiki

(→Terminators are better: out-commenting) |
(whitespace/indentation as example of "Initiator") |
||

Line 21: | Line 21: | ||

** let syntax: <hask>let a = 'a'; b = 'b' in ...</hask> and <hask>let a = 'a'; b = 'b'; in ...</hask> |
** let syntax: <hask>let a = 'a'; b = 'b' in ...</hask> and <hask>let a = 'a'; b = 'b'; in ...</hask> |
||

** do syntax: <hask>do a ; b</hask> and <hask>do a; b;</hask> |
** do syntax: <hask>do a ; b</hask> and <hask>do a; b;</hask> |
||

− | * Initiator? Theoretically it would also be possible to introduce each list element with some symbol. However, I don't know if this is used somewhere. |
||

+ | * Initiator: |
||

+ | ** The whitespace/indentation-delimited format used by <hask>let</hask> and <hask>do</hask> statements, among others, is an example of initiator format. Each element is preceded by a newline and the appropriate amount of spaces/indentation. |
||

== Terminators are better == |
== Terminators are better == |

## Latest revision as of 18:44, 4 October 2021

There are several concepts for notation of sequences of elements. Usually, we don't think much about it. Programming languages provide different schemes, often different schemes in the same language, we are used to them, and no scheme seems to be better than the other one. However, there are differences and good reasons for preferences.

## Terms

- Separator: There is a symbol between each element. This is what the functions
`Data.List.intersperse`

and`Data.List.unwords`

generate. In Haskell language, the following syntaxes allow separators only:- list sugar:
`[0,1,2,3]`

- tuples:
`(0,1,2,3)`

- type class constraints:
`f :: (Show a, Ord a) => a -> a`

- declaration of named record fields:
`data T = Cons {a :: Int, b :: String}`

- declaration of data constructors:
`data T = A | B | C`

- list sugar:
- Terminator: There is one symbol after each element.
- list notation using infixes can be considered an example:
`0:1:2:3:[]`

- list notation using infixes can be considered an example:
- Liberal choice between separators and terminators:
- export lists:
`module A(a,b,c) where`

and`module A(a,b,c,) where`

(and`module A(a,b,c,,,) where`

...) - import lists:
`import A(a,b,c)`

and`import A(a,b,c,)`

- let syntax:
`let a = 'a'; b = 'b' in ...`

and`let a = 'a'; b = 'b'; in ...`

- do syntax:
`do a ; b`

and`do a; b;`

- export lists:
- Initiator:
- The whitespace/indentation-delimited format used by
`let`

and`do`

statements, among others, is an example of initiator format. Each element is preceded by a newline and the appropriate amount of spaces/indentation.

- The whitespace/indentation-delimited format used by

## Terminators are better

- The theoretical reason: In separator notations there is one comma less than the number of elements. An empty list would need -1 commas, which can't be written, obviously. That is, empty lists must always be handled differently in the separator approach. There is no such problem with terminators.
- The practical reason: In terminator notation, each list element is followed by the terminator symbol. Thus it is easier to reorder the elements of a list in an editor. If you have written
`(1:2:3:[])`

you can simply cut some elements and the subsequent ':' and then you can insert them whereever you want. If you place every element at a line then it is easy to disable individual lines with a line comment (starting with`--`

). This formatting is also optimal for line oriented version control systems and diff.