모두가 계속 말하는이 '람다'는 무엇입니까?


93

모두가 계속 말하는이 '람다'는 무엇입니까? 많은 사람들이 그것을 좋아하는 것 같지만, 내가 모을 수있는 것은 단지 많은 줄의 코드를 하나의 표현식에 넣는 방법뿐입니다.

누군가가 그 진정한 가치에 대해 가르쳐 줄 수 있습니까?


16
질문자가 .net을 언급하지 않는다는 것을 답변자에게 지적 할 수 있습니까?


크래킹 질문. 질문 주셔서 감사합니다.
Peanut

Lambda는 함수형 프로그래밍 (선언적 프로그래밍)의 세계에 속합니다.
RBT

답변:


179

이름없는 기능

간단히 말해 람다는 이름이없는 함수이거나 익명 함수입니다. 변수 인 것처럼 전달할 수있는 작은 실행 코드입니다. JavaScript에서 :

function () {}; // very simple

이제 이러한 람다에 대한 몇 가지 용도를 살펴 보겠습니다.

상용구 코드 추상화

Lambda는 상용구 코드를 추상화하는 데 사용할 수 있습니다. 예를 들어 루프. 우리는 하루 종일 쓰기 forwhile반복에 익숙합니다 . 그러나 이것은 작성되지 않은 코드입니다. 루프의 가장 중요한 부분 인 루프 내부의 코드를 추출하고 나머지는 추상화 할 수 있습니다.

for (var i=0; i<array.length; i++) {
    // do what something useful with array[i]
}

forEach배열 객체 를 사용하면 다음 과 같습니다.

array.forEach(function (element, index) {
   // do something useful with element
   // element is the equivalent of array[i] from above
});

위의 추상화는 그다지 유용하지 않을 수 있지만 forEach훨씬 더 유용한 작업을 수행하는 다른 고차 함수 (예 :)가 있습니다. 예 filter:

var numbers = [1, 2, 3, 4];
var even    = [];

// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
        even.push(numbers[i]);
    }
}

alert(even);

// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
    return number % 2 === 0;
});

alert(even);

코드 실행 지연

이벤트 개념을 사용할 수있는 일부 환경에서는 람다를 사용하여 특정 시점에 발생할 수있는 이벤트에 응답 할 수 있습니다.

window.onload = function () {
    alert("Loaded");
};

window.setTimeout(function () {
    alert("Code executed after 2 seconds.");
}, 2000);

이것은 다른 방법으로 수행 될 수 있지만 다소 장황합니다. 예를 들어, Java에는 Runnable인터페이스가 있습니다.

기능 공장

이 시점까지 우리는 대부분의 구문 설탕 기능에 람다 만 사용했습니다. 그러나 람다가 훨씬 더 유용 할 수있는 상황이 있습니다. 예를 들어 람다를 반환하는 함수가있을 수 있습니다. 반환 값을 캐시 할 함수가 있다고 가정 해 보겠습니다.

var users = [];
var getUser = function (name) {
    if (! users[name]) {
        // expensive operations to get a user. Ajax for example
        users[name] = user_from_ajax;
    }

    return users[name];
};

나중에 유사한 기능이 있음을 알 수 있습니다.

var photos = [];
var getPhoto = function (name) {
    if (! photo[name]) {
        // expensive operations to get a user. Ajax for example
        photos[name] = photo_from_ajax;
    }

    return photos[name];
};

거기에 분명히 패턴이 있으므로 추상화합시다. 메모 화를 사용합시다 .

/**
 * @param {Array}     store Data structure in which we cache lambda's return values
 * @param {Function}  lambda
 * @return {Function} A function that caches the result of calling the lambda param
 */
var memoize = function (store, lambda) {
    // return a new lambda
    return function (name) {
        if (! store[name]) {
            // Execute the lambda and cache the result
            store[name] = lambda(name);
        }

        return store[name];
    };
};

var getUsers = memoize([], function (name) {
    // expensive operations to get a user. Ajax for example
});

var getPhotos = memoize([], function (name) {
    // expensive operations to get a photo. Ajax for example
});

