Анонимная функция

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

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

Обычно при создании анонимные функции либо вызываются напрямую, либо ссылка на функцию присваивается переменной, с помощью которой затем можно косвенно вызывать данную функцию. Но в последнем случае анонимная функция получает имя и уже перестаёт быть анонимной. Если анонимная функция ссылается на переменные, не содержащиеся в её теле (захват), то такая функция называется замыканием. Лямбда-выражение — типичная для многих языков синтаксическая конструкция для определения анонимной функции.

Синтаксис[править | править код]

Синтаксис записи анонимных функций для различных языков программирования в большинстве случаев сильно различается.

Язык Пример записи сложения
AS3
function(x:int, y:int):int{return x + y;}
C#
(x,y) => x+y
C++ Введены в C++11. Обязательно должны присутствовать захват и тело. Полная форма[1]:
[захват](параметры)mutable исключения атрибуты->возвращаемый_тип{тело}
Пример[2]:
[](int x, int y){ return x + y; }

В С++14 была добавлена возможность использовать лямбда-функции с auto[3]:

auto lambda = [](auto x, auto y) {return x + y;};
Анонимная функция может захватывать как отдельные переменные, например:
int a; auto f = [a](){return a;}
так и все внешние переменные: по ссылке [&] или с помощью копии [=]. Также можно комбинировать эти подходы: например, все переменные захватить по ссылке, а определённые параметры по копии. Чтобы иметь возможность модифицировать переменные, захваченные по ссылке, нужно указать ключевое слово mutable при объявлении функции. В C++14 добавлена возможность инициализации переменных лямбды в захвате. Например:
[a = std::string{}](){return a;}
CoffeeScript
(x, y) -> x + y
D
// короткая форма записи с автовыводом типов
auto a = ((x, y) => x + y)(2, 3);

// длинная форма записи (блок с фигурными скобками) с автовыводом типов
auto aa = (x, y) { return x + y; }(2, 3);

// автоопределение компилятором типа анонимной функции: функция или делегат
auto b = (int x, int y) => x + y;
auto bb = (int x, int y) { return x + y; };

// функции не имеют доступа к внешним переменным
auto c = function(int x, int y) => x + y;
auto cc = function(int x, int y) { return x + y; };

// делегаты имеют доступ к внешним переменным
auto d = delegate(int x, int y) => x + y;
auto dd = delegate(int x, int y) { return x + y; };

// делегат, принимающий переменную типа int и возвращающий значение типа double
auto f = delegate double(int x) { return 5.0 / x; };
Delphi (c 2009 версии)
function(x, y: integer): integer 
begin
  result := x+y;
end;
Erlang
fun(X,Y)->X+Y end
GNU Octave
@(x,y)x+y
Go
    Z := func() int {
        return X + Y
    }()
Groovy
{x, y -> x + y}
Haskell
\x y -> x + y
Java (с версии 8)
// with no parameter
() -> System.out.println("Hello, world.");

// with a single parameter (This example is an identity function).
a -> a

//with a single expression
(a, b) -> a + b

// with explicit type information
(Long id, String name) -> "id: " + id + ", name:" + name

// with a code block
(a, b) -> {return a + b;}

// with multiple statements in the lambda body. It requires a code block.
// This example also includes a nested lambda expression as well as a closure.
(id, newPrice) -> {
  Optional<Product> mayBeProduct = findProduct(id);
  mayBeProduct.ifPresent(product -> product.setPrice(newPrice));
  return mayBeProduct.get();
}
JavaScript Стрелочная функция (arrow function expression) всегда объявляется без имени. Стрелочные функции добавлены в стандарт ECMAScript 6 (также известном как ECMAScript 2015)[4].
// Стрелочная функция. ES6+ (ES2015+)
(x, y) => x + y;
Объявление функции через выражение функции (function expression) без указания имени. Впервые такой способ описан в спецификации стандарта ECMAScript 3[5][6].
// Выражение функции. ES3+
function(x, y) { return x + y }

Динамическое создание функции конструктором объекта Function (Function constructor) всегда объявляется без имени. Более короткая запись динамического создания функции — вызов функции Function, который автоматически вызывает конструктор Function с теми же параметрами. Эти способы создания функций существуют с самых ранних спецификаций, начиная с ECMAScript первой редакции[7][8].

// Динамическое создание функции конструктором Function. ES1+
new Function('x', 'y', 'return x + y')

// Более короткая запись. ES1+
Function('x', 'y', 'return x + y')
Lua
function(x,y) return x+y end
Maple
(x, y) -> x + y
Mathematica
#1+#2&

или

