Функции

```

* **Область** - область видимости функции
	+ **g** - глобальная функция (в данной области имя должно начинаться с верхнего регистра)
	+ **v** - глобальная системная функция
	+ **s** - функция, доступная только в текущем скрипте
	+ **b** - функция, доступная только в текущем буфере
	+ **w** - функция, доступная только в текущем окне
	+ **t** - функция, доступная только в текущей вкладке
* **Имя** - имя функции (допустимый формат *[A-Za-z\_][A-Za-z0-9\_]+*)
* **Аргументы** - имена переменных (без области видимости), доступные телу функции в области **a**
* **Тело** - код, выполняющийся при вызове функции

Если объявляемая функция уже существует в данной области видимости, возможно заменить ее используя запись **function!**.

### Вызов

Для вызова функции используется команда **call**:

```
call g:MyFun(<параметры>)

```

* **Параметры** - любые данные, передаваемые телу функции

Если функция возвращает значение, она может быть вызвана любым выражением:

```
let s:result = g:Sum(1, 2, 3)

```

Команда **call** может использоваться в качестве функции:

```
call call('g:MyFun', <массивПараметров>)

```

* **МассивПараметров** - массив значений, передаваемых в вызываемую функцию в качестве параметров (если функция не принимает аргументов, необходимо передать пустой массив)

### Параметры

Функция может принимать любое число аргументов, а так же не принимать их вовсе. Областью видимости параметров функции является **a**.

```
function g:Sum(a, b)
  return a:a + a:b
endfunction

```

Параметры функции не могут быть изменены

```
function g:MyFun(param)
  let a:param = 5 " Ошибка
endfunction

```

Функция может принимать динамическое число параметров, используя запись ... Доступ к таким параметрам осуществляется с помощью переменных:

* **a:000** - массив динамических параметров
* **a:1**, **a:2** - первый, второй и т.д. переданный динамический параметр
* **a:0** - количество переданных динамических параметров

```
function g:MyFun(...)
  echo 'Переданно ' a:0 ' параметров'
endfunction

```

### Возвращаемое значение

Команда **return** завершает выполнение тела функции и возвращает переданное значение:

```
function g:GetHello()
  return 'Hello world'
endfunction

```

### Косвенные ссылки

На функцию можно ссылаться из переменной. Для этого используется функция **function**, которая возвращает ссылку на функцию:

```
let s:Fun = function('g:MyFun')

```

Если переменная, ссылающаяся на функцию, объявляется в глобальной области **g**, ее имя должно начинаться с заглавной буквы.

Переменная ссылающаяся на функцию может быть вызвана аналогично обычной функции:

```
echo s:Fun(1, 2)

```

Функции передаются по ссылке.

## Лямбда-функции

### Объявление

```
{<аргументы> -> <тело>}

```

### Возвращаемое значение

В лямбда-функции возвращаемое значение вычисляется ее телом, что позволяет избавиться от операции **return**.

## Замыкания

Замыкание предоставляет доступ к внешней области видимости.

### Объявление

```
function <имя>(<аргументы>) closure
  <тело>
endfunciton

```

## Пример использования

Функция проверки вхождения элемента в массив:

```
function g:Has(array, value)
  for l:el in a:array
    if l:el == a:value
      return 1
    endif
  endfor

  return 0
endfunction

```

Функция для суммирования чисел:

```
function g:Sum(...)
  let l:result = 0
  for l:val in a:000
    let l:result += l:val
  endfor

  return l:result
endfunction

```

Фильтрация массива с помощью лямбда-функции:

```
let s:arr = [1,2,3,4,5]
echo filter(s:arr, {val -> val > 3})

```

Использование замыкания:

```
function! Foo()
  let x = 0
    function! Bar() closure
      let x += 1
      return x
    endfunction
  return funcref('Bar')
endfunction

let F = Foo()
echo F() " 1
echo F() " 2
echo F() " 3

```