Функция высшего порядка
Фу́нкция вы́сшего поря́дка — в программировании функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата. Основная идея состоит в том, что функции имеют тот же статус, что и другие объекты данных. Использование функций высшего порядка приводит к абстрактным и компактным программам, принимая во внимание сложность производимых ими вычислений.[1]
Пример
Следующий исходный код, написанный на Python, содержит функцию высшего порядка g(), которая в качестве первого аргумента принимает функцию. В результате на экран будет выведено «100» (результат вычисления (7+3)×(7+3)).
def f(x):
return x + 3
def g(function, x):
return function(x) * function(x)
print (g(f, 7))
Та же программа на F#, здесь g — функция высшего порядка, принимающая функцию func в качестве параметра.
let f x = x + 3
let g func x = (func x) * (func x)
System.Console.WriteLine(g f 7)
На C#, здесь g — функция высшего порядка, принимающая функцию func в качестве параметра.
var f = (Func<int, int>)((x) => x + 3);
var g = (Func<Func<int, int>, int, int>)((func, x) => func(x) * func(x));
Console.WriteLine(g(f, 7));
Тот же код, написанный на языке Ruby.
Вариант 1. Использования lambda-объекта.
f = ->(x) { x+3 }
def g (f, x); f.call( x ) * f.call( x ) end
puts g f,7
Вариант 2. Использование блока для подстановки анонимной функции.
def g x; (yield x) * (yield x) end
puts g(7){|x| x+3}
На языке Elixir
defmodule Hop do
def twice(f, v) do
f.(f.(v))
end
end
add3 = fn(v) -> 3 + v end
IO.puts Hop.twice(add3, 7) #13
На Erlang
f(X) ->
X + 3.
g(Fun, X) ->
Fun(X) * Fun(X).
start()->
Result = g(fun f/1, 7),
io:format("~p", [Result]).
На Pascal.
{$mode objfpc}
type fun = function(x:integer):integer;
function f(x:integer):integer;
begin
f:= x+3;
end;
function g( func:fun; x:integer):integer;
begin
g:= func(x)*func(x);
end;
begin
write(g(@f, 7));
end.
На PHP.
<?php
$f = function (int $x): int {
return $x + 3;
};
function g(callable $function, int $x): int
{
return $function($x)*$function($x);
}
print g($f, 7);
На Clojure.
(defn g [f x]
(* (f x) (f x)))
(print (g #(+ 3 %) 7))
На Lua.
local f = function(func, x)
return func(x) * func(x)
end
print(f(function(x) return x + 3 end, 7))
То же самое на Haskell.
f func x = (func x)^2
main = print $ f (+3) 7
На Scala.
Вариант 1. С использованием обычной функции:
def f(x: Int) = x + 3
def g(f: Int ⇒ Int, x: Int) = f(x) * f(x)
println(g(f, 7))
Вариант 2. С использованием анонимной функции:
def g(f: Int ⇒ Int, x: Int) = f(x) * f(x)
println(g(_ + 3, 7))
На Perl:
my $f=sub { $_[0]+3 };
sub g {
$_[0]->($_[1])*$_[0]->($_[1])
}
say g $f,7
На JavaScript
// ES5
var f = function (x) {
return x + 3;
};
var g = function (func, x) {
return func(x) * func(x);
};
console.log(g(f, 7));
// ES6
let f = x => x + 3;
let g = (func, x) => func(x) * func(x);
console.log(g(f, 7));
На языке Swift.
Вариант 1. С использованием обычной функции.
func f(_ x: Int) -> Int {
return x + 3
}
func g(_ function: (Int) -> Int, x: Int) -> Int {
return function(x) * function(x)
}
print(g(f, x: 7))
Вариант 2. С использованием анонимной функции:
let g: (Int, (Int) -> Int) -> Int = { (x, f) in f(x) * f(x) }
print(g(7) { x in x + 3 })
// С сокращенными именами параметров
let g: (Int, (Int) -> Int) -> Int = { $1($0) * $1($0) }
print(g(7) { $0 + 3 })
на nim
proc f(x: int): int =
return x + 3
proc g(function: proc, x: int): int =
return function(x) * function(x)
echo g(f, 7)
И на Java
Function<Integer, Integer> f = x -> x + 3;
BiFunction<Function<Integer, Integer>, Integer, Integer> g = (func, x) -> func.apply(x) * func.apply(x);
System.out.println(g.apply(f, 7));
На Groovy
f = { x -> x + 3 }
g = { func, x -> func(x) * func(x) }
System.out.println(g(f, 7))
На C
int f(int x){ return x + 3; }
int g(int (*func)(int), int x){ return func(x) * func(x); }
printf("%d", g(f, 7));
На C++
int f(int x){ return x + 3; }
template<typename T>
int g(T&& func, int x){ return func(x) * func(x); }
std::cout << g(f, 7);
На C++ с использованием лямбда-функций
auto f = [](auto x){ return x + 3; }
auto g = [](auto f, auto x){ return f(x) * f(x); }
std::cout << g(f, 7);
На D
int f(int x){ return x + 3; }
int g(alias pred, T)(T input) { return pred(input) * pred(input); }
writefln("%d", g!f(7));
На D с использованием лямбда-функций
auto f = (int x) {return x + 3;};
auto g = (int function(int) func, int x) { return func(x) * func(x); };
writefln("%d", g(f, 7) );
На D в функциональном стиле
import std.stdio : writeln;
alias square = (f) => (int x) => f(x)*f(x);
alias plusThree = (int i) => i + 3;
void main()
{
auto g = square(plusThree);
writeln(g(7)); // 100
}
На Scheme
(define (f x)(+ x 3))
(define (g f x)(* (f x) (f x)))
(print (g f 7))
На Kotlin
fun f(x:Int):Int= x+3
fun g(function:(y:Int)->Int, x:Int):Int = function(x)*function(x)
println(g(::f,7))
На Go
func f(x int) int {
return x + 3
}
func g(function func(x int) int, x int) int {
return function(x) * function(x)
}
fmt.Print(g(f, 7))
На Bash
#! /bin/bash
function f(){
X=$1;
echo $(( $X + 3 ));
}
function g(){
FUNCTION=$1;
X=$2;
echo $(( $( ${FUNCTION} ${X} ) * $( ${FUNCTION} ${X} ) ));
}
echo "$( g f 7 )";
Примечания
- А. Филд, П. Харрисон Функциональное программирование: Пер. с англ. — М.: Мир, 1993. — 637 с, ил. ISBN 5-03-001870-0. Стр. 55 [Глава 3: Функции высшего порядка].