[lambda] 모두가 계속 말하는이 ‘람다’는 무엇입니까?

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

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



답변

이름없는 기능

간단히 말해 람다는 이름이없는 함수이거나 익명 함수입니다. 변수 인 것처럼 전달할 수있는 작은 실행 코드입니다. 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함수가 결과 (람다)를 반환 한 후에도 해당 매개 변수에 액세스 할 수 있습니다.


답변

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

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

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

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


답변

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

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


답변

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

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


답변

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


답변

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


답변

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

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

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