2015-01-27 11 views
5

In F # posso utilizzare la corrispondenza del modello in una varietà di punti all'interno della sintassi.Come destrutturare un argomento del costruttore?

Ad esempio:

// Given this type... 
type SingleCaseUnion = | SingleCaseUnion of int 

/// ...I can do this: 
let destructureInFunc (SingleCaseUnion n) = 
    printfn "%d" n 

// ...and this: 
type DestructureInMethod() = 
    member t.M(SingleCaseUnion n) = 
     printfn "%d" n 

Ma non riesco a capire come fare questo:

type DestructureInCtor(SingleCaseUnion n) = 
    do printfn "%d" n 

// type DestructureInCtor(SingleCaseUnion n) = 
// ---------------------------------------^ 
// 
// stdin(3,40): error FS0010: Unexpected identifier in type definition. Expected ')' or other token. 

Devo la sintassi sbagliata, o fa F # non supporta il pattern matching in parametri del costruttore ?

+0

Mentre non funziona per i costruttori * primary *, altri costruttori (secondari) lo consentono. * (ripubblicato come commento da quando la mia risposta è diventata ridondante.) * – Vandroiy

risposta

5

No, il language spec dice esplicitamente no:

primary-constr-args : attributesopt accessopt (simple-pat, ... , simplepat) 
simple-pat : 
| ident 
| simple-pat : type 

Come è stato sottolineato, i costruttori secondari sono permessi i parametri del modello di pari, ma la differenza con il costruttore principale è ciascuno dei parametri del primario è sia un parametro di funzione e una dichiarazione di campo privata.

Se F # dovesse consentire la corrispondenza del modello qui, ci sarebbero alcuni schemi che potrebbero interrompere questa relazione a un parametro con un campo.

type DestructureInCtor(SingleCaseUnion _) = 
    // doesn't declare a private field 

o:

type DestructureInCtor((a:int, b:int)) = 
    // declares two private fields? 

Non è inconcepibile che questo potrebbe funzionare, ma sto cercando di indovinare la complessità di permettere pattern matching per essere esteso a fornire dichiarazioni di campo supera i benefici.

+0

Guardando la sezione 8.6.1.3 della specifica, non sembra esserci una relazione campo-parametro uno-a-uno. I parametri possono rimanere locali al costruttore in base al loro utilizzo, proprio come i legami 'let' nel costruttore principale. * (Vedi l'esempio in cui "L'input y è usato solo durante la costruzione" nelle specifiche) * Dato che il resto del costruttore principale consente i pattern, non capisco perché porteranno troppa complessità nella lista dei parametri. – Vandroiy

+0

@Vandroiy Hai ragione che se un parametro non viene utilizzato come un campo, non viene creato alcun campo. Ma questi parametri * sono * diversi dai normali parametri di funzionamento. Ecco perché aggiungerebbe complessità per consentire la corrispondenza dei modelli qui e sto suggerendo che questo non era nelle priorità dei designer linguistici. –

+0

Mi sto confrontando con let-binding anziché con i parametri di funzione. Perché 'MyType (pattern) =' non dovrebbe essere compilato come 'MyType (a) = (newline) let pattern = a'? Non sembra aggiungere molta complessità a prima vista. – Vandroiy

Problemi correlati