Le titre n'est pas clair.
[PyAlgebraicDataTypes] J'ai joué avec (https://github.com/benanhalt/PyAlgebraicDataTypes). Inspiré du langage Racket [Algebraic Data Types](http://ja.wikipedia.org/wiki/%E4%BB%A3%E6%95 Il semble que ce soit une bibliothèque qui exprime% B0% E7% 9A% 84% E3% 83% 87% E3% 83% BC% E3% 82% BF% E5% 9E% 8B) en Python. Je l'ai essayé parce qu'il était petit et avait l'air bien pour l'apprentissage.
3.4
>>> from adt import ADT, Require
>>> class List(ADT): pass
...
>>> class Nil(List): pass
...
>>> class Cons(List):
... car = Require(int)
... cdr = Require(List)
3.4
>>> Nil()
Nil()
Une liste d'éléments
3.4
>>> Cons(1, Cons(2, Nil()))
Cons(car=1, cdr=Cons(car=2, cdr=Nil()))
Il peut être exprimé en passant * Cons * à * Cons.cdr *. S'il n'y a pas d'élément, vous pouvez exprimer la fin en utilisant * Nil *.
Puisqu'il est difficile d'écrire ces données * List * à la main, définissons une fonction * range_ * qui a l'élément spécifié par l'argument.
3.4
>>> def range_(until, value=0):
... return Nil() if value == until else Cons(value, range_(until, value + 1))
...
>>> range_(5)
Cons(car=0, cdr=Cons(car=1, cdr=Cons(car=2, cdr=Cons(car=3, cdr=Cons(car=4, cdr=Nil())))))
J'ai pu définir mon propre type de * Liste * avec une structure de données de liste.
Maintenant que je sais comment l'utiliser, je vais définir * FizzBuzzList * avec une structure de données comme Fizz Buzz.
3.4
class FizzBuzzList(List):
pass
class Value(FizzBuzzList):
value = Require(int)
class Fizz(FizzBuzzList):
value = Require(int)
class Buzz(FizzBuzzList):
value = Require(int)
class FizzBuzz(FizzBuzzList):
value = Require(int)
fizz = Require(Fizz)
buzz = Require(Buzz)
3.4
def fbrange(until, value=0):
"""
>>> fbrange(6, 1) # doctest: +NORMALIZE_WHITESPACE
Cons(car=Value(value=1), cdr=Cons(car=Value(value=2),
cdr=Cons(car=Fizz(value=3), cdr=Cons(car=Value(value=4),
cdr=Cons(car=Buzz(value=5), cdr=Nil())))))
"""
def make_cons(obj):
return Cons(obj, fbrange(until, obj.value + 1))
if value == until:
return Nil()
elif value % 15 == 0:
return make_cons(FizzBuzz(value, Fizz(value), Buzz(value)))
elif value % 5 == 0:
return make_cons(Buzz(value))
elif value % 3 == 0:
return make_cons(Fizz(value))
return make_cons(Value(value))
Lorsque vous considérez Fizz Buzz comme une structure de données, la logique ressort lorsque vous créez les données. Ici, il est généré par la logique de Fizz Buzz, qui est généralement appelée, mais vous pouvez également penser à la structure de données de Fizz Buzz avec votre propre logique.
[MatchCases] Vous pouvez exprimer des correspondances de modèles en créant un matcher qui hérite (https://github.com/benanhalt/PyAlgebraicDataTypes#match-cases). Faisons correspondre cette structure de données et produisons Fizz Buzz.
3.4
from adt import MatchCases
class FizzBuzzMatch(MatchCases):
def value(match: Value):
return value
def fizz(match: Fizz):
return 'fizz'
def buzz(match: Buzz):
return 'buzz'
def fizzbuzz(match: FizzBuzz):
return FizzBuzzMatch(fizz) + FizzBuzzMatch(buzz)
def cons(match: Cons):
return '{}, {}'.format(FizzBuzzMatch(car), FizzBuzzMatch(cdr))
def nil(match: Nil):
return None
Comme ça.
3.4
>>> FizzBuzzMatch(fbrange(16, 1))
'1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz, None'
Étant donné que Python est typé dynamiquement, même s'il est écrit dans un style de correspondance de modèle, l'erreur réelle ne peut être détectée qu'au moment de l'exécution, donc même si elle est implémentée avec * isinstance * comme indiqué ci-dessous, cela peut ne pas faire une grande différence dans cet exemple. ..
3.4
def match_fizzbuzz(fblist):
if isinstance(fblist, Value):
return fblist.value
elif isinstance(fblist, Fizz):
return 'fizz'
elif isinstance(fblist, Buzz):
return 'buzz'
elif isinstance(fblist, FizzBuzz):
return match_fizzbuzz(fblist.fizz) + match_fizzbuzz(fblist.buzz)
elif isinstance(fblist, Cons):
return '{}, {}'.format(
match_fizzbuzz(fblist.car),
match_fizzbuzz(fblist.cdr))
elif isinstance(fblist, Nil):
return None
Cependant, l'instruction if crée une dépendance sur l'ordre, donc lorsque le type de données est dérivé et compliqué (par exemple, lorsque le type FizzBuzz hérite du type Fizz et du type Buzz). Je pense que la rigueur de la correspondance de type est efficace.
Python ne prend pas en charge les types de données algébriques (types à somme directe) en tant que langage
Je ne pense pas que ce soit normal d'y penser, donc c'était intéressant de l'essayer et de réaliser la différence de pensée.
Une dernière chose, la logique de Fizz Buzz est apparue lorsque les données ont été générées. J'ai remarqué qu'il est également différent que le résultat de sortie puisse être modifié sans changer le côté de sortie (lors de la correspondance de motif) en changeant la méthode de génération de données.
Recommended Posts