Функция высшего порядка

Фу́нкция вы́сшего поря́дка — в программировании функция, принимающая в качестве аргументов другие функции или возвращающая другую функцию в качестве результата. Основная идея состоит в том, что функции имеют тот же статус, что и другие объекты данных. Использование функций высшего порядка приводит к абстрактным и компактным программам, принимая во внимание сложность производимых ими вычислений.[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 )";

Примечания

  1. А. Филд, П. Харрисон Функциональное программирование: Пер. с англ. — М.: Мир, 1993. — 637 с, ил. ISBN 5-03-001870-0. Стр. 55 [Глава 3: Функции высшего порядка].
This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.