2012-11-28 4 views
7

Ich versuche Racket zu lernen und versuche dabei einen Python-Filter neu zu schreiben. Ich habe das folgende Paar von Funktionen in meinem Code:Migration von Python zu Racket (reguläre Expressions-Bibliotheken und der "Racket Way")

def dlv(text): 
    """ 
    Returns True if the given text corresponds to the output of DLV 
    and False otherwise. 
    """ 
    return text.startswith("DLV") or \ 
      text.startswith("{") or \ 
      text.startswith("Best model") 

def answer_sets(text): 
    """ 
    Returns a list comprised of all of the answer sets in the given text. 
    """ 
    if dlv(text): 
     # In the case where we are processing the output of DLV, each 
     # answer set is a comma-delimited sequence of literals enclosed 
     # in {} 
     regex = re.compile(r'\{(.*?)\}', re.MULTILINE) 
    else: 
     # Otherwise we assume that the answer sets were generated by 
     # one of the Potassco solvers. In this case, each answer set 
     # is presented as a comma-delimited sequence of literals, 
     # terminated by a period, and prefixed by a string of the form 
     # "Answer: #" where "#" denotes the number of the answer set. 
     regex = re.compile(r'Answer: \d+\n(.*)', re.MULTILINE) 
    return regex.findall(text) 

Von dem, was ich die Umsetzung der ersten Funktion in Racket kann sagen etwas entlang der folgenden Zeilen wäre:

(define (dlv-input? text) 
    (regexp-match? #rx"^DLV|^{|^Best model" text)) 

Welche scheint zu funktionieren korrekt. Die Arbeit an der Umsetzung der zweiten Funktion, ich habe zur Zeit mit folgendem kommen (für den Anfang):

(define (answer-sets text) 
    (cond 
     [(dlv-input? text) (regexp-match* #rx"{(.*?)}" text)])) 

Dies ist nicht korrekt, da regexp-match* eine Liste der Strings gibt, die den regulären Ausdruck, einschließlich die geschweiften Klammern. Weiß jemand, wie man das gleiche Verhalten wie in der Python-Implementierung bekommt? Auch Vorschläge, wie man die regulären Ausdrücke "besser" machen könnte, wären sehr willkommen.

+1

Dürfen wir den Grund für die Migration stellen? –

+1

Ich habe den ursprünglichen Filter geschrieben, um Python zu lernen, und nehme einen ähnlichen Ansatz zum Lernen von Racket. Es ist also nur eine persönliche "weil ich möchte" Grund. – ggelfond

+2

Nur um zu bemerken: Um das Verhalten genau anzupassen, hätte die Python-Version die kompilierten regulären Ausdruckswerte heben müssen. Python kann das Ergebnis von 're.compile' für einfache Eingaben zwischenspeichern, aber Sie möchten möglicherweise nicht von diesem Verhalten für leistungskritischen Code abhängig sein. – dyoo

Antwort

8

Sie sind sehr nah dran. Sie müssen einfach #:match-select cadr zu Ihrem regexp-match Anruf hinzuzufügen:

(regexp-match* #rx"{(.*?)}" text #:match-select cadr) 

standardmäßig #:match-select hat einen Wert von car, der die ganze abgestimmte String zurückgibt. cadr wählt die erste Gruppe, caddr wählt die zweite Gruppe usw. Weitere Informationen finden Sie unter regexp-match* documentation.

+0

Vielen Dank. – ggelfond