람다는 무엇이며 왜 유용합니까? [닫은]


56

지금까지 나는 들었습니다.

  • 람다 미적분학
  • 람다 프로그래밍
  • 람다 식
  • 람다 함수

기능 프로그래밍과 관련된 것 같습니다 ...

분명히 C ++ 1x에 통합 될 것이므로 지금 이해하는 것이 좋습니다.

http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions

누군가 람다 일을 간단히 정의하고 유용 할 수있는 곳을 줄 수 있습니까?


2
역사적으로이 용어는 표현으로 표현 된 기능에 대해 이야기 할 수있는 좋은 방법을 원한다는 점에서 유념하십시오. x + 1로 표시되는 함수는 람다 x로 작성됩니다. x + 1.
kasterma

람다 방식으로, 함수는 다른 함수 및 / 또는 입력 값을 먹고 다른 함수를 생성합니다. 함수가 솔루션을 생성 할 때까지 계속됩니다. 또한 악어 알 .
SD

그것은 나에게 그리스어입니다. 나는 자이로가 갈 것 같아, 나는 양고기를 좋아한다.

답변:


44
  • 람다 미적분학

람다 미적분학은 Alonzo Church가 30 년대에 발명 한 계산 모델입니다. 대부분의 기능적 프로그래밍 언어의 구문과 의미는 람다 미적분에서 직접 또는 간접적으로 영감을 얻습니다.

가장 기본적인 형태의 람다 미적분학에는 추상화 ((익명) 함수 생성) 및 응용 프로그램 (함수 적용)이라는 두 가지 작업이 있습니다. λ 연산자를 사용하여 추상화를 수행하여 람다 미적분학의 이름을 지정합니다.

  • 람다 식
  • 람다 함수

익명 함수는 종종 "lambdas", "lambda functions"또는 "lambda expressions"라고 부릅니다. 위에서 말했듯이 λ는 람다 미적분학에서 익명 함수를 생성하는 상징이기 때문에 lambda많은 단어 에서 익명 함수를 생성하는 데 사용됩니다. 같은 이유로 언어 기반).

  • 람다 프로그래밍

이것은 일반적으로 사용되는 용어는 아니지만 익명 함수를 사용한 프로그래밍 또는 고차 함수를 사용한 프로그래밍을 의미한다고 가정합니다.


C ++ 0x의 람다에 대한 약간의 정보, 동기 부여 및 함수 포인터와의 관련성 (많은 것은 이미 알고있는 것과 반복적이지만 람다의 동기와 차이점을 설명하는 데 도움이되기를 바랍니다. 함수 포인터에서) :

C에 이미 존재하는 함수 포인터는 비교 함수를 정렬 함수에 전달하는 데 매우 유용합니다. 그러나 그 유용성에는 한계가 있습니다.

예를 들어 i각 벡터 의 th 요소 ( i런타임 매개 변수)를 기준 으로 벡터 벡터를 정렬하려는 경우 함수 포인터로이 문제를 해결할 수 없습니다. 두 i요소를 th 요소로 비교하는 함수는 세 개의 인수 ( i및 두 개의 벡터) 를 가져야 하지만 정렬 함수에는 두 개의 인수를 취하는 함수가 필요합니다. 우리가 필요로하는 i것은 정렬 함수에 전달하기 전에 함수에 인수 를 제공하는 방법 이지만 일반 C 함수로는이를 수행 할 수 없습니다.

이를 해결하기 위해 C ++은 "함수 객체"또는 "펑터"라는 개념을 도입했습니다. 펑 터는 기본적으로 operator()방법 이있는 객체입니다 . 이제 클래스를 정의 할 수 있는데 CompareByIthElement,이 인수 i는 생성자 인수로 인수를 취한 다음 두 벡터를 operator()메소드의 인수로 비교합니다 . 에 의해 벡터의 벡터를 정렬하려면 i번째 요소 우리는 지금 만들 수 CompareByIthElement와 객체를 i인수로 다음 정렬 기능에 해당 객체를 전달합니다.

함수 객체는 객체 일뿐 기술적으로 기능하는 것은 아니기 때문에 (함수처럼 동작하도록 의도 된 경우에도) 함수 포인터를 함수 객체로 가리킬 수는 없습니다 (물론 함수 객체에 대한 포인터를 가질 수는 있지만 CompareByIthElement*함수 포인터가 아닌 형식을 가질 것입니다 ).

