Der Titel ist unklar.
[PyAlgebraicDataTypes] Ich habe mit (https://github.com/benanhalt/PyAlgebraicDataTypes) gespielt. Inspiriert von der Sprache Racket [Algebraic Data Types](http://ja.wikipedia.org/wiki/%E4%BB%A3%E6%95 Es scheint sich um eine Bibliothek zu handeln, die% B0% E7% 9A% 84% E3% 83% 87% E3% 83% BC% E3% 82% BF% E5% 9E% 8B) in Python ausdrückt. Ich habe es versucht, weil es klein war und gut zum Lernen aussah.
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()
Eine Liste mit Elementen
3.4
>>> Cons(1, Cons(2, Nil()))
Cons(car=1, cdr=Cons(car=2, cdr=Nil()))
Es kann ausgedrückt werden, indem * Cons * an * Cons.cdr * übergeben wird. Wenn kein Element vorhanden ist, können Sie das Ende mit * Nil * ausdrücken.
Es ist mühsam, diese * List * -Daten von Hand zu schreiben. Definieren wir also eine * range_ * -Funktion, deren Element durch das Argument angegeben wird.
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())))))
Ich konnte meinen eigenen * List * -Typ mit einer Listendatenstruktur definieren.
Jetzt, da ich weiß, wie man es benutzt, werde ich * FizzBuzzList * mit einer Datenstruktur wie Fizz Buzz definieren.
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))
Wenn Sie sich Fizz Buzz als Datenstruktur vorstellen, wird die Logik beim Erstellen der Daten deutlich. Hier wird es durch die Logik von Fizz Buzz generiert, die allgemein genannt wird, aber Sie können auch mit Ihrer eigenen Logik über die Datenstruktur von Fizz Buzz nachdenken.
[MatchCases] Musterübereinstimmungen können ausgedrückt werden, indem ein erbender Matcher erstellt wird (https://github.com/benanhalt/PyAlgebraicDataTypes#match-cases). Lassen Sie uns Muster mit dieser Datenstruktur abgleichen und Fizz Buzz ausgeben.
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
So was.
3.4
>>> FizzBuzzMatch(fbrange(16, 1))
'1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz, None'
Da Python dynamisch typisiert ist, selbst wenn es in einem Mustervergleichsstil geschrieben ist, kann der tatsächliche Fehler nur zur Laufzeit erkannt werden. Selbst wenn es wie unten gezeigt mit * isinstance * implementiert wird, macht es in diesem Beispiel möglicherweise keinen großen Unterschied. ..
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
Die if-Anweisung erzeugt jedoch eine Abhängigkeit von der Reihenfolge. Wenn also der Datentyp abgeleitet und kompliziert ist (z. B. wenn der FizzBuzz-Typ den Fizz-Typ und den Buzz-Typ erbt). Ich bin der Meinung, dass die Strenge der Typanpassung effektiv ist.
Python unterstützt keine algebraischen Datentypen (direkte Summentypen) als Sprache
Ich denke nicht, dass es normal ist, darüber nachzudenken, deshalb war es interessant, es zu versuchen und den Unterschied im Denken zu erkennen.
Eine weitere Sache, die Logik von Fizz Buzz, kam heraus, als die Daten generiert wurden. Mir ist aufgefallen, dass es auch anders ist, dass das Ausgabeergebnis geändert werden kann, ohne die Ausgabeseite (bei der Musterübereinstimmung) durch Ändern der Datengenerierungsmethode zu ändern.
Recommended Posts