Найти тему
Блокнот математика

Рубрика "Секреты Вим". Безымянные функции и замыкания

Привет, коллеги. Эта заметка относится к серии "Скриптовый язык" и описывает нововведения Вим версии 8: лямбда-выражения и замыкания. Модные темы добрались и до Вим!

Лямбдаааа!!!!
Лямбдаааа!!!!

Проверить, что у вас это есть, можно так:

echo has('lambda')

В коде тоже так можно проверить наличие данной возможности: через has().

Итак, что такое безымянная функция, она же лямбда-выражение? Это функция, создаваемая по месту и присваиваемая переменной. Это как бы выражение, возможно, с параметрами, которое не вычисляется сразу. Синтаксис в Вим:

{аргументы -> выражение}

Например,

:let f = {x -> x*x+1}
echo f(1)

Или

:let f = {x,y -> sqrt(x*x+y*y)}

Или даже без параметров:

:let pi = {-> arccos(-1.0)}

Выражение справа от -> является выражением: команды Вим там доступны только через execute.

Параметры доступны по имени без префикса a:, в отличие от функций.

Замыканием называется доступ к переменным и другим объектам из области видимости, которая может уже и не существовать. Пример:

function F(x)
let y = 42
return {z -> a:x+y-z}
endfuntion
let f=F(6)
echo f(8)

Увидим 40. Дело в том, что параметр функции x и локальная переменная y уже не существуют (функция-то завершилась), но замыкание помнит их значения. Функция F возвращает функцию, которая принимает один аргумент и возвращает число.

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

А замыкание позволяет "спрятать" переменную вообще. Технически ее и нет уже, а замыканию она доступна. Например, функция может запросить у пользователя секретное слово, создать лямбду, которая с ним работает, и вернуть ее: создать замыкание. Вызывая эту безымянную функцию, мы можем что-то делать с секретом, но не можем его ни прочитать, ни изменить.

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

map([1, 2, 3], {idx, val -> val * val})

Функция map применяет выражение ко всем элементам списка. Вместо выражения и можно использовать лямбду:

sort([3,7,2,1,4], {a, b -> a - b})

Здесь мы указываем явно выражение, сравнивающее два элемента.

Конечно, можно выражение и без того указать, используя предопределенные переменные. Но лямбды могут быть удобнее, тем более что и имена параметров вы сами задаете.

В общем, возможность есть, а уж применять или нет - это вам решать.

Научно-популярные каналы на Дзене: путеводитель
Новости популярной науки12 марта 2022