В языке есть так называемые контракты - фича, позволяющая отслеживать параметры функции передающиеся внутрь и наружу. Это важно для безопасности и защите от ошибок.
fn retDiv(let const a : int,let const b : int, {b != 0})
-> (let const : int)
{
return a / b;
}
Проверяет что деление ок.
fn returnConc(let const a : string,let const b : string)
-> (let const : string, {@.len() > 0})
{
return a + b;
}
Проверяет что возвращаемая строка не пуста.
fn test(let a : int {>0})
{
}
Говорит, что a должно быть больше нуля.
Функции могут иметь выбор явный/неявный. Функции могут иметь уникальное полное имя (имя + расширение)
fn run::now default() // ключевое слово default
{
doTask();
}
fn run::after()
{
sleep(1000);
dotask();
}
run::after(); // Вызовет вторую функцию
run(); // Вызовет первую ()т.к. она default
run::() // Вызовет любую подходящую функцию (первую)
Мы можем воспользоваться SFINAE и вызвать функцию наиболее подходящую под параметры без указания расширения.
fn sum::a(let a : int, let b : int) -> (let int) {return a + b;}
fn sum::b(let a : real, let b : real) -> (let real) {return a + b;}
let const a = sum(1,2); // 3
let const b = sum(0.1, 0.2); // 0.3
Мы можем применить интроспекцию и передать в функцию её расширение как переменную.
fn test::<let t : fn::ext::enum>()
{
if t == ::run
{
doTask();
}
elif t == ::runLater
{
sleep(1000);
doTask();
}
}
test::run(); // Вызовет первую ветку
test::<run>();
test::runLater(); // Вызовет вторую ветку
Можно запретить использование расширения имени.
func:: = null;
fn func::a()
{ ... }
fn func::b()
{ ... }
func::a(); //ok
func::b(); //ok
func(); // error
Для контрактов работает принцип SFINAE. Вы можете использовать это в том числе для перегрузки функций в том числе по типу передаваемых переменных и их значениям. Если для вызова будет доступно несколько функций, будет выбрана дефолтная или будет выведена ошибка если такой функции нет в области видимости имени.
// Мы используем здесь числа для различия функций
fn func::0(a : int, {a <= 100})
{
println!("<= 100");
}
fn func::1(a : int, {a > 100})
{
println!("> 100");
}
func(150); // Выведет вторую функцию
func(90); // Выведет первую функцию
В случае если функция всё равно не найдена будет выброшено исключение или CE.