2014-07-16 15 views
10

bemerkte ich, dass der folgende Code kompiliert und arbeitet in VS 2013:Warum ist "do" in einer Funktion erlaubt?

let f() = 
    do Console.WriteLine(41) 
    42 

Aber wenn bei der F # 3.0-Spezifikation suchen kann ich keine Erwähnung von do finden auf diese Weise verwendet wird. Soweit ich das beurteilen kann, do folgende Verwendungen haben:

  • Als Teil der Schleife (z while expr do expr done), das ist hier nicht der Fall.
  • Innerhalb Berechnung Ausdrücke, z.B .:

    seq { 
        for i in 1..2 do 
        do Console.WriteLine(i) 
        yield i * 2 
    } 
    

    dass hier entweder nicht der Fall ist, f keine Rechenausdrücke enthält.

    Obwohl was verwirrt mich hier ist, dass nach der Spezifikation sollte do von in folgen. Die Option in sollte aufgrund der Lightweight-Syntax optional sein. Wenn Sie sie jedoch hier hinzufügen, wird ein Kompilierungsfehler verursacht ("Unerwartetes Token" in "oder unvollständiger Ausdruck").

  • Anweisung in einem Modul oder einer Klasse. Dies ist auch hier nicht der Fall, der do ist innerhalb einer Funktion, nicht innerhalb eines Moduls oder einer Klasse.

Ich habe auch bemerkt, dass mit #light "off", wird der Code nicht kompilieren („Unexpected Schlüsselwort‚do‘in binding“), aber ich habe nichts gefunden, die entweder das im Abschnitt über die leichte Syntax erklären würden, .

Basierend auf all dies würde ich davon ausgehen, dass die Verwendung do innerhalb einer Funktion auf diese Weise nicht kompilieren sollte, aber es tut. Habe ich etwas in der Spezifikation vermisst? Oder ist das eigentlich ein Fehler im Compiler oder in der Spezifikation?

+2

Es wird eine Do-Bindung genannt. Ich konnte es nicht in der Spezifikation finden, aber es ist [dokumentiert auf MSDN] (http://msdn.microsoft.com/en-us/library/dd393786.aspx). – Daniel

+0

@Daniel Das ist der dritte Fall, den ich erwähnt habe, "do" in einem Modul. "Verwenden Sie eine do-Bindung, wenn Sie Code * unabhängig von einer Funktion ausführen möchten." – svick

+1

Um das Zitat zu beenden: _unabhängig von einer Funktion * oder Wertdefinition * ._ Der zweite Fall könnte innerhalb einer Funktion anwendbar sein. – Daniel

Antwort

7

Vom documentation on MSDN:

A do Bindung verwendet wird, Code auszuführen, ohne eine Funktion oder der Wert definiert wird.

Auch wenn die Spezifikation nicht eine umfassende Liste der Orte, enthält es erlaubt ist, ist es nur ein Ausdruck des Typs unit sein behauptet. Einige Beispiele:

if ((do()); true) then() 
let x: unit = do() 

Es wird im Allgemeinen verzichtet. Jedes der vorhergehenden Beispiele ist gültig ohne do. Daher dient do nur dazu assert, dass ein Ausdruck vom Typ unit ist.

+0

Ich denke, die Spezifikation verbietet es, da es nicht als eine der Auswahlmöglichkeiten für 'expr' (§6 und §A.2.3) aufgeführt ist. – svick

+0

In den letzten Jahren habe ich viele Beispiele von 'Do' in einer Funktion oder Methode verwendet. Wenn dieses Verhalten nicht beabsichtigt ist, ist es an diesem Punkt de facto gültig. Ich denke jedoch, dass das nicht der Fall ist und die Spezifikation in diesem Punkt unvollständig ist. – Daniel

0

Wenn man durch den Ausdruck F# 3.0 specification Syntax hat do expr als eine Wahl von class-function-or-value-defn (Typen) [Ch 8, A.2.5] und module-function-or-value-defn (Module) [Ch 10, A.2.1.1].

Ich sehe nicht in der Spezifikation, wo function-defn mehr als einen Ausdruck haben kann, solange alle bis auf die letzte unit auswerten - oder dass alle außer dem letzten Ausdruck ignoriert wird bei der Bestimmung der Funktionen Rückgabewert.

Es scheint also, dies ist ein Versehen in der Dokumentation.

+0

"Ich sehe nicht in der Spezifikation, wo' function-defn' mehr als einen Ausdruck haben kann "Das ist dank der' expr = expr; Ausdr "-Regel und die Tatsache, dass die Syntax mit geringem Gewicht das Semikolon optional macht. – svick

Verwandte Themen