보시다시피 람다를 사용하여 캐싱 / 메모리 화 논리를 추상화 할 수있었습니다. 다른 예에 대해 몇 가지 해결 방법이 있다면이 특정 문제는 다른 기술을 사용하여 거의 해결되지 않는다고 생각합니다. 우리는 몇 가지 중요한 상용구 코드를 한곳으로 추출했습니다. users그리고 photos전역 변수를 제거했다는 것은 말할 것도 없습니다 .

프로필을 살펴보면 대부분 Python 사용자라는 것을 알 수 있습니다. 위 패턴의 경우 Python에는 데코레이터 개념이 있습니다. 메모 데코레이터를 위한 많은 예제가 인터넷에 있습니다. 유일한 차이점은 Python 에서는 데코레이터 함수 내에 명명 된 중첩 함수 가있을 가능성이 높다는 것 입니다. 그 이유는 파이썬이 단일 표현식 람다 만 지원하기 때문입니다. 그러나 개념은 동일합니다.

Python 람다 사용의 예입니다. 짝수를 필터링 한 위의 코드는 다음과 같이 Python으로 나타낼 수 있습니다.

filter(lambda x: x % 2 == 0, [1, 2, 3, 4])

어쨌든 람다는 클로저 없이는 그렇게 강력하지 않습니다. 클로저는 람다의 개념을 강력하게 만드는 것입니다. 내 메모 화 예제에서는 클로저를 사용하여 store매개 변수 주위에 클로저를 생성했습니다 . 이렇게하면 memoize함수가 결과 (람다)를 반환 한 후에도 해당 매개 변수에 액세스 할 수 있습니다.


3
와우 당신은 그것에 많은 시간을 투자했습니다.
mk12

4
@ Mk12, 실제로 답변을 작성하는 것은 아닙니다. 내가 :) 시작한 이후이 물건을 학습, 그래, 시간이 좀 지났
누트 G. 스탠

좋은 대답이지만 "기능적 인터페이스"에 대한 정보가 누락되었습니다 (Java 관점에서).
djangofan 2013-08-02

"추상 상용구 코드"에서 "==="연산자는 무엇입니까?
Don


19

"람다"라는 용어는 익명 함수, 일반적으로 클로저 를 가리키는 데 사용됩니다 . 불필요하게 코드를 부 풀리지 않고 다른 함수를 사용하는 함수를 작성할 수 있기 때문에 유용합니다. 예를 들어, Ruby에서 :

(1..100).select {|num| num % 2 == 0}

이렇게하면 1에서 100 사이의 짝수를 포함하는 배열이 생성됩니다. 명시적인 루프를 작성할 필요가 없습니다. select 메서드는 값을 테스트하는 데 사용하는 함수를 사용하므로 사용자 지정 논리 만 있으면됩니다. 이를 통해 실질적으로 노력이나 오버 헤드없이 메서드를 크게 사용자 지정할 수 있습니다. 기본적으로 더 작은 함수로 함수를 구성 할 수 있습니다.

이는 그들이 할 수있는 일의 쉬운 예일뿐입니다. 함수를 데이터로 전달할 수있는 능력은 정말 강력하고 기능적인 언어 프로그래머는 일상적으로 정말 놀라운 일을합니다.


6
파이프 안에있는 것이 매개 변수라고 추가해야 할 수도 있습니다. 나는 루비를 읽는 데 어려움을 겪는 사람들 중 하나입니다.
Skurmedel

이것은 좋은 대답입니다. Ionut이 내 투표를받은 유일한 이유는 그가 왜 우리가 람다에 대해 (상세하게) 관심을 가져야 하는지를 알려주기 때문입니다.
Frank Shearar

나는 람다가 보통 클로저라는 것에 동의하지 않을 것입니다.
jwg

6

"람다"가 너무 적을 수도 있습니다. Lambda 미적분을 살펴보십시오 . 함수형 프로그래밍에 유용합니다.

함수형 프로그래밍은 절차 적 또는 객체 지향과 같은 또 다른 프로그래밍 패러다임입니다.


