Fasulye Makinesi Retrospektif, bölüm 9

Fasulye Makinesi Retrospektif, bölüm 9


C#, F#, Scala ve benzerlerinden farklı olarak yerleşik herhangi bir kalıp eşleştirmesi olmayan bir dil olan Python’da kısa “örüntü eşleştirme” uygulamak istedim. Mantıksal olarak bir kalıp sadece bir yüklemdir: bir değer alan ve değer kalıpla “eşleşiyorsa” true, aksi takdirde false değerini döndüren bir işlev. Bu bölümün kodu burada.

Bu işe başladığımda iki şeyin farkına vardım. Birincisi, hata ayıklama amacıyla, dönüş değerinde yalnızca “doğru” veya “yanlış”tan daha fazla bilgiye sahip olmak güzel olabilir; özellikle karmaşık bir model eşleşmeyi başaramadığında ancak eşleşmesi gerekiyorsa, o zaman bir hata yapmışım demektir. Bu hatayı gidermek için aslında kalıpların yeni bir tür döndürmesini sağladım:

class MatchResult(ABC):
    test: Any
    submatches: Dict[str, "MatchResult")
    # ... and so on, boilerplate code for the rest of this.

Karmaşık bir model, bileşen modellerinin eşleşmemesi nedeniyle başarısız olabilir ve böylece hata sonucuna bilgi dahil edilir. Ayrıca alt sınıflar da yaptım Success Ve Fail.

Biliyor musun, tam da bu anda burada “Başarısız” kelimesini isim olarak kullandığımı fark ettim. Öyle olmalıydı Failure. Oh iyi.

İkincisi, her şey için fonksiyonları kullanmanın kesinlikten yoksun olacağını fark ettim. Baştan sona böyle bir kod yazmak istemedim:

is_binop = lambda x: Success(x) if isinstance(x, ast.BinOp) else Fail(x)

“Bu şey bir binop mu?” kavramı zaten tamamen BinOp tipi tarafından yakalanıyor; Bu nesneyi bir kalıbın gerekli olduğu yerde kullanabilir miyiz?

Farklı seçeneklerle uğraştıktan sonra sonunda şu tür disipline ulaştım:

class PatternBase(ABC):
    @abstractmethod
    def match(self, test: Any) -> MatchResult:
        pass
    def __call__(self, test: Any) -> MatchResult:
        return self.match(test)

Pattern = Union[PatternBase, int, str, float, type, list, None)

Bir model temel nesnesi, bir test değeri alan ve ayrıca çağırabileceğiniz bir işlev olarak değerlendirilebilecek bir eşleşme yüklemine sahiptir.

Bir kalıba ihtiyaç duyduğumuz her yerde, arayan kişi şunları sağlayabilir:

  • desen tabanının bir örneği
  • Hiçbiri, tamsayı, kayan nokta veya dize değeri; anlambilim “test verilen değere eşitse model eşleşir” şeklindedir.
  • bir tür; anlambilim “testin verilen türde olması durumunda model eşleşir”
  • kalıpların bir listesi; anlambilim şu şekildedir: “test aynı uzunlukta bir liste ise ve her liste öğesi karşılık gelen kalıpla eşleşiyorsa kalıp eşleşir”

Buraya kadar şu kalıpları ifade edebiliriz:

p = [ BinOp, 3, None ) 
# p matches a list of three items where the first is a binary op AST,
# the second is the number 3, and the third is the value None

Ancak “eşleşme örneklerini” nasıl ifade edebiliriz? Foo kimin bar özellik 3″ mü? Birden fazla kalıpla nasıl eşleşiriz sorusuna ilişkin daha genel bir sorunu çözerek başlayabiliriz. İşte ilk birleştiricimiz:

def match_every(*patterns: Pattern) -> Pattern:
  # ... the implementation is tedious to make it efficient,
  # but you get the idea; we produce a pattern which succeeds if
  # every given subpattern succeeds, and fails otherwise.

Test edilen değerin bir özelliği olan bir alt modelin eşleştirilmesine ilişkin spesifik problemi çözebiliriz:

class AttributeSubpattern(PatternBase):
    name: str
    subpattern: Pattern
    def match(self, test: Any) -> MatchResult:
        submatch = match(self.subpattern, getattr(test, self.name, None))
        submatches = {self.name: submatch}
        if submatch.is_success():
            return Success(test, submatches)
        return Fail(test, submatches)
    # ...

Aramak biraz hantal AttributeSubpattern bu yüzden bir eşanlamlı işlevi yaptım attribute ilave olarak. Bu sınıfın bir birleştirici olduğuna dikkat edin; bir modeli alır ve yeni bir model üretir.

Ve şimdi ilk ikisinden üçüncü bir birleştirici yapabiliriz: Bir nesnenin belirli bir türde olup olmadığını ve bir modelle eşleşen bir özniteliğe sahip olup olmadığını kontrol eden bir model istiyorum:

def type_and_attributes(typ: type, patterns: Dict[str, Pattern)) -> Pattern:
    t: List[Pattern) = [typ)
    tuples: List[Pattern) = [
        attribute(name, subpattern) for (name, subpattern) in patterns.items()
    )
    return match_every(*(t + tuples))

Ve şimdi söyleyebiliriz

is_addition = type_and_attributes(BinOp, {"op": Add})

