2010-02-18 7 views
10

Не имея их использовать все это, я не совсем уверен, что все, что lambdas/blocks могут использоваться для (кроме map/collect/do/lightweight local function syntax). Если бы некоторые люди могли опубликовать некоторые интересные, но несколько понятные примеры (с объяснением).Fun with Lambdas

предпочтительные языки для примера: питон, Smalltalk, Haskell

ответ

2

Вы можете сделать функциональную структуру данных из лямбды. Вот простой один - функциональный список (Python), поддержка add и contains методы:

empty = lambda x : None 

def add(lst, item) : 
    return lambda x : x == item or lst(x) 

def contains(lst, item) : 
    return lst(item) or False 

Я просто закодированные это быстро для удовольствия - обратите внимание, что вы не разрешается добавлять falsy значения, как есть. Он также не является хвостовым рекурсивным, поскольку должна быть хорошая функциональная структура. Упражнения для читателя!

+0

изменит его работу? def содержит (lst, item): return lst (item) or None –

2

Вы можете использовать их для управления потоком. Например, в Smalltalk метод ifTrue: ifFalse: является методом для логических объектов с другой реализацией в каждом из классов True и False. Выражение

someBoolean ifTrue: [self doSomething] ifFalse: [self doSomethingElse] 

использует два затворы --- блоков, в [квадратных скобках] в Smalltalk синтаксис --- один для истинной ветви, и один для ложной ветви. Реализация «ifTrue: ifFalse:» для экземпляров класса ИСТИНА

ifTrue: block1 ifFalse: block2 
    ^block1 value 

и для класса Ложный:

ifTrue: block1 ifFalse: block2 
    ^block2 value 

Затворы, здесь, используются для задержки оценки, с тем, что решение о потоке управления может быть принято, без какого-либо специализированного синтаксиса вообще (кроме синтаксиса для блоков).

Haskell немного отличается, его ленивая модель оценки эффективно автоматически производит эффект закрытия во многих случаях, но на Схеме вы в конечном итоге используете lambdas для управления потоком. Например, здесь это утилита для извлечения значения из ассоциации-списка, снабжая необязательно-вычисленный по умолчанию в случае, когда значение нет:

(define (assq/default key lst default-thunk) 
    (cond 
    ((null? lst) (default-thunk)) ;; actually invoke the default-value-producer 
    ((eq? (caar lst) key) (car lst)) 
    (else (assq/default key (cdr lst) default-thunk)))) 

Это будет называться так:

(assq/default 'mykey my-alist (lambda() (+ 3 4 5))) 

Ключом здесь является использование лямбда для задержки вычисления значения по умолчанию, пока не станет известно, что это требуется.

См. Также продолжение-прохождение-стиль, который делает это до крайности. Например, Javascript полагается на продолжение и стиль закрытия, чтобы выполнять все свои блокирующие операции (такие как спящий режим, ввод-вывод и т. Д.).

ETA: Где я сказал закрытие выше, я имею в виду лексической область видимости закрытия. Часто это лексический масштаб.

+0

Не могли бы вы добавить описание лексической области? –

+0

@Roman: Лексическая область видимости означает, что если у вас есть функция типа 'f: = a -> (x -> (a ++) * x)', то вызов 'f (2)' вернет функцию 'x - > (a ++) * x' с 'a' связан с переменной, которая имеет значение 2. Потому что это' a' из области, где функция была определена в лексическом смысле. Это 'a', однако, полностью не зависит от' a' в функции, возвращаемой 'f (3)' или другим вызовом 'f (2)', поскольку каждый вызов создает новое закрытие. –

1

Вы можете использовать лямбда для создания Y Combinator, то есть функцию, которая принимает другую функцию и возвращает рекурсивную форму.Вот пример:

def Y(le): 
    def _anon(cc): 
     return le(lambda x: cc(cc)(x)) 
    return _anon(_anon) 

Это мысль дубинка что заслуживает большего объяснения, но вместо того, пересказывают его здесь проверить this blog entry (выше образец приходит оттуда тоже).

0

Пример в Haskell вычислить производную от одной variabled функции с использованием численной аппроксимации:

deriv f = \x -> (f (x + d) - f x)/d 
    where 
    d = 0.00001 

f x = x^2 
f' = deriv f -- roughly equal to f' x = 2 * x 
1

Его C#, но я лично получаю удовольствие от этой статьи каждый раз, когда я прочитал:

Building Data out of Thin Air - реализация функций Лисса, автомобиля и cdr в C#. Он показывает, как полностью построить структуру данных стека из лямбда-функций.

1

Это на самом деле не достаточно той же концепции, что и в Haskell и т.д., но в C#, лямбда конструкция имеет (необязательно) возможность компилировать к objcet модель, представляющую код (выражение-деревья), а чем сам код (это само по себе является одним из краеугольных камней LINQ).

Это, в свою очередь, может привести к очень выразительных мета-программирования возможностей, например (где лямбда здесь, выражающие «данной услуги, что вы хотите с ним делать?»):

var client = new Client<ISomeService>(); 
string captured = "to show a closure"; 
var result = client.Invoke(
    svc => svc.SomeMethodDefinedOnTheService(123, captured) 
); 

(предполагая подходящую подпись Invoke)

Существует много применений для этого типа вещей, но я использовал его для создания стека RPC, который не требует генерации кода во время выполнения - он просто анализирует выражение- дерево, определяет, что задумал вызывающий, переводит его в RPC, вызывает его, собирает ответ и т. д. (подробнее обсуждается here).