Function[#1+#2]

или

Function[{x,y},x+y]
[9][10]
MATLAB
f=@(x,y) x+y
Maxima
lambda([x,y], x+y)
Nim
proc(x,y: int): int = x*y
PascalABC.NET
(x, y) -> x + y
Perl
sub { return $_[0] + $_[1] }
[11]
PHP
// PHP 7.4+
fn($x, $y) => $x + $y;

Стрелочные функции (Arrow Functions) добавлены в PHP 7.4[12].

// PHP 5.3+
function($x, $y) use ($a, &$b) { return $x + $y; }

Здесь $a, $b — захваченные переменные, при этом переменная $b ещё и замкнутая[13][14].

// PHP 4.0.1+
create_function('$x, $y', 'return $x + $y;')

Создание анонимной функции с помощью функции create_function[15]. Такой способ объявлен устаревшим, начиная с PHP 7.2.0.

PowerShell
{ param($x, $y) $x + $y }
[16]
Python
lambda х, у: х+у
[17]
R
function(x,y) x+y
Ruby
lambda { |x, y| x + y }
[18]
Rust
| x: i32, y: i32 | x + y
Scala

Без указания контекста надо указывать тип переменных:

(x: Int, y: Int) => x + y

Но в местах, где тип может быть выведен, можно использовать сокращенные формы:

(1 to 100) reduce ((a, b) => a+b)

Или ещё короче, с использованием автоподстановок '_':

(1 to 100) reduce (_ + _)
Scheme, Common Lisp
(lambda (x y) (+ x y))
SML
fn (x, y) => x + y
Swift
    // 1 вариант
    let f: (Int, Int) -> Int = { x, y in return x + y }
    
    // 2 вариант
    let f: (Int, Int) -> Int = { x, y in x + y }
    
    
    /* С сокращенными именами параметров */
    // 1 вариант
    let f: (Int, Int) -> Int = { return $0 + $1 }
    
    // 2 вариант
    let f: (Int, Int) -> Int = { $0 + $1 }
TypeScript
// Стрелочная функция (arrow function expression) всегда объявляется без имени
(x, y) => x + y

// Выражение функции (function expression) без имени
function(x, y) { return x + y }

// Динамическое создание функции
// контруктором объекта Function (Function constructor)
// всегда объявляется без имени
new Function('x', 'y', 'return x + y')

// Более короткая запись динамического создания функции.
// Вызов функции Function автоматически вызывает
// конструктор Function с теми же параметрами
Function('x', 'y', 'return x + y')
Visual Prolog
{(X,Y)=X+Y}

См. также[править | править код]

Примечания[править | править код]

  1. анонимные функции.
  2. C++11. Лямбда-выражения
  3. Sutter, Herb Trip Report: ISO C++ Spring 2013 Meeting. isocpp.org (20 April 2013). Дата обращения 14 июня 2013.
  4. Стрелочные функции (HTML). MDN web docs. Mozilla Developer Network. Дата обращения 27 сентября 2019. Архивировано 19 августа 2019 года.
  5. ECMAScript Language Specification. Edition 3 Final (англ.) (PDF). Архив mozilla.org P. 79. Switzerland, CH-1204 Geneva, 114 Rue du Rhône: ECMA (24 March 2000). — Спецификация стандарта ECMAScript (ECMA-262). Третья редакция. Дата обращения 27 сентября 2019.
  6. Функции в JavaScript (HTML). MDN web docs. Mozilla Developer Network. Дата обращения 27 сентября 2019. Архивировано 3 сентября 2019 года.
  7. ECMAScript. A general purpose, cross-platform programming language (англ.) (PDF). Архив mozilla.org P. 63-64. Switzerland, CH-1204 Geneva, 114 Rue du Rhône: ECMA (June 1997). — Спецификация стандарта ECMAScript (ECMA-262). Первая редакция.. Дата обращения 27 сентября 2019.
  8. Function (HTML). MDN web docs. Mozilla Developer Network. — Описание объекта-функции Function и конструктора Function для динамического создания функций.. Дата обращения 27 сентября 2019. Архивировано 23 сентября 2019 года.
  9. Mathematica Documentation: Function (&) Архивировано 5 апреля 2008 года.
  10. Function (&). Wolfram Language & System - Documentation Center. Wolfram.
  11. perldoc perlref (англ.)
  12. PHP-Дайджест № 152 (11 – 25 марта 2019)
  13. M. Zandstra, “PHP Objects, Patterns, and Practice”, second edition, Ed. Apress, 2008.
  14. PHP Manual
  15. PHP Manual
  16. Simplifying Data Manipulation in PowerShell with Lambda Functions.
  17. Раздел учебника «Освой Python за 24 часа самостоятельно» Архивировано 30 апреля 2006 года.
  18. Описание в книге «Programming Ruby» Архивировано 11 апреля 2006 года. (англ.)