2012-12-07 11 views
17

Normalerweise erlaubt F # nicht, dass Mustervariablen zweimal im selben Muster vorkommen. Aber im folgenden Code beschwert sich F # nicht - ist das ein Fehler?Warum kann eine Variable zweimal in einem Muster gebunden werden?

type foo = { A: int } 
let test (x, {A = x}) = x 
let result = test ("bla", {A = 3}) 
+2

Simplere Beispiel - 'let test (x, (x, y)) = 1' –

+3

Nicht sicher, warum diese Frage ein Downvote bekam - es sieht aus wie ein interessantes Problem für mich! Ich denke, das ist ein Fehler und Sie können es melden, indem Sie eine E-Mail an _fsbugs_ at _microsoft_dot_com_ senden. –

+0

Nicht sicher, ob es ein Fehler ist - es folgt wohl folgenden Scoping-Regeln, indem es an das am nächsten definierte x bindet. – plinth

Antwort

5

Ich glaube nicht, dies ein Fehler ist, obwohl es verwirrend scheint, aber es ist nur die Art und Weise der Compiler Bindung des obigen Wert kompiliert.

Abschnitt 14.6.3 besagt, dass, wenn der Wert Definition nicht ein einziges Wertmuster ist (wie es hier der Fall ist), der ausgefeilte Ausdruck

tmp <typars1… typarsn> = expr 
ident1 <typars1> = expr1 
… 
identn <typarsn> = exprn 

wo tmp eine neue Kennung und jeweils expri Ergebnisse ist aus die Kompilation des Pattern pat (§7) gegen Eingabe tmp [von spec].

Um zu sehen, was der Compiler tut, wir ein F # Zitat verwenden könnte, zum Beispiel:

<@ let test (x:int, {A = x:int})= x in test (3, {A = 5}) @>;; 

In String-Format erhalte ich (ein paar Sachen heraus zu verlassen):

Let (test, 
    Lambda (tupledArg, 
      Let (x, TupleGet (tupledArg, 0), 
        Let (_arg1, TupleGet (tupledArg, 1), 
         Let (x, PropertyGet (Some (_arg1), A, []), x)))), 
    Application (test, NewTuple (Value (3), NewRecord (foo, Value (5))))) 

weshalb wir nimm das "innere" x.

Ich glaube nicht, dass es ein Fehler ist, aber vielleicht wäre es konsistenter, wenn dies eine Warnung erzeugen würde.

+0

Liegt das daran, dass in F # Shadowing-Wertnamen zulässig sind? – Goswin

Verwandte Themen