Schlägermakro zum automatischen Definieren von Funktionen anhand einer Liste

Ich möchte automatisch eine Reihe von Testfunktionen aus einer Liste generieren. Der Vorteil ist, dass ich die Liste ändern kann (z. B. durch Einlesen einer CSV-Datentabelle) und das Programm bei der nächsten Programmausführung automatisch verschiedene Tests generiert.

Angenommen, ich versuche zu identifizierenOxyanionen in einer Zeichenfolge mit achemische Formel.

Meine Liste könnte ungefähr so ​​aussehen:

(define *oxyanion-tests*
  ;           name         cation
  (list (list "aluminate"  "Al")
        (list "borate"     "B")
        (list "gallate"    "Ga")
        (list "germanate"  "Ge")
        (list "phosphate"  "P")
        (list "sulfate"    "S")
        (list "silicate"   "Si")
        (list "titanate"   "Ti")
        (list "vanadate"   "V")
        (list "stannate"   "Sn")
        (list "carbonate"  "C")
        (list "molybdate"  "Mo")
        (list "tungstate"  "W")))

Ich bin mir ziemlich sicher, dass die chemische Formel eine davon enthältOxyanionen wenn es ein Kation gibt, dem ein Sauerstoff in Klammern folgt (z. B. "(C O3)"), oder wenn dem Kation 2 oder mehr Sauerstoff (z. B. "C O3") folgen. Beachten Sie, dass dies nicht perfekt ist, da Hypochloritanionen (z. B. "Cl O") fehlen, aber es ist gut genug für meine Anwendung.

(define ((*ate? elem) s-formula)
  (or (regexp-match? (regexp (string-append "\\(" elem "[0-9.]* O[0-9.]*\\)")) s-formula)
      (regexp-match? (regexp (string-append "(^| )" elem "[0-9.]* O[2-9][0-9.]*")) s-formula)))

Ich glaube, ich brauche dazu ein Makro, aber ich verstehe nicht wirklich, wie sie funktionieren, wenn ich die Dokumentation lese. Ich frage hier, damit ich ein gutes Beispiel habe, das mir sofort nützlich ist.

Ich denke, wie das Makro aussehen sollte, aber es funktioniert nicht und ich habe nicht wirklich ein mentales Modell, um herauszufinden, wie es behoben werden kann.

(require (for-syntax racket))
(define-syntax-rule (define-all/ate? oxyanion-tests)
  (for ([test oxyanion-tests])
    (match test
      [(list name cation) (syntax->datum (syntax (define ((string->symbol (string-append name "?")) s-formula)
                                    ((*ate? cation) s-formula))))])))

Vielen Dank für jede Anleitung, die Sie mir geben können!

P.S. Hier sind einige Tests, die bestanden werden sollten:

(define-all/ate? *oxyanion-tests*)
(module+ test
  (require rackunit)
  (check-true (borate? "B O3"))
  (check-true (carbonate? "C O3"))
  (check-true (silicate? "Si O4")))

Antworten auf die Frage(1)

Ihre Antwort auf die Frage