2016-06-06 2 views
4

Ich habe ein Problem in OCaml, ich lerne es gerade, aber ich bin immer noch ein Neuling. Ich möchte eine Funktion machen, die true zurückgibt, wenn der String leer ist oder nur Whitespace enthält und gleichzeitig das Auftreten von begin und end entfernt.OCaml Test, wenn eine Zeichenfolge fast leer ist oder Schlüsselwörter enthält

Ich habe bereits versucht dies:

let isEmptyString s = 
    let rec empty i = 
    if i < 0 then true 
    else 
      let c = String.get s i in 
      if c = ' ' || c = '\009' then empty (pred i) 
      else false 
    in 
    s = Str.global_replace(Str.regexp "begin") "" s; 
    s = Str.global_replace(Str.regexp "end") "" s; 
    empty (pred (String.length s)) 

Aber natürlich ist diese Funktion nicht funktioniert, wie ich es möchte, weil ich noch begin in Formula.importNrAgentsFormula erhalten, nachdem es nennen ... Hier ist meine Art, es zu nennen:

while true do 
    let input = read_line() in 
    if not (isEmptyString input) then 
     let (nr, f) = Formula.importNrAgentsFormula input in 
     incr counter; 
     flush stdout; 
     match choice with 
     | "graph" -> printRes (Graph.isSat ~verbose:verb nr f) 
     | _ -> printUsage() 
    else() 
done 

Wenn jemand mit mehr Erfahrungen in OCaml könnte mir den Fehler erkennen und erklären, würde ich i :)

Dank freuen n im Voraus,

Mit freundlichen Grüßen.

+1

Juliens Antwort ist in Ordnung, aber ich würde etwas hinzufügen. Wie Sie es tun, werden Sie Ihre Zeichenfolge zweimal lesen, aber Sie konnten es nur einmal durch Schreiben von Str.global_replace (Str.regexp "\\ (Anfang \\) \\ | \\ (Ende \\)") "" s' – Lhooq

Antwort

3

Ich schlage vor, Sie Ihre Funktion lassen isEmptyString (isBlankString eher?) Tun, was es tun soll (nur überprüfen, ob es nur Leerzeichen oder nichts enthält), sollte es nicht die ursprüngliche Zeichenfolge ändern.Sie können dies in der Schleife tun:

while true do 
    let input = read_line() in 
    let input = Str.global_replace(Str.regexp "begin") "" input in 
    let input = Str.global_replace(Str.regexp "end") "" input in 
    if not (isEmptyString input) then 
    ... 

bearbeiten: Sorry für die späte bearbeiten, hier einige zusätzliche Informationen über Ihre Fehler:

Wenn Sie Ihre Funktion in OCaml laufen, sehen Sie diese Warnung:

Warning 10: this expression should have type unit. 

auf der Linie s = Str.global_replace(Str.regexp "begin") "" s;. Das liegt daran, dass der Operator = in OCaml in diesem Fall nicht der Zuweisungsoperator ist, sondern der Gleichheitsoperator. In dieser Zeile vergleichen Sie also einfach Ihre beiden Werte und geben einen booleschen Wert zurück. Da OCaml e1 in e1;e2 erwartet, um unit zurückzugeben, erhalten Sie diese Warnung.

In OCaml, Werte von Variablen sind unveränderlich, so können Sie:

  • Verwenden Sie eine andere Variable wie @ Jason schlägt vor: let t = Str.global_replace(Str.regexp "begin") "" s
  • "Schatten" der alte Wert, wie ich oben vorschlagen: let s = Str.global_replace(Str.regexp "begin") "" s
  • Verwenden Sie eine Referenz (ein Zeiger auf eine Speicherstelle): let s = ref "before" in s := "after", Sie können dann auf den Wert zugreifen, auf den die Referenz mit dem Operator ! zeigt: !s. Wenn Sie jedoch funktionale Programmierung lernen, schlage ich vor, dass Sie versuchen, am Anfang keine zwingenden Funktionen von OCaml zu verwenden, um dieses neue Paradigma und seine Möglichkeiten zu entdecken.
2

Als ich bei der Arbeit bin ich nicht habe utop mit mir, aber nur von dem ersten Blick in Ihrem ersten, die Dokumentation sagt:

val global_replace : regexp -> string -> string -> string 

Das heißt, Sie brauchen nicht zu einem „; " wie das für ist, wenn Funktionen Einheit zurückzukehren und ist syntaktischer Zucker für so etwas wie

let() = print_endline("foobar") 

Darüber hinaus müssen Sie eine let-Anweisung verwenden, wie Sie den Wert s nicht nur neu zuweisen können. Ich empfehle nicht, die Variable zu schattieren, da dies in der funktionalen Programmierung generell eine schlechte Übung ist. Verwenden Sie etwas wie:

let t = (Str.global_replace(Str.regexp "begin") "" s) 

Auch Ihre Funktion macht zwei verschiedene Dinge. Die rekursive Hilfsfunktion, die Sie geschrieben haben, gibt true und false zurück, was gut ist (ich gehe davon aus, dass es funktioniert). Was Sie letztendlich dafür verwenden, ist, was Sie zurückgeben. Daher geben Sie die Zeichenfolge für die erste Funktion nicht wirklich zurück, wenn "begin" und "end" s ersetzt wurden. Daher sollte die Endausgabe Ihrer Funktion eigentlich ein Tupel vom Typ (bool, string) sein. Dann können Sie auf sie passen, wenn man es so nennen (zB

let b,s = isEmptyString "foobar" in 
if not b then: 
    rest of your code 

Ich glaube Ihnen, die richtige Idee für Ihre Funktion haben though. auch in Ihrer zweiten Funktion ist es eine Möglichkeit für Sie nicht während Schleifen zu verwenden und counters (Auch hoffentlich wird Ihr Counter mit Referenzen implementiert, sonst haben Sie nichts Global.) Ich würde vorschlagen, den Ort, an dem Sie Ihre erste Funktion aufrufen, zu wiederholen, da Loops und Counter imperativ und nicht funktional sind OCaml so

fun 

:) Wenn nicht, ist es gut, manchmal gibt es nur Dinge, die Sie können tu wirklich in OCaml, ohne seine imperativen Funktionen zu verwenden. Lassen Sie mich wissen, ob diese Vorschläge nicht funktionieren.

Verwandte Themen