Name bindings
Basics
Name bindings are made of three distinct components. The name, the type and the value that is assigned to the name.
Declaration of variables happens using the :
and =
symbols:
x: i32 = 3;
The :
symbol is used to denote the type of a variable, and the =
symbol is used to assign a value to it.
The type can be omitted, in which case it is inferred:
x := "Terence Tao"; // `x: str` inferred
x: str = "Terence Tao"; // same thing
x: i32 = "Terence Tao"; // Compile error: `str` is not assignable to `i32`.
Declaration and assignment can happen separately:
x: i32:
print(x); // Compile error: `x` might be uninitialised at this point!
x = 3;
print(x); // Ok
A variable declaration is an expression like any other, and returns the value of the variable. This means that you can write something like:
while (bytes_read := read_file(&buffer)) != 0 {
print("Read some bytes!");
}
Hash is statically typed, which means that variables cannot change types:
x := "Ha!";
x = Some("Baaa"); // Compile error: `Option<str>` is not assignable to `str`.
Mutability
By default, all bindings in Hash are constant.
In order to declare a mutable variable, use the mut
keyword in front of a name binding.
(mut a, mut b) := (1, 2);
mut test := get_test();
modify_test(&mut test);
a += 2;
b += 3;
Visibility
Visibility modifiers can be added to declarations inside modules or traits.
By default, all declarations in a module scope or impl
block are private, while all declarations in a trait
block are public.
To declare that a member is private, use priv
, while to declare that a member is public, use pub
.
// Visible from outside:
pub foo := 3;
// Not visible from outside:
bar := 4;
Foo := trait {
// Visible from outside
foo: (Self) -> str;
// Not visible from outside
priv bar: (Self) -> str;
};
Grammar
The grammar for name bindings (and partial name bindings/reassignments) is as follows:
pattern = pattern_binding | ...(other patterns)
pattern_binding = ( "pub" | "priv" )? "mut"? identifier
name_binding =
| ( pattern ":=" expr ) // Declaration and assignment, infer type
| ( pattern ( ":" type )? "=" expr ) // Assignment
| ( pattern ( ":" type ) ) // Declaration