открыть: Синтаксис 3Syntax 2открыть: Синтаксис 1

Пользовательские функции

Информация на этой странице в процессе обновления.

Все функции в ksi принимают два аргумента – левый и правый. Для задания возвращаемого значения внутри функции служит специальная переменная ret.

Имя функции, определённой пользователем, начинается с символа амперсанд &.

Определение фунцкции

Определения функций помещаются в декларативную часть файла, которая находится перед ключевым словом `plain.

&sum x y ( ret = x + y )

Вызов функции

Вызвать функцию можно только внутри императивной части файла. Т.е. после ключевого слова `plain или внутри функции.

&sum x y ( ret = x + y ) `plain c = 5 &sum 4 -- c = 9

Передача аргументов по ссылке

При вызове функции есть возможность передать переменную по ссылке в качестве аргумента. Для этого непосредственно после имени переменной ставится амперсанд. В этом случае изменения параметра, сделанные внутри функции, отразятся и на значении исходной переменной.

&set_zero var any ( var = 0 ) `plain var = 5 -- передаём ссылку на переменную var& &set_zero # -- var = 0

Аналогично можно передавать ссылку и на элемент массива, и на свойство класса.

$coords (x y) &set_zero var any ( var = 0 ) `plain v1 = [5 5] v1.0& &set_zero # v1[1]& &set_zero # v2 = $coords[5 5] v2.x& &set_zero #

Перегрузка функций

Функция может быть перегружена для определённого типа левого аргумента.

-- перегрузка для типа $map# &map_replace $map# map src ( src #is $map# (? map `each key : val& ( src #has_key key (? val = src[key] ) ) ) ret = map ) -- &map_replace в общем виде &map_replace a b ( FN# % ' ~ Первый аргумент должен быть типа $map#.' #log # ) `plain {%x:0 %y:0 %z:0} => map &map_replace {%z:1 %y:1 %a:1} map #write [n# ':'] /* Вывод: x:0 y:1 z:1 */

В качестве типа для перегрузки можно указать имя типа со звёздочкой. Это значит, что такая перегрузка сможет принимать значения левого аргумента, не только заданного типа, но и их наследников. Это так называемая "type_based" перегрузка.

$shape (position) $circle : $shape (radius) $rectangle : $shape (width height) &draw $shape* shape any ( -- do something ) `plain origin = [0 0] o1 = $circle{%position: origin, %radius: 20} o2 = $rectangle[origin, 10 10} o1 &draw # o2 &draw #

В качестве типа для перегрузки можно указать категорию типа. Это значит, что такая перегрузка сможет принимать значения левого аргумента, любых типов, относящихся к заданной категории.

&square _number# n any ( ret = n * n ) `plain 5 &square # #write_ln # -- 25 0.1 &square # #write_ln # -- 0.01

Порядок поиска подходящей перегрузки при вызове функции является следующий:

Когда подходящяя перегрузка найдена, то она будет вызвана, и поиск перегрузки не будет дальше продолжаться. Если не найдена ни одна подходящая перегрузка, то результатом вызова функции будет null #.

Поменять местами левый и правый аргументы при вызове функции

Для этого непосредственно после имени функции ставится знак >.

array = [1 3 2] # #sort> array -- array #sort #

Вызов функции через указатель

Через указатель можно вызвать как пользовательские, так и стандартные функции. Для получения указателя непосредственно после имени функции ставится знак & амперсанд. Для вызова через указатель используется символ ! восклицательный знак, перед которым не должно быть пробельных символов.

fn = #implode& -- указатель на функцию присваивается в переменную fn [1 2 3 4 5] => array array fn! ', ' => str -- str = '1, 2, 3, 4, 5'

Тип значения "указатель на функцию" является $fn#.

Безымянные функции

Безымянные функции могут быть определены в императивной части скрипта, или в теле другой функции. Тип безымянной функции $closure#.

`plain func = &[] x y ( x + y => ret ) 1 func! 2 => c #write # -- выдаст: 3

Внутри безымянной функции своя собственная область видимости локальных переменных (точно также как и у любых других функций). Для того, чтобы иметь доступ к локальным переменным из области видимости host функции (или из блока `plain) – существует способ захвата переменных.

Пример с захватом переменной по значению:

`plain factor = 2 func = &[factor] x y ( x + y => ret *= factor ) 1 func! 2 => c #write # -- выдаст: 6

Пример с захватом переменной по ссылке:

`plain factor = 2 func = &[factor&] x y ( x + y => ret *= factor ) factor = 1 1 func! 2 => c #write # -- выдаст: 3

* Захватывать можно и несколько переменных, перечислив их через необязательнйю запятую, с возможностью указания захвата по ссылке или по значению для каждой.


Безымянную функцию можно передать в качестве аргумента другой функции.

&apply_to _callable# fn items ( items `each key : val& ( val = val& fn! # ) ) `plain array = [1, 2, 3] lambda = &[] item any ( item -= 1 ) lambda &apply_to array array #dump #0 -- [0, 1, 2]