Frage

Eine reguläre Funktion kann eine Verbindung zu sich selbst in ihrer Definition enthalten, kein Problem. Ich kann nicht herausfinden, wie es mit einer Lambda-Funktion zu tun, wenn auch aus dem einfachen Grunde, dass die Lambda-Funktion keinen Namen zurück zu verweisen hat. Gibt es eine Möglichkeit, es zu tun? Wie?

War es hilfreich?

Lösung

Die einzige Möglichkeit, die ich denken kann, dies zu tun beträgt die Funktion einen Namen zu geben:

fact = lambda x: 1 if x == 0 else x * fact(x-1)

oder alternativ für frühere Versionen von Python:

fact = lambda x: x == 0 and 1 or x * fact(x-1)

Aktualisieren : die Ideen von den anderen Antworten verwendet wird, konnte ich die Fakultäts-Funktion in ein einziges unbenannte Lambda verkeilen:

>>> map(lambda n: (lambda f, *a: f(f, *a))(lambda rec, n: 1 if n == 0 else n*rec(rec, n-1), n), range(10))
[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

So ist es möglich ist, aber nicht wirklich zu empfehlen!

Andere Tipps

ohne reduzieren, Karte, genannt lambdas oder Python-Interna:

(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)

Sie können nicht direkt tun es, weil es keinen Namen hat. Aber mit einer Hilfsfunktion wie die Y-Combinator Lemmy zu spitz, können Sie die Rekursion erstellen, indem Sie die Funktion als Parameter an sich vorbei (so seltsam das auch klingen mag):

# helper function
def recursive(f, *p, **kw):
   return f(f, *p, **kw)

def fib(n):
   # The rec parameter will be the lambda function itself
   return recursive((lambda rec, n: rec(rec, n-1) + rec(rec, n-2) if n>1 else 1), n)

# using map since we already started to do black functional programming magic
print map(fib, range(10))

Dieser druckt die ersten zehn Fibonacci-Zahlen: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55],

Im Gegensatz zu dem was Sache sagen, Sie können dies direkt tun.

(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(n)

Der erste Teil ist das Festpunkt combinator Y , dass erleichtert Rekursion in Lambda-Kalkül

Y = (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))

Der zweite Teil ist die Fakultätsfunktion Tatsache definiert rekursiv

fact = (lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))

Y wird an Tatsache einen weiteren Lambda-Ausdruck bilden

F = Y(fact)

, die auf den dritten Teil angelegt wird, n , die das n-ten faktoriellen evaulates

>>> n = 5
>>> F(n)
120

oder äquivalent

>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: 1 if (i == 0) else i * f(i - 1)))(5)
120

Wenn Sie jedoch lieber fibs Fakten können Sie auch tun, dass die gleiche combinator mit

>>> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(lambda f: (lambda i: f(i - 1) + f(i - 2) if i > 1 else 1))(5)
8

Ja. Ich habe zwei Möglichkeiten, es zu tun, und man war bereits abgedeckt. Dies ist meine bevorzugte Art und Weise.

(lambda v: (lambda n: n * __import__('types').FunctionType(
        __import__('inspect').stack()[0][0].f_code, 
        dict(__import__=__import__, dict=dict)
    )(n - 1) if n > 1 else 1)(v))(5)

Ich habe noch nie Python verwendet, aber diese wahrscheinlich ist das, was Sie suchen.

Diese Antwort ist ziemlich einfach. Es ist ein wenig einfacher als Hugo Walter Antwort:

>>> (lambda f: f(f))(lambda f, i=0: (i < 10)and f(f, i + 1)or i)
10
>>>

Hugo Walter Antwort:

(lambda a:lambda v:a(a,v))(lambda s,x:1 if x==0 else x*s(s,x-1))(10)
def recursive(def_fun):
    def wrapper(*p, **kw):
        fi = lambda *p, **kw: def_fun(fi, *p, **kw)
        return def_fun(fi, *p, **kw)

    return wrapper


factorial = recursive(lambda f, n: 1 if n < 2 else n * f(n - 1))
print(factorial(10))

fibonaci = recursive(lambda f, n: f(n - 1) + f(n - 2) if n > 1 else 1)
print(fibonaci(10))

Hoffe, dass es jemandem nützlich sein würde.

Nun, nicht ganz rein Lambda-Rekursion, aber es ist anwendbar an Orten, wo man nur lambdas verwenden kann, beispielsweise reduzieren, Karte und Listenkomprehensionen oder andere lambdas. Der Trick ist, aus der Liste Verständnis und Python Namen Umfang profitieren. Das folgende Beispiel durchläuft das Wörterbuch durch die gegebene Kette von Schlüsseln.

>>> data = {'John': {'age': 33}, 'Kate': {'age': 32}}
>>> [fn(data, ['John', 'age']) for fn in [lambda d, keys: None if d is None or type(d) is not dict or len(keys) < 1 or keys[0] not in d else (d[keys[0]] if len(keys) == 1 else fn(d[keys[0]], keys[1:]))]][0]
33

Das Lambda wieder verwendet den Namen in der Liste Verständnis Ausdruck (fn) definiert. Das Beispiel ist ziemlich kompliziert, aber es zeigt das Konzept.

Für diese können wir verwenden Festpunkt combinators , speziell Z combinator, weil es wird in strengen Sprachen arbeiten, auch eifrig Sprachen genannt:

const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)))

definieren fact Funktion und ändern Sie es:

1. const fact n = n === 0 ? 1 : n * fact(n - 1)
2. const fact = n => n === 0 ? 1 : n * fact(n - 1)
3. const _fact = (fact => n => n === 0 ? 1 : n * fact(n - 1))

Beachten Sie, dass:

  

Tatsache === Z (_fact)

Und es verwenden:

const Z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));

const _fact = f => n => n === 0 ? 1 : n * f(n - 1);
const fact = Z(_fact);

console.log(fact(5)); //120

Siehe auch: Festpunkt combinators in JavaScript: Memoizing rekursiven Funktionen

Lambda kann leicht ersetzen rekursiven Funktionen in Python:

Zum Beispiel dieser grundlegende compound_interest:

def interest(amount, rate, period):
    if period == 0: 
        return amount
    else:
        return interest(amount * rate, rate, period - 1)

kann ersetzt werden durch:

lambda_interest = lambda a,r,p: a if p == 0 else lambda_interest(a * r, r, p - 1)

oder für mehr Sichtbarkeit:

lambda_interest = lambda amount, rate, period: \
amount if period == 0 else \
lambda_interest(amount * rate, rate, period - 1)

ANWENDUNG:

print(interest(10000, 1.1, 3))
print(lambda_interest(10000, 1.1, 3))

Ausgabe:

13310.0
13310.0

Wenn Sie wirklich masochistisch, könnte Sie in der Lage sein, es zu tun C-Erweiterungen verwenden, aber Greg Echo (hallo Greg!), Dies übersteigt die Fähigkeit eines Lambda (unbenannt, anonym) functon.

Nein. (Für die meisten Werte von no).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top