{{위키데이터 속성 추적}}
'''고차 함수'''(高次函數, {{lang|en|higher-order function}})는 [[수학]]과 [[컴퓨터 과학]]에서 적어도 다음 중 하나를 수행하는 [[함수]]이다.<ref>[http://www.naeil.com/news_view/?id_art=124852 로드맵수학학원 - 수학 공부의 틀을 바꾸는 종횡무진 학습법]. 내일신문. 2014년 10월 17일.</ref><ref>유아영. [http://www.dongascience.com/news.php?idx=7933 PART 01. 의심스러운 토대 위에 싹트다]. 동아사이언스. 2015년 8월 27일.</ref><ref>[http://www.itworld.co.kr/news/97950 함수 언어 : 3대 함수 언어 전문가가 말하는 정체와 역할]. ITWorld. 2016년 2월 19일.</ref>
* 하나 이상의 함수를 인수로 취한다. (예: [[절차적 매개변수]])
* 함수를 결과로 반환한다.

다른 모든 함수들은 일차(first order) 함수이다. 수학에서 고차 함수들은 [[연산자]], [[범함수]]라고도 한다. [[미적분학|미적분]]에서 [[미분 연산자]]가 일반적인 예인데, 그 이유는 함수를 그 [[미분]]에 연결시키기 때문이다.

형식화되지 않은 [[람다 대수]]에서 모든 함수들은 고차 함수이다. 대부분의 [[함수형 프로그래밍]] 언어를 파생시키는 [[형식화된 람다 대수]]에서 하나의 함수를 인수로 취하는 고차 함수들은 <math>(\tau_1\to\tau_2)\to\tau_3</math>의 형태의 값이다.

== 일반적인 예 ==
수많은 함수형 프로그래밍 언어에서 볼 수 있는 <code>[[map]]</code> 함수는 고차 함수의 한 예이다.

== 프로그래밍 언어에서의 지원 ==
=== 직접적인 지원 ===
==== 파이썬 ====
<syntaxhighlight lang="pycon">
>>> def twice(function):
...     return lambda x: function(function(x))

>>> def f(x):
...     return x + 3

>>> g = twice(f)

>>> print g(7)
13
</syntaxhighlight>

====F#====
<syntaxhighlight lang="fsharp">
let twice f = f >> f

let f = (+) 3

twice f 7 |> printf "%A" // 13
</syntaxhighlight>

==== 하스켈 ====
<syntaxhighlight lang="haskell">
twice :: (a -> a) -> (a -> a)
twice f = f . f

f :: Num a => a -> a
f = subtract 3

main :: IO ()
main = print (twice f 7) -- 1
</syntaxhighlight>

==== 클로저 ====
<syntaxhighlight lang="clojure">
(defn twice [function x]
  (function (function x)))

(twice #(+ % 3) 7) ;13
</syntaxhighlight>

==== 스킴 ====
<syntaxhighlight lang="scheme">
(define (add x y) (+ x y))
(define (f x)
  (lambda (y) (+ x y)))
(display ((f 3) 7))
(display (add 3 7))
</syntaxhighlight>

==== 얼랭 ====
<syntaxhighlight lang="erlang">
or_else([], _) -> false;
or_else([F | Fs], X) -> or_else(Fs, X, F(X)).

or_else(Fs, X, false) -> or_else(Fs, X);
or_else(Fs, _, {false, Y}) -> or_else(Fs, Y);
or_else(_, _, R) -> R.

or_else([fun erlang:is_integer/1, fun erlang:is_atom/1, fun erlang:is_list/1],3.23).
</syntaxhighlight>

==== 자바스크립트 ====
<syntaxhighlight lang="javascript">
var twice = function(f, v) {
    return f(f(v));
};

var f = function(v) {
    return v + 3;
};

console.log(twice(f, 7)); // 13
</syntaxhighlight>

==== 고 ====
<syntaxhighlight lang="go">
func twice(f func(int) int, v int) int {
	return f(f(v))
}

func main() {
	f := func(v int) int {
		return v + 3
	}
	twice(f, 7) // returns 13
}
</syntaxhighlight>

==== 스칼라 ====
<syntaxhighlight lang="scala">
def twice(f:Int=>Int) = f compose f

twice(_+3)(7) // 13
</syntaxhighlight>

==== 자바 (1.8 이상) ====
<syntaxhighlight lang="java">
Function<Function<Integer, Integer>, Function<Integer, Integer>> twice = f -> f.andThen(f);
twice.apply(x -> x + 3).apply(7); // 13
</syntaxhighlight>

==== 스위프트 ====
<syntaxhighlight lang="swift">
func f(x: Int) -> Int {
    return x + 3
}

func g(function: (Int) -> Int, paramX: Int) -> Int {
    return function(paramX) * function(paramX)
}

g(function: f, paramX: 7)
</syntaxhighlight>

==== 러스트 ====
<syntaxhighlight lang="rust">
// Take function f(x), return function f(f(x))
fn twice<A, F>(function: F) -> Box<Fn(A) -> A>
    where F: 'static + Fn(A) -> A
{
    Box::new(move |a| function(function(a)))
}

// Return x + 3
fn f(x: i32) -> i32 {
    x + 3
}

fn main() {
    let g = twice(f);
    println!("{}", g(7));
}
</syntaxhighlight>

==== C++ ====
<syntaxhighlight lang="c++">
// Generic lambdas provided by C++14.
#include <iostream>

auto twice = [](auto f, int v)
{
    return f(f(v));
};

auto f = [](int i)
{
    return i + 3;
};

int main()
{
    std::cout << twice(f, 7) << std::endl;
}

// Or, use std::function in C++11
#include <iostream>
#include <functional>

auto twice = [](const std::function<int(int)>& f, int v)
{
    return f(f(v));
};

auto f = [](int i)
{
    return i + 3;
};

int main()
{
    std::cout << twice(f, 7) << std::endl;
}
</syntaxhighlight>

==== 콜드퓨전 마크업 언어 (CFML) ====
<syntaxhighlight lang="cfs">
twice = function(f, v) {
    return f(f(v));
};

f = function(v) {
    return v + 3;
};

writeOutput(twice(f, 7)); // 13
</syntaxhighlight>

==== PHP ====
<syntaxhighlight lang="php">
$twice = function($f, $v) {
    return $f($f($v));
};

$f = function($v) {
    return $v + 3;
};

echo($twice($f, 7)); // 13
</syntaxhighlight>

==== R ====
<syntaxhighlight lang="R">
twice <- function(func) {
  return(function(x) {
    func(func(x))
  })
}

f <- function(x) {
  return(x + 3)
}

g <- twice(f)

> print(g(7))
[1] 13
</syntaxhighlight>

=== XACML ===
<syntaxhighlight lang="java">
rule allowEntry{
    permit
    condition anyOfAny(function[stringEqual], citizenships, allowedCitizenships)
}
</syntaxhighlight>

=== 대안 ===
==== 함수 포인터 ====
<syntaxhighlight lang=c>
#include <stdio.h>

double square(double x)
{
    return x * x;
}

double cube(double x)
{
    return x * x * x;
}

/* Compute the integral of f() within the interval [a,b] */
double integral(double f(double x), double a, double b, int n)
{
    int i;
    double sum = 0;
    double dt = (b - a) / n;
    for (i = 0;  i < n;  ++i) {
        sum += f(a + (i + 0.5) * dt);
    }
    return sum * dt;
}

int main()
{
    printf("%g\n", integral(square, 0, 1, 100));
    printf("%g\n", integral(cube, 0, 1, 100));
    return 0;
}
</syntaxhighlight>

==== 오브젝트 ====
<syntaxhighlight lang=pascal>
program example;

type
  int = integer;
  Txy = record x, y: int; end;
  Tf = function (xy: Txy): int;

function f(xy: Txy): int;
begin
  Result := xy.y + xy.x;
end;

function g(func: Tf): Tf;
begin
  result := func;
end;

var
  a: Tf;
  xy: Txy = (x: 3; y: 7);

begin
  a := g(@f);     // return a function to "a"
  writeln(a(xy)); // prints 10
end.
</syntaxhighlight>

==== 기능상실 ====
<syntaxhighlight lang=cpp>
// Defunctionalized function data structures
template<typename T> struct Add { T value; };
template<typename T> struct DivBy { T value; };
template<typename F, typename G> struct Composition { F f; G g; };

// Defunctionalized function application implementations
template<typename F, typename G, typename X>
auto apply(Composition<F, G> f, X arg) {
    return apply(f.f, apply(f.g, arg));
}

template<typename T, typename X>
auto apply(Add<T> f, X arg) {
    return arg  + f.value;
}

template<typename T, typename X>
auto apply(DivBy<T> f, X arg) {
    return arg / f.value;
}
</syntaxhighlight>

== 같이 보기 ==
* [[함수형 프로그래밍]]
* [[전략 패턴]]

== 각주 ==
{{각주}}

[[분류:고차 함수| ]]
[[분류:함수형 프로그래밍]]
[[분류:람다 대수]]
[[분류:함수 (프로그래밍)]]