5
그런 다음 사람들은 "Lambda"에 대해 이야기합니다. 대부분은 익명 함수, 함수 포인터, 클로저 또는 이와 유사한 것을 말합니다. 실제 람다 미적분을 거의 언급하지 않습니다.
J-16 SDiZ

람다 미적분에 대해 언급 해주셔서 감사합니다.! +1.
RBT

5

.NET의 Lambda는 종종 "구문 설탕"이라고합니다. 기능에 직접적인 영향을주지는 않지만 사람들이 사용하기 쉽게 언어를 만듭니다.

그것들을 사용하는 힘을 이해했다면 델리게이트 / 익명 메서드를 사용하는 이전 스타일 방식에 비해 적은 코드를 작성하게 될 것입니다.


1
나는 아무도 .NET을 언급하지 않았다고 생각하므로 OP는 아마도 더 일반적인 대답으로 더 나을 것입니다.
molf

2
그래서 .net에 대한 답변으로 명확히했습니다. 다른 사람들이 언어 구현에 대해 우는 소리를 낸다면 Q & A는 언어 선택에 관계없이 많은 사람들을 도울 것입니다.
redsquare

이 답변은 람다에 대해 들어 본 것처럼 읽지 만 아직 이해하지 못합니다.
jwg

2

Dobbs Journal 박사 는 람다 식을 소개 하는 유용한 기사를 제공합니다 (C ++의 맥락에서하지만 원칙을 모든 언어에 적용 할 수 있다고 생각합니다).

기사에서 "람다 식은 별도의 클래스 / 함수 정의가 필요없는 매우 간결한 식입니다."

따라서 작성하는 대신 DDJ 의 목록 1 및 2의 예를 사용하십시오 .

std::for_each( vec.begin(), vec.end(), print_to_stream<std::string>(std::cout));

다음과 같은 별도의 클래스 정의가 필요합니다.

template <typename T, typename Stream> class print_to_stream_t {
  Stream& stream_;
public:
  print_to_stream_t(Stream& s):stream_(s) {}
  void operator()(const T& t) const {
    stream_ << t;
  }
};
template <typename T,typename Stream> 
print_to_stream_t<T,Stream>   print_to_stream(Stream& s) {
  return print_to_stream_t<T,Stream>(s);
}

Boost 람다 라이브러리를 사용하면 다음과 같이 될 수 있습니다.

std::for_each(vec.begin(),vec.end(),std::cout << _1);

정의를 인라인으로 유지합니다.

이 기사에서는 람다 식의 몇 가지 응용 프로그램에 대해서도 설명합니다.

DDJ 기사의 요점 은 "일반적으로 람다 식은 호출 사이트에서 작고 지나치게 복잡하지 않은 함수가 필요할 때 사용됩니다. 함수가 사소하지 않은 경우 람다식이 아닌 일반 함수 또는 함수 객체. "


2

함수 포인터, 델리게이트, 전략 또는 관찰자 패턴 / 이벤트 처리를 사용하는 함수 / 메서드로 작업 한 적이 있고 "이 전체 함수를 한 번만 사용하기 위해 작성하고 있습니다.이 메서드에 전달하기 위해 ; 코드를 어지럽히 지 않고 제자리에 작성하면 좋겠습니다. "-Lambda 함수를 사용할 수 있습니다. 이 구조를 지원하는 언어는 일반적으로 특히 목록 작업과 관련하여 함수를 매개 변수로 전달하는 개념을 많이 활용합니다 (1 급 함수 및 고차 함수). 계산을 위해 메모리 수정보다는 함수 구성에 의존하는 함수 언어의 경우 특히 그렇습니다. 경우에 따라 (Python과 같은 언어)


2

'람다'qua 단어는 컴퓨터 과학 유형이 컴퓨터 과학 학위를 가진 것보다 수학 또는 논리에 대해 훈련 될 가능성이 높았던 시대의 용어입니다. 그들 중 일부는 '기능적 프로그래밍'이라는 패러다임을 만들었는데, 명령형과는 상당히 다르고 매우 강력했습니다. 용어가 사용 된 환경 인 AFAIK .