함수를 인수로 사용하는 C ++ 표준 라이브러리의 대부분의 함수는 함수 객체뿐만 아니라 함수 포인터와도 작동하도록 템플릿을 사용하여 정의됩니다.

이제 람다에게 :

ith 요소 로 비교할 전체 클래스를 정의하는 것은 벡터를 정렬하는 데 한 번만 사용하려는 경우에는 조금 장황합니다. 함수 포인터 만 필요한 경우에도 a) 네임 스페이스를 오염시키고 b) 함수가 일반적으로 매우 작고 실제로 없기 때문에 명명 된 함수를 정의하는 것이 한 번만 사용되는 경우 차선책입니다 논리를 자체 함수로 추상화 해야하는 좋은 이유 (함수를 정의하지 않고 함수 포인터를 가질 수있는 경우 제외).

그래서이 람다를 해결하기 위해 소개되었습니다. 람다는 함수 포인터가 아닌 함수 객체입니다. 람다 리터럴을 사용하면 [x1, x2](y1,y2){bla}기본적으로 다음을 수행하는 코드 와 같은 리터럴 이 생성됩니다.

  1. 두 개의 멤버 변수 ( x1x2)와 operator()인수 ( y1y2) 및 본문 이있는 클래스를 정의하십시오 bla.
  2. 멤버 변수 x1와 변수 x2값을 설정 x1하고 x2현재 범위 내에 있는 클래스의 인스턴스를 만듭니다 .

따라서 람다는 람다를 사용하는 것 이외의 다른 방법으로 람다를 구현하기 위해 생성 된 클래스에 액세스 할 수 없다는 점을 제외하고 함수 객체처럼 동작합니다. 따라서 함수를 인수로 받아들이는 함수 (기본적으로 표준 라이브러리에서 C가 아닌 함수를 의미 함)는 람다를 받아들이지 만 함수 포인터 만 허용하는 함수는 받아들이지 않습니다.


익명 함수는 함수 포인터와 함께 사용됩니까? 그렇지 않다면 차이점은 무엇입니까?
jokoon

1
@ jokoon : 아니요, 익명 함수는 함수 포인터 만 취하는 함수에 매개 변수로 전달할 수 없습니다. 그러나 함수를 인수로 취하는 대부분의 함수는 템플릿을 사용하여 정의되므로 함수 포인터뿐만 아니라 모든 종류의 함수 객체를 인수로 사용할 수 있습니다. 즉, 함수 포인터를 사용할 수있는 대부분의 장소에서 std::sort익명 함수를 대신 사용할 수 있습니다. 그러나 익명 함수를 인수로 사용해야하는 함수를 정의 할 때는 템플릿을 사용하거나 std::function인수 유형으로 사용해야 합니다.
sepp2k

함수 포인터는 람다를 포함 할 수 없습니다.
jokoon

1
+1 훌륭한 설명-나는 그것을 찾을 수 없었습니다.
Michael K

2
나는 마이클과 함께 해요. 이것은 매우 포괄적입니다. +1나에게서.
sbi

18

기본적으로 람다 함수는 "즉석에서"만드는 함수입니다. C ++ 1x에서는 함수형 프로그래밍에 대한 지원을 향상시키는 데 사용할 수 있습니다.

std::for_each( begin, end, [](int i){std::cout << i << '\n';} );

이것은 대략 다음과 비슷한 코드를 생성합니다.

struct some_functor {
  void operator()(int i) {std::cout << i << '\n';}
};

std::for_each( begin, end, some_functor() );

당신이 필요로하는 경우에 some_functor단지이 하나의 호출에 대해 std::for_each(), 그 람다 함수는 그 위에 몇 가지 장점이 있습니다 :

  • 루프에서 수행되는 작업은 루핑 함수가 호출되는 곳에서 바로 지정됩니다.
  • 보일러 플레이트 코드를 작성하지 않아도됩니다.
  • 모든 네임 스페이스 범위에 놓여있는 functor가 없으므로 모든 사람이 코드를보고 무엇이 필요한지 궁금해합니다.

7

람다 함수는 익명 함수의 다른 이름입니다. 기본적으로 이름이없는 함수입니다.

보통이 기능은 한 번만 사용해야하는 언어로 사용합니다. 예를 들어

def add(a, b)
  return a+b

그런 다음 해당 기능을 다른 기능으로 전달하십시오.

reduce(add, [5,3,2])

람다를 사용하면 간단하게 할 수 있습니다.

reduce(lambda x, y: a+b, [5,3,2])
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.