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

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

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

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

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

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

Язык Пример записи сложения
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
PascalABC.NET
(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
Scala

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

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

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

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

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

(1 to 100) reduce (_ + _)
GNU Octave
@(x,y)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
var square = function(number) {return number + number};
[4] В ECMAScript 6 (также известном как ECMAScript 2015) были добавлены Arrow Functions:
(x,y) => x+y;
[5]
Lua
function(x,y) return x+y end
Maple
(x, y) -> x + y
Mathematica
#1+#2&

или

Function[#1+#2]

или

Function[{x,y},x+y]
[6]
MATLAB
f=@(x,y) x+y
Maxima
lambda([x,y], x+y)
Perl
sub { return $_[0] + $_[1] }
[7]
PHP
// PHP 5.3
function($x, $y) use ($a, &$b) { return $x + $y; }

$a, $b - захваченные переменные, при этом переменная $b ещё и замкнутая[8][9].

// PHP 4 >= 4.0.1, PHP 5
create_function('$x, $y', 'return $x + $y;')

[10]

Python
lambda х, у: х+у
[11]
R
function(x,y) x+y
Ruby
lambda { |x, y| x + y }
[12]
Rust
| x: i32, y: i32 | x + y
Scheme, Common Lisp
(lambda (x y) (+ x y))
SML
fn (x, y) => x + y
Visual Prolog
{(X,Y)=X+Y}
Go
    Z := func() int {
        return 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 }

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

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

  1. анонимные функции.
  2. C++11. Лямбда-выражения
  3. Sutter, Herb Trip Report: ISO C++ Spring 2013 Meeting. isocpp.org (20 April 2013). Проверено 14 июня 2013.
  4. Описание в справочнике «Ядро JavaScript»
  5. Arrow functions. Mozilla Developer Network. Проверено 30 декабря 2015.
  6. Mathematica Documentation: Function (&) Архивировано 5 апреля 2007 года.
  7. perldoc perlref (англ.)
  8. M. Zandstra, “PHP Objects, Patterns, and Practice”, second edition, Ed. Apress, 2008.
  9. PHP Manual
  10. PHP Manual
  11. Раздел учебника «Освой Python за 24 часа самостоятельно» Архивировано 30 апреля 2006 года.
  12. Описание в книге «Programming Ruby» Архивировано 11 апреля 2006 года. (англ.)