(Here's part of a theory of declarations. It came from thinking about 'using'. – jrose)
A declaration is an optional type, followed by a name and an optional initializer. Additional names and optional initializers may follow, separated by commas.
A declaration introduces one or more named values. A declaration may appear anywhere an expression or statement can.
(Issue: What's the story for distinguishing 'String x' from 'println x'? They seem to be the same syntax, but have different scoping effects.)
If a declaration is used as an expression, it produces as its value, the value of last (or only) name it declares.
Every name defined by a declaration is in scope from immediately after that name (and its initializer if any) to the closing brace of the innermost relevant block. A block B is relevant to a declaration D if any of the following is true:
- B contains D
- B is appended to a method call containing D
- B is a body of a control flow construct ('if', etc.) containing D
These rules allow new names to be introduced in the midst of a method call or other expression, and be used until the next 'obvious' right brace.
Here are examples in which such declarations are moved to outer scopes: