<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ko">
		<id>https://tcatmon.com/w/index.php?action=history&amp;feed=atom&amp;title=%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98</id>
		<title>고차 함수 - 편집 역사</title>
		<link rel="self" type="application/atom+xml" href="https://tcatmon.com/w/index.php?action=history&amp;feed=atom&amp;title=%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98"/>
		<link rel="alternate" type="text/html" href="https://tcatmon.com/w/index.php?title=%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98&amp;action=history"/>
		<updated>2026-04-30T06:26:58Z</updated>
		<subtitle>이 문서의 편집 역사</subtitle>
		<generator>MediaWiki 1.28.0</generator>

	<entry>
		<id>https://tcatmon.com/w/index.php?title=%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98&amp;diff=829528&amp;oldid=prev</id>
		<title>2017년 2월 7일 (화) 11:57에 Maintenance script님의 편집</title>
		<link rel="alternate" type="text/html" href="https://tcatmon.com/w/index.php?title=%EA%B3%A0%EC%B0%A8_%ED%95%A8%EC%88%98&amp;diff=829528&amp;oldid=prev"/>
				<updated>2017-02-07T11:57:54Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;새 문서&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[목차]&lt;br /&gt;
&lt;br /&gt;
== 정의 ==&lt;br /&gt;
어떤 함수 F가 하나 이상의 인자(argument)로서 함수를 받거나, 결과값(return value)으로 함수를 돌려주는 경우 그 함수 F를 고차 함수라고 한다. 아래 [[JavaScript|자바스크립트]] 예제들을 보자.&lt;br /&gt;
-----&lt;br /&gt;
[anchor(정의예제1)](1) 아래에서 함수 {{{#green apply}}}는 함수를 인자로 받으므로 '''고차 함수'''이다.{{{#!syntax javascript&lt;br /&gt;
function inc(n) {&lt;br /&gt;
  return n + 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function apply(f, v) {&lt;br /&gt;
  return f(v);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const m = apply(inc, 9);    // m = 10&lt;br /&gt;
}}}&lt;br /&gt;
----&lt;br /&gt;
[anchor(정의예제2)](2) 아래에서 함수 {{{#green greeting}}}은 함수를 결과값으로 돌려주고 있으므로 '''고차 함수'''이다.{{{#!syntax javascript&lt;br /&gt;
function greeting(msg) {&lt;br /&gt;
  return function(who) {&lt;br /&gt;
    return `${msg}! ${who}`;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const hello = greeting(&amp;quot;hello&amp;quot;);&lt;br /&gt;
const helloToAlice = hello(&amp;quot;alice&amp;quot;);         // helloToAlice = &amp;quot;hello! alice&amp;quot;&lt;br /&gt;
&lt;br /&gt;
const annyeong = greeting(&amp;quot;안녕&amp;quot;);&lt;br /&gt;
const annyeongToAlice = annyeong(&amp;quot;alice&amp;quot;);   // annyeongToAlice = &amp;quot;안녕! alice&amp;quot;&lt;br /&gt;
}}}&lt;br /&gt;
----&lt;br /&gt;
[anchor(정의예제3)](3) 아래에서 함수 {{{#green curry}}}는 함수를 인자로 받고 또 결과값으로 함수를 돌려준다. 따라서 '''고차 함수'''이다.{{{#!syntax javascript&lt;br /&gt;
function add(a, b) {&lt;br /&gt;
  return a + b;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function curry(f, a) {&lt;br /&gt;
  return function(b) {&lt;br /&gt;
    return f(a, b);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const add7 = curry(add, 7);&lt;br /&gt;
const retval = add7(8);         // retval = 15&lt;br /&gt;
}}}&lt;br /&gt;
&lt;br /&gt;
== 관련 개념 ==&lt;br /&gt;
=== 익명 함수 (Anonymous function) ===&lt;br /&gt;
명칭 그대로 이름을 갖지 않는 함수이다. 위의 고차 함수 정의 섹션의 [[#정의예제2|예제 (2)]]의 함수 greeting과 [[#정의예제3|예제 (3)]]의 함수 curry가 {{{#green 결과값으로서 돌려주는 함수}}}같은 것들이 바로 익명 함수다. 더 자세한 내용은 별도의 [[람다식|익명 함수]] 문서를 참조하자.&lt;br /&gt;
=== 일차 함수 (First-order function) ===&lt;br /&gt;
일차 함수는 고차 함수를 제외한 모든 함수를 가리킨다. 위의 고차 함수 정의 섹션의 [[#정의예제1|예제 (1)]]의 함수 {{{#green inc}}}, [[#정의예제2|예제 (2)]]의 함수 {{{#green hello}}}와 {{{#green annyeong}}} 그리고 [[#정의예제3|예제 (3)]]의 함수 {{{#green add}}} 및 {{{#green add7}}}은 고차 함수가 아니므로 일차 함수이다.&lt;br /&gt;
=== 일등급 시민으로서의 함수 (Function as first-class citizen) ===&lt;br /&gt;
일등급 함수(First-class function)이라고도 한다. 어떤 [[프로그래밍 언어]]가 함수를 인자로 전달하고, 결과값으로 반환하고, 변수에 대입하는 등의 행위를 허용할 때 그 언어가 &amp;quot;함수를 일등급 시민으로서 대접한다&amp;quot;라고 말한다.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 활용[* 예제들은 [[C++]]로 쓰여졌다. 이 문서를 보는 사람들 중에는 명령형 프로그래밍의 관점을 가지신 분들이 더 많으리라 예상되어 --번잡하고 추한 문법에도 불구하고-- 부득이하게 [[C++]]를 골랐다. 양해 바랍니다.] ==&lt;br /&gt;
[[함수]]나 [[수|수(數)]]를 어떻게 활용할 것인가를 생각해보면 그 가능성은 무궁무진하다. '''고차''' 함수 역시 마찬가지다. --아래의 예제들은 무한 속의 한톨 모래알만큼이다.--&lt;br /&gt;
=== 예제 하나 ===&lt;br /&gt;
'''고차 함수'''는 추상화를 좀 더 간편한 방법으로 가능하게 한다. 추상화는 장황하고 반복적인 코드를 줄여준다. 줄어든 코드는 [[프로그래머]]를 인간답게 만든다. 무엇보다도 추상화된 코드는 아름답다. 고차 함수 {{{#green fold}}}[* fold는 우리말로 접는다는 뜻이다. 배열이나 리스트와 같은 선형 데이터 구조를 맨 왼쪽 혹은 맨 오른쪽 원소부터 하나씩 접어 나가는 걸 상상해 보라. 트리나 그래프 등과 같은 비선형 구조도 어디서부터 시작해서 어떠한 순서로 접을지만 규정해 준다면 접지 못할 이유는 없다.]를 직접[* 많은 [[프로그래밍 언어]]들이 언어 내부(internal)에 혹은 라이브러리의 형태로 전형적으로 많이 쓰이는 자료구조에 연계된 고차 함수들(map,fold,filter,partition,group,sort,span,scan,take....)을 제공해 준다. 뿐만 아니라 고차 함수와 고차 함수를 합성(composition)한 고차 함수, 고차 함수와 자주 쓰이는 [[#s-2.2|일차 함수]]를 결합한 함수를 미리 마련해 두고 있다. __물론 고차 함수가 자료 구조와 반드시 연계되어야만 하는 것은 아니다.__] 구현하면서 추상화를 진행해 보자.&lt;br /&gt;
----&lt;br /&gt;
[anchor(추상화예제0)]'''추상화 前''': 정수 배열을 순회하며 총합과 총곱을 구해보자&lt;br /&gt;
{{{#!syntax cpp&lt;br /&gt;
int main(int argc, char** argv) {&lt;br /&gt;
    int array[] = {1,2,3,4,5,6,7,8,9,10};&lt;br /&gt;
    int stop = 10;&lt;br /&gt;
    int sum = 0, product = 1;&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; stop; i++) {&lt;br /&gt;
        sum = sum + array[i];&lt;br /&gt;
        product = product * array[i];&lt;br /&gt;
    }&lt;br /&gt;
    // sum = 55, product = 3628800&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
}}}&lt;br /&gt;
----&lt;br /&gt;
[anchor(추상화예제1)]'''추상화 1단계''': sum과 product 연산을 별도의 함수로 만들어 재활용할 수 있게 하자&lt;br /&gt;
{{{#!syntax cpp&lt;br /&gt;
int sum(int array[], size_t stop, int identity) {&lt;br /&gt;
    int retval = identity;&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; stop; i++)&lt;br /&gt;
        retval = retval + array[i];&lt;br /&gt;
&lt;br /&gt;
   return retval;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int product(int array[], size_t stop, int identity) {&lt;br /&gt;
    int retval = identity;&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; stop; i++)&lt;br /&gt;
        retval = retval * array[i];&lt;br /&gt;
&lt;br /&gt;
   return retval;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char** argv) {&lt;br /&gt;
    int array[] = {1,2,3,4,5,6,7,8,9,10};&lt;br /&gt;
&lt;br /&gt;
    int sum_result      = sum(array, 10, 0);&lt;br /&gt;
      // sum_result = 55&lt;br /&gt;
    int product_result = product(array, 10, 1);&lt;br /&gt;
      // product_result = 3628800&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
}}}&lt;br /&gt;
----&lt;br /&gt;
[anchor(추상화예제2)]'''추상화 2단계''': [[#추상화예제1|추상화 1단계]]의 {{{#green sum}}}과 {{{#green product}}} 함수를 서로 비교해보자. 다른 점은 오직 (+)와 (*)뿐이다. 이제 '''고차 함수'''가 등장할 차례다.&lt;br /&gt;
{{{#!syntax cpp&lt;br /&gt;
// fold 함수는 두개의 정수를 받아 정수를 돌려주는 함수를 &amp;quot;f&amp;quot;라는 파라미터명으로 받는 고차 함수다.&lt;br /&gt;
// 파라미터:&lt;br /&gt;
//   array   : 정수 배열&lt;br /&gt;
//   stop    : 연산의 종착 인덱스(대개는 배열의 길이와 동일할 것이다)&lt;br /&gt;
//   f       : 폴딩(folding)에 사용될 바이너리 함수&lt;br /&gt;
//   identity: 폴딩에 사용될 최초값&lt;br /&gt;
int fold(int array[], size_t stop, int(*f)(int, int), int identity) {&lt;br /&gt;
    int retval = identity;&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; stop; i++)&lt;br /&gt;
        retval = f(retval, array[i]);    // 인자로 받은 f 함수는 이곳에서 쓰인다.&lt;br /&gt;
&lt;br /&gt;
    return retval;&lt;br /&gt;
}&lt;br /&gt;
}}}정의한 고차함수 {{{#green fold}}}를 써먹어 보자.{{{#!syntax cpp&lt;br /&gt;
int sum(int a, int b) { return a + b; }&lt;br /&gt;
int product(int a, int b) { return a * b; }&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char** argv) {&lt;br /&gt;
    int array[] = {1,2,3,4,5,6,7,8,9,10};&lt;br /&gt;
&lt;br /&gt;
    int sum_result = fold(array, 10, sum, 0);&lt;br /&gt;
      // sum_result = 55; 고차 함수인 fold에 sum 함수를 넘겨주었음에 주목하자&lt;br /&gt;
    int product_result = fold(array, 10, product, 1);&lt;br /&gt;
     // product_result = 3628800; 이번엔 함수 fold에 prodct 함수를 넘겨주었다.&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
}}}* {{{#green fold}}} 함수를 별도의 라이브러리로 만들어 놓는다든가 하면 얼마나 편리할까!&lt;br /&gt;
----&lt;br /&gt;
[anchor(예제3)]'''추상화 3단계''': 그런데 [[#추상화예제2|추상화 2단계]]의 {{{#green fold}}} 함수는 정수 배열에 대한 연산만 가능하다. 모든 형의 배열에 대해 가능하도록 추상화해 보자.[* 추상화를 '''적극''' 지원하는 [[프로그래밍 언어]]들은 명칭 그리고 내부구현은 다르지만 [[C++]]의 template과 하는 역할이 사실상 동일한 기능을 제공해 준다.]&lt;br /&gt;
{{{#!syntax cpp&lt;br /&gt;
template&amp;lt;typename T, typename R&amp;gt;  // T는 배열에 들어있는 엘리먼트의 형을, R은 최종 결과값의 형을 대변한다.&lt;br /&gt;
R fold(T array[], size_t stop, R(*f)(R, T), R identity) {&lt;br /&gt;
    R retval = identity;&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; stop; i++)&lt;br /&gt;
        retval = f(retval, array[i]);&lt;br /&gt;
&lt;br /&gt;
    return retval;&lt;br /&gt;
}&lt;br /&gt;
}}}이제 형에 대한 추상화까지 마친 {{{#green fold}}} 함수를 이용해 보자.[anchor(추상화예제3메인)]{{{#!syntax cpp&lt;br /&gt;
#include &amp;lt;string&amp;gt;&lt;br /&gt;
using std::string;&lt;br /&gt;
using std::to_string;&lt;br /&gt;
&lt;br /&gt;
int sum(int a, int b) { return a + b; }&lt;br /&gt;
int product(int a, int b) { return a * b; }&lt;br /&gt;
string stringify(string s, int n) { return s + to_string(n); }&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char** argv) {&lt;br /&gt;
    int array[] = {1,2,3,4,5,6,7,8,9,10};&lt;br /&gt;
&lt;br /&gt;
    int sum_result = fold(array, 10, sum, 0);&lt;br /&gt;
      // sum_result = 55&lt;br /&gt;
    int product_result = fold(array, 10, product, 1);&lt;br /&gt;
      // product_result = 3628800&lt;br /&gt;
    string stringified_result = fold(array, 10, stringify, string(&amp;quot;&amp;quot;));&lt;br /&gt;
      // stringified_result = string(&amp;quot;12345678910&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
}}}&lt;br /&gt;
----&lt;br /&gt;
'''추상화 번외''': [[#추상화예제3메인|추상화 3단계]]의 {{{#green fold}}} 함수와 ({{{#green sum}}}, {{{#green product}}} 그리고 {{{#green stringify}}}) 함수들과 각 연산의 identity를 하나로 묶은 함수들을 만들 수 있진 않을까. [[Closure|클로저(Closure)]]를 이용해 보자.&lt;br /&gt;
{{{#!syntax cpp&lt;br /&gt;
// 파라미터:&lt;br /&gt;
//   f       : 폴딩(folding)에 사용될 바이너리 함수&lt;br /&gt;
//   identity: 폴딩에 사용될 최초값&lt;br /&gt;
template&amp;lt;typename T, typename R&amp;gt;&lt;br /&gt;
auto foldop(R(*f)(R,T), R identity) {&lt;br /&gt;
    // 익명 함수를 반환한다.&lt;br /&gt;
    // 반환되는 익명함수가 자신의 외부 함수인 foldop 함수의 인자들(f, identity)을 품고 있다가 자신이 호출되었을 때 사용함에 주목하자.&lt;br /&gt;
    return [f, identity](T array[], int stop) {&lt;br /&gt;
      return fold(array, stop, f, identity);&lt;br /&gt;
    };&lt;br /&gt;
}&lt;br /&gt;
}}}이제 {{{#green foldop}}} 함수와 그것이 반환하는 [[Closure|클로저]]를 활용해 보자.{{{#!syntax cpp&lt;br /&gt;
int main(int argc, char** argv) {&lt;br /&gt;
    int array_pos[] = {1,2,3,4,5,6,7,8,9,10};&lt;br /&gt;
    int array_neg[] = {-10,-9,-8,-7,-6,-5,-4,-3,-2,-1};&lt;br /&gt;
&lt;br /&gt;
    auto foldsum = foldop(sum, 0);&lt;br /&gt;
    auto foldproduct = foldop(product, 1);&lt;br /&gt;
    auto foldstringify = foldop(stringify, string(&amp;quot;&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
    int sum_pos = foldsum(array_pos, 10);&lt;br /&gt;
      // sum_pos = 55&lt;br /&gt;
    int sum_neg = foldsum(array_neg, 10);&lt;br /&gt;
      // sum_neg = -55&lt;br /&gt;
    int product_pos = foldproduct(array_pos, 10)&lt;br /&gt;
      // product_pos = 3628800&lt;br /&gt;
    int product_neg = foldproduct(array_neg, 10);&lt;br /&gt;
      // product_neg = 3628800&lt;br /&gt;
    string stringified_pos = foldstringify(array_pos, 10);&lt;br /&gt;
      // stringified_pos = string(&amp;quot;12345678910&amp;quot;)&lt;br /&gt;
    string stringified_neg = foldstringify(array_neg, 10);&lt;br /&gt;
      // stringified_neg = string(&amp;quot;-10-9-8-7-6-5-4-3-2-1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
}}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[분류:수학]][[분류:프로그래밍]]&lt;/div&gt;</summary>
		<author><name>Maintenance script</name></author>	</entry>

	</feed>