2017-12-31 120 views
0

Es tut mir leid für die hier eine solche grundlegende Frage zu stellen, aber ich bin ein Syntaxfehler, wenn ich versuche den folgenden Code zu kompilieren,OCaml Syntaxfehler durch Doppelsemikolon Fest

let sum_of_squares_of_two_largest x y z = 
    let a :: b :: _ = List.sort (fun x y -> -(compare x y)) [x; y; z] in 
    a * a + b * b; 

let rec factorial n = 
    if n = 0 then 1 else n * factorial (n - 1); 

let e_term n = 1.0 /. float_of_int (factorial n); 

let rec e_approximation n = 
    if n = 0 then (e_term 0) else (e_term n) +. (e_approximation (n - 1)); 

let rec is_even x = if x = 0 then true else is_odd (x - 1); 
    and is_odd x = not (is_even x); 

let rec f_rec n = 
    if n < 3 then n else f_rec(n - 1) + 2 * f_rec(n - 2) + 3 * f_rec(n - 3); 

Der uninformativ Compiler sagt mir In Zeile 19, die die letzte Zeile der Datei darstellt, liegt ein Syntaxfehler vor.

File "source.ml", line 19, characters 0-0: 
Error: Syntax error 

Das heißt, Linie 19 ist eine Leerzeile, nur mit einem neuen Online-Charakter.

Ich kann diesen Syntaxfehler "beheben", indem Sie ;; am Ende jeder Funktionsdefinition anstelle der ; hinzufügen.

Fehle ich ein Semikolon irgendwo?

+0

Sie brauchen keines der Semikolons, die Sie in diesem Code haben, einfach alle loswerden. –

+0

@SteveVinoski Ah das war es. Danke vielmals! Wann werden Semikola benötigt? –

+1

Verwenden Sie Semikola, um zwingende Anweisungen zu trennen. –

Antwort

2

Wie in den Kommentaren darauf hingewiesen wurde, ist ; kein Anweisungsterminator wie in vielen anderen (Algol-inspirierten) Sprachen, sondern ein Sequenzoperator. Es braucht zwei Werte, verwirft die erste (aber warnt, wenn es keine Einheit ist) und gibt die zweite zurück. a; b entspricht daher ungefähr let _ = a in b.

Sie sagen, Sie würden die Fehler zu erwarten etwas wie ';' is missing the second operand. zu sagen, aber das Ding ist: es funktioniert nicht. Nicht bis zum Ende der Datei (an diesem Punkt hätte die Fehlermeldung sicherlich intelligenter sein können, aber wahrscheinlich nicht sehr genau).

Was jeder ; im Code folgt sieht aus wie ein absolut gültige Ausdruck, der einen Wert ergeben könnte. Zum Beispiel, wenn let rec factorial n = ...;let rec factorial n = ... in 2 gewesen wäre Der Wert des Ausdrucks wäre 2 gewesen. Das Problem besteht aus der Sicht des Compilers darin, dass es keine Datei mehr gibt, bevor der Ausdruck beendet ist.

Wie Sie auch herausgefunden haben, ist ;; tatsächlich eine Aussage Terminator. Oder ein Toplevel Definitionsterminator ist ein besserer Begriff (ich weiß nicht, ob er überhaupt einen offiziellen Namen hat). Es wird in der REPL verwendet, um die Eingabe zu beenden, wird aber im normalen OCaml-Code nicht benötigt, es sei denn, Sie mischen Definitionen und Ausdrücke auf oberster Ebene, was Sie niemals tun sollten.

;; kann immer noch für Anfänger als „Schott“, aber nützlich sein. Wenn Sie nur eine ;; anstelle einer ; in der Mitte Ihrer Datei setzen, werden Sie feststellen, dass der Compiler jetzt den Fehlerort dort zeigt. Das liegt daran, dass ;; die Definition beendet, ohne dass der vorhergehende Ausdruck vollständig ist. Sie wissen jetzt, dass vorher ein Fehler aufgetreten ist. (Eigentlich im vorhergehenden Ausdruck, aber da Ihre gesamte Datei ein einziger Ausdruck ist, ist "davor" wirklich das Beste, was wir tun können).

+0

Vielen Dank für das Aufräumen. Vor allem der Punkt, warum die Fehlermeldung nicht schlauer hätte sein können. Ich sehe, dass die Datei beendet wurde, während sie den letzten Ausdruck analysierte, von dem erwartet wurde, dass er in einen Nicht-Einheitenwert aufgelöst wird. Vielen Dank! –