Veya daha da iyisi, her zaman eşleşen bir model ve başka bir birleştirici oluşturalım:

class AnyPattern(PatternBase):
    def match(self, test: Any) -> MatchResult:
        return Success(test)

_any = AnyPattern()

def binop(
  op: Pattern = _any, 
  left: Pattern = _any, 
  right: Pattern = _any) -> Pattern:
  return type_and_attributes(
    BinOp, {"op": op, "left": left, "right": right})

is_addition = binop(Add)

Ayrıca aşağıdakiler için kalıpları veya birleştiricileri tanımladım:

  • Bu kalıplardan en az biriyle eşleşin
  • Listedeki ilk öğeyi bir kalıpla ve listenin sonunu başka bir modelle eşleştirin
  • Listedeki en az bir öğeyi belirli bir kalıpla eşleştirin
  • Listedeki tüm öğeleri aynı kalıpla eşleştirin
  • Bu desenin tersini eşleştirin
  • Tanımlayıcılar, işleçler vb. gibi yaygın olarak kullanılan AST düğümleri için yardımcı birleştiriciler.
  • Ve benzeri; Fikri anladın.

Araç kutumdaki bu araçlarla, “bu listedeki herhangi bir öğe tanımlayıcı değil mi?” gibi kalıpları hızla oluşturabiliyordum.

any_non_id = ListAny(negate(name()))

Desenler hangi kodun dönüştürülmesi gerektiğini tanımlar; kurallar onları dönüştürür. FAIC’de bir dahaki sefere AST dönüşümlerini kısaca temsil etmek için bir dizi kural ve kural birleştiricileri oluşturmaya bakacağız.



Source link

Postagens Similares

  • İNCELEME: X (Daniel John Pilkington)

    Daniel John Pilkington’ın kitabında Xgenellikle insanlardan ihtiyati bir güvenlik önlemi olarak birbirlerinden uzak durmaları istenen mesafeyi belirtmek için kullanılan, COVID sırasında fotoğraflanan bir dizi “X”i bir araya getiriyor – “burada, 1,5 m aralıklarla durun”. Bu, X’in fiil, isim, sıfat, kısaltma, sembol ve ikon olarak farklı tanımlarını bir araya getiren yan sayfalardaki bir şiirle tezat oluşturuyor….

  • Ексклюзивна обкладинка: From Beijing, With Love by Bei Lin

    Сьогодні на сайті я радий представити обкладинку З Пекіна, з любов’ю від Bei Lin, сучасний гей-роман, який виходить 29 вересня від Alcove Press! Ось історія: Життя Деніела Ву в Амстердамі далеко не спонтанне. Коли його хлопець кидає його в той самий день, коли нещасний випадок змушує його піти у відпустку, він порушує всі свої правила,…

  • Slowlock

    Zo nu en dan hoor je een verhaal als “er was een geval van een 1-Gbps NIC-kaart op een machine die plotseling slechts met 1 Kbps verzond, wat vervolgens een kettingreactie stroomopwaarts veroorzaakte, op zo’n manier dat de prestaties van de gehele werklast van een cluster met 100 knooppunten in een slakkengang kroop, waardoor het…

  • کسی زمرے کو کیسے اڑا دیں۔

    نوٹ – یہ جذبات کے طور پر جذبات کا ایک عجلت میں لکھا گیا دماغی ڈمپ ہے کیونکہ میرے پاس اس مضمون کو اپنے معمول کے مطابق پالش کرنے کا وقت نہیں ہے، لیکن پھر بھی میں اس اہم لمحے کو حاصل کرنا چاہتا ہوں اور اپنی زندگی کا خاتمہ کرنا چاہتا ہوں۔ کسی بھی…

  • Насправді структуроване журналювання (січень 2025 р.)

    Я був дуже схвильований, коли побачив епізод Кела Ньюпорта на Structured Journaling, але я був розчарований рекомендаціями: Щодня: фіксуйте все, що вам подобається/бачите/думаєте/відчуєте, на молескейн, який ви носите з собою Щомісяця: дистиль з молескеїну Щороку (жовтень) обдумуйте вивчене та будуйте нові особисті наративи/цілі Це не зовсім та структура, яку я хочу у своєму житті. Ведення…

  • இது தத்துவம், முட்டாள்! | கிரெக் லேடனின் வலைப்பதிவு

    இது தத்துவம், முறை அல்ல. இந்த எளிய உறவைக் கவனியுங்கள்: தத்துவம் —> உத்தி —> தந்திரங்கள் மன்றத்தில் உள்ள தத்துவஞானிகள் அனைத்து சோக்ரீடியனுக்கும் செல்வதற்கு முன், நான் “தத்துவம்” என்று கூறும்போது நான் என்ன சொல்கிறேன் என்பதை வரையறுக்கிறேன். நான் அதை வடமொழி அர்த்தத்தில், உலகப் பார்வையாகச் சொல்கிறேன். உத்திகள் மற்றும் தந்திரோபாயங்கள் நீங்கள் எப்படிச் செய்கிறீர்கள், உத்திகள் நீண்ட கால திட்டமிடல் மற்றும் தந்திரோபாயங்கள் இந்த தருணத்தின் கருவிகள், இன்று அல்லது இந்த வாரம்…

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *