Putting the fun back in functional

Code-Stücke können hier veröffentlicht werden.
Antworten
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

Ich hab mal ein Modul angefangen um ein paar Ideen von Haskell nach Python zu bringen. Ich bin mir aber noch nicht sicher, ob sie da sinnvoll sind.

Code: Alles auswählen

class F(functools.partial):
    """Adds function composition to functools.partial.
    E.g. F(map, f) * F(filter, g) ->
    lambda iter: map(f, filter(g, iter))"""

    def __mul__(left, right):
        return F(lambda *args, **kwargs: left(right(*args, **kwargs)))

def flip(f):
    "Takes a function that takes two arguments and returns a function "
    "with the arguments reversed."
    return lambda x, y: f(y, x)

def maybe(value, just_f, none_f):
    "returns just_f(value) if value is not None else none_f()."
    return none_f() if value is None else just_f(value)

def maybe_args(just_f, none_f, *args, **kwargs):
    "returns just_f with all additional arguments if none of them are None "
    "else none_f()"
    return none_f() if (
            any(arg is None for arg in args) or
            any(arg is None for arg in kwargs.values())
        ) else just_f(*args, **kwargs)
Mit der F erweiterung kann man * als Function composition operator verwenden:

Code: Alles auswählen

get_session_id = F(string.rstrip, chars='L') * F(string.lstrip, chars='0x') * F(hex) * F(random.getrandbits, 128)
http://www.felix-benner.com
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Jetzt will ich noch die Currying-Semantik von Haskell haben :D Ich habs mal in Scheme nachgebaut, in Python würde man wohl eine Klasse basteln, die __call__ so überschreibt, dass sie entweder die Funktion aufruft oder eine neue Instanz seiner selbst zurück.

Vielleicht implementiere ich das ja mal beizeiten...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beim Currying gibt es bei Python nur ein sehr ärgerliches Problem. Was macht man (sinnvoll) mit Funktionen, bei denen Default-Werte gegeben sind? Natürlich könnte man, wenn man denn __call__ implementiert, einen Aufruf ohne Parameter tätigen, das sieht aber irgendwie dumm aus. Außer "nicht zulassen" oder Sonderbehandlung einführen fällt mir nichts vernünftiges ein.
Das Leben ist wie ein Tennisball.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Du meinst so was?

Code: Alles auswählen

def curryable(f, n=None):
    if n is None:
        n = len(f.func_code.co_varnames)
    if n > 1:
        return lambda x: curryable(lambda *args: f(x, *args), n - 1)
    return f
        
@curryable
def add(a, b, c):
    return a + b + c
    

print add(3)(4)(6)
Stefan
Antworten