Fuzion Declaration Syntax
Declarations for features may require type information if the type cannot be inferred automatically. The basic decision here is whether the type should be before or after the declared feature.
Mixing type and declared entity
The C/C++ programming language chose to mix the types and the declared entity, e.g.,
C/C++ |
---|
int a[3]; int (*f)(int); |
Such confusing syntax must be avoided, this is extremely hard to parse for humans.
Type before declared entity
Java (with exceptions) |
---|
int[] a; java.util.Vector<String> v; |
Type after declared entity
Rust | Modula-2 | Go |
---|---|---|
let y: f32 = 3.0; // f32 |
VAR Count : INTEGER; x,y : INTEGER; |
x int p *int a [3]int f func(func(int,int) int, int) func(int, int) int |
Separating type and declared entity
Using an explicit separator like :
between the type and the declared entity makes parsing the language significantly simpler, but increases verbosity.
References
Go uses entity name before type without a separator symbol. There is a nice blogpost giving the rationale: Go declaration syntax rationale.
Separation of argument list and result type
Other languages
Here are some examples how languages separate the result type
rt
from the argument list (here for one argument x
of type at
) in a function declaration:
Haskell | Java | Rust | Pascal |
---|---|---|---|
f :: at -> rt f x = ... |
rt f(at x) { .. } |
fn f(x: at) -> rt { .. } |
function f(x : at) : rt; begin ... |
The linked article argues that the trend for new programming languages is to have the types at the right side.
Fuzion
Fuzion requires formal arguments to be enclosed in parentheses ( )
, the result type follows immediately after the argument list:
Fuzion using explicit result type | Fuzion using result type inference |
---|---|
f(x at) rt => ... |
f(x at) => ... |
Fuzion type syntax and argument list syntax are similar such that some types can be parsed as valid argument lists and vice versa. This is a problem for Fuzion features with an empty argument list that return tuple type:
Fuzion code | interpretation |
---|---|
f (a, b i32) is ... |
constructor with two arguments of type i32 returning a new instance of f .
|
f (a, b i32) unit => ... |
function with two arguments of type i32 returning a unit value (i.e. nothing).
|
f () (a, b i32) => ... |
function without arguments returning a tuple of types a and b i32 using explicit result type
|
f => (a x y, b i32 z) |
function without arguments returning a tuple of types a and b i32 using type inference
|
f (a, b i32) -> bool => ... |
function without arguments returning a function taking two arguments of types a and b i32 and resulting in bool .
|
Fuzion using =>
We could introduce =>
as a required separator between the argument list and the result type. This would turn these examples into the following:
Fuzion using explicit result type | Fuzion using result type inference |
---|---|
f(x at) => rt => ... |
f(x at) => ... |
Examples of disambiguation of tuple result and argument lists using =>
:
Fuzion code | interpretation |
---|---|
f (a, b i32) is ... |
constructor with two arguments of type i32 returning a new instance of f .
|
f (a, b i32) => unit => ... |
function with two arguments of type i32 returning a unit value (i.e. nothing).
|
f () => (a, b i32) => ... |
function without arguments returning a tuple of types a and b i32 using explicit result type
|
f => (a, b i32) => ... |
function without arguments returning a tuple of types a and b i32 using explicit result type
|
f => (a x y, b i32 z) |
function without arguments returning a tuple of types a and b i32 using type inference
|
f => (a, b i32) -> bool => ... |
function without arguments returning a function taking to arguments of types a and b i32 and resulting in bool .
|
We need to decide if a clear separator like =>
between argument lists and result type brings an advantage.
Pros:
- clear syntactic difference between functions (features
with
=>
in their declaration) that produce a result and constructors (features without=>
in their declaration) that create a new instance. - Parser ambiguity between argument list and result type is removed.
- Consistency between argument field declaration
a i32
and 'normal' field declarationa i32 := value
.
Cons:
- Additional
=>
symbol in every function declaration. - More cryptic code, newbies might get confused about what
=>
means. - Inconsistency between argument field declaration
a i32
and 'normal' field declarationa => i32 := value
(alternatively a different rule making=>
optional for fields).
A third alternative would be to add =>
as an optional
separator. This, however, will very likely introduce confusion since it will be
required (and hence used) in very few, specific cases (when a function's result
is a tuple).