Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

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 declaration a 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 declaration a => 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).