2.7. Static Type Inference

For the sake of convenience, Sather provides a mechanism for statically inferring the type of a variable from the context. This type-inference takes place in different situations, where the type is available from the context.

2.7.1. Creation Expressions

In a creation expression, it is tedious to have to repeat the type of a class on both sides of a creation expression and assignment. Hence, the # symbol may infer its type from the context.
a := #(3,4);
-- Equivalent to a := #POINT(3,4);

2.7.2. Assignments and ::=

Type inference can also take place in a declaration, if it is combined with an assignment. Since the declared type of the right hand side of the assignment is known, its type is used as the type of the variable. This combination of declaration and assignment is extremely common in Sather code.
a ::= 3;                     -- Equivalent to a:INT := 3;
p1:POINT := #POINT(3,5);
p2:POINT := #POINT(4,5);
p3 ::= p1.add(p2);           -- 'p3' is of type POINT.
-- Assumes the function 'add' in POINT i.e. POINT::add(POINT,POINT);

When an assignment is associated with a creation, we can make use of either form of type inference
a ::= #POINT(3,4);  -- Equivalent to a:POINT := #POINT(3,4);
a:POINT := #(3,4);  -- Means the same

2.7.3. Arguments to a function call

The type of the arguments to a function call are also known and can be used to infer the type of a creation expression in a call to the function.
foo(a:POINT) is  ...

-- The create expression infers its type
-- from the type of the argument that 'foo' is expecting

This form of type inference may be used for closure creation expressions as well, which will be discussed in the chapter on Closures
apply(arg:ROUT{INT}:INT) is ....

If the plus routine in the INT class is overloaded, then the appropriate routine is chosen based on the declared type of the argument to 'apply' i.e. ROUT{INT}:INT. Note that if both the 'apply' routine and the 'plus' routine are overloaded, type inference may not be able to determine the type and it might be necessary to create a temporary variable with the right type
r:ROUT{INT}:INT := bind(3.plus(_));

In any case, we strongly recommend that static type inference not be used in cases where confusion might result; the extra typing is usually worthwhile!