수학자와 논리학자는 이상한 단어를 사용합니다.

'람다'는 정말 난해하게 들립니다. 마치 아주 이상하고 특별한 것 같습니다. 실제로 웹 브라우저 애플리케이션 용 JavaScript를 작성하고 "var foo = function () {...}"관용구를 사용한다면 람다 함수를 계속 사용하고있는 것입니다.


1

람다 식은 간단한 형태의 함수입니다. 아이디어는 왼쪽에있는 형식 (매개 변수와 동일)이 오른쪽에있는 형식 (본문과 동일)이되는 것입니다.

예를 들어, c sharp에서 :

x => x * x

값을 제곱하는 람다입니다. 형태의 무언가

x

형태가된다

x * x

0

"람다 식은 식과 문을 포함 할 수있는 익명 함수이며 대리자 또는 식 트리 유형을 만드는 데 사용할 수 있습니다.

모든 람다 식은 "goes to"로 읽히는 람다 연산자 =>를 사용합니다. 람다 연산자의 왼쪽은 입력 매개 변수 (있는 경우)를 지정하고 오른쪽에는 식 또는 문 블록이 있습니다. 람다 식 x => x * x는 "x가 x x x가됩니다"로 읽습니다.

에서 MSDN


4
예, Microsoft는 모든 사람이 자신이 발명했다고 생각하게 만듭니다. 하지만 Lambda 표현식은 Microsoft보다 앞서 있습니다. 여러 프로그래밍 언어에 적용되는 수학 용어입니다. (수학은 그 자체로 컴퓨터 언어로 간주 될 수 있기 때문에 어느 것이 가능합니다.)
빔 열 직전

4
이것은 Microsoft의 .Net 구현에만 해당됩니다. 람다의 일반적인 아이디어와 크게 다르지는 않지만 Lisp에서 구현 된 기능이 더 "표준"이라고 생각합니다.
Chuck

2
그 대답은 Lambda가 무엇인지 (익명 함수, 델리게이트, 표현식 트리 유형의 정의가 필요함) 전혀 설명하지 않으며 그 값이 무엇인지 확실히 설명하지 않습니다.
danio 09.07.06

0

Lambda 표현식에 대한 자세한 설명은 Wikipedia를 참조하십시오 . ( Lambda 미적분 및 프로그래밍 언어 부분으로 스크롤하십시오 .) Lambda 표현식은 그다지 새로운 것이 아니며 C #의 일부가 아니라 거의 80 년 전에 컴퓨팅에 도입 된 것입니다! Lambda 표현식은 함수형 프로그래밍의 기초입니다.

가치? 글쎄요, 그것이 실제로 꽤 오래되었다는 것을 고려하면, 저는 계산을하는 모든 사람에게 매우 가치 있다고 말할 것입니다.


0

Java를 사용하는 경우 지난 두 달 동안 람다 또는 클로저에 대해 많이 들었습니다.이 기능을 Java 7에 추가하기위한 다른 제안이 있었기 때문입니다. 그러나위원회에서 삭제 한 것 같습니다. 제안 중 하나는 Neal Gafter의 제안이며 여기에 자세히 설명되어 있습니다 : javac.info . 이것은 사용 사례와 장점 (특히 내부 클래스에 비해)을 이해하는 데 도움이되었습니다.




-1

예, 여러 줄의 코드를 하나의 표현식으로 압축하는 방법 일뿐입니다. 그러나 매우 효율적인 크 래밍이므로 프로그램을 구성하는 새로운 방법을 사용할 수 있습니다.

종종 델리게이트 또는 콜백 작성을 피하고 단순히 단일 표현식에 대해 새 함수 나 클래스를 선언하는 데 너무 많은 작업이 필요하기 때문에 절차 스타일로 되돌릴 수 있습니다.

Lambda 표현식을 사용하면 아주 작은 작업에도 콜백을 사용할 수 있으므로 코드가 더 명확해질 수 있습니다. 그렇지 않을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.