9
votes

Combinaison de fonction Pointfree en Python

J'ai des prédicats, par exemple: xxx pré>

et veulent les combiner logiquement comme dans: p> xxx pré>

La question est maintenant: Cette combinaison peut-elle être écrite dans un style PointFree , tel que: P>

P(is_divisible_by_13).and_(is_palindrome)


2 commentaires

On dirait que vous essayez terriblement difficile de faire une langue non fonctionnelle se comporter comme une langue fonctionnelle. Êtes-vous attaché à Python?


@Eric: oui, genre de. Mon code Python est intégré dans un projet C ++ et je ne peux pas simplement passer à une autre langue.


5 Réponses :


10
votes

Vous pouvez remplacer l'opérateur & CODE> (BITWWITER ET ) en Python en ajoutant un __ et __ code> méthode sur la classe p code>. Vous pouvez ensuite écrire quelque chose comme: xxx pré>

ou même p> xxx pré>

De même, vous pouvez remplacer le | code> ( Opérateur bitwise ou) en ajoutant un __ ou __ code> méthode et l'opérateur ~ code> (négation binaire) en ajoutant un __ pas __ code> méthode. Notez que vous ne pouvez pas remplacer les et code>, ou code> et non code>, ceci est donc probablement aussi proche que possible de votre objectif. Vous devez toujours avoir une instance p code> comme argument le plus à gauche. P>

Pour des raisons d'exhaustivité, vous pouvez également remplacer les variantes sur place ( __ iand __ code> , __ ior __ code>) et les variantes de droite ( __ rand __ code>, __ ror __ code>) de ces opérateurs. p>

exemple de code (non testé , N'hésitez pas à corriger): P>

@predicate
def is_divisible_by_13(number):
    return number % 13 == 0

@predicate
def is_palindrome(number):
    return str(number) == str(number)[::-1]

>>> pred = (is_divisible_by_13 & is_palindrome)
>>> print [x for x in xrange(1, 1000) if pred(x)]
[494, 585, 676, 767, 858, 949]


2 commentaires

Je ne sais pas si je veux surcharger les opérateurs bitwise avec une autre signification, mais je trouve l'idée de décorateur très intéressante. Merci!


@ Franks.THOMAS: Les opérations bitwises ont-elles un sens avec vos prédicats? Sinon, rien de mal à les surcharger.



3
votes

Fondamentalement, votre approche semble être la seule réalisable à Python. Il y a un module Python sur GitHUB en utilisant à peu près le même mécanisme pour implémenter la composition de fonction de point à point.

Je ne l'ai pas utilisé, mais à un premier coup d'œil, sa solution semble un peu plus agréable (car il utilise des décorateurs et une surcharge de l'opérateur où vous utilisez une classe et __ appel __ ).

Mais autre que cela, ce n'est pas un code techniquement ponctuel, il est juste "point caché" si vous voulez. Qui peut ou peut ne pas être suffisant pour vous.


0 commentaires

2
votes

Vous pouvez utiliser le Recette d'opérateur Infix :

1001
2002
3003
4004
5005
6006
7007
8008
9009


2 commentaires

C'est probablement le piston python de l'année pour 2012. Au moins pour moi.


@ Tamás: La recette est déjà le meilleur hack de 2005 :-) Aussi, c'est par Ferdinand Jamitzky, non moi. I Seulement (Abu?) L'a utilisé pour ma réponse.



1
votes

Ce serait ma solution: xxx

et c'est mon résultat: xxx


0 commentaires

2
votes

Python a déjà un moyen de combiner deux fonctions: Lambda. Vous pouvez facilement faire votre propre composition et plusieurs fonctions de composition:

compose2 = lambda f,g: lambda x: f(g(x))
compose = lambda *ff: reduce(ff,compose2)

filter(compose(is_divisible_by_13, is_palindrome, xrange(1000)))


1 commentaires

Il devrait être réduire (compose2, ff) ou juste Réduire (Lambda F, G: Lambda x: F (g (x)), FF)