2010-10-08 11 views
16

Dopo aver letto la risposta di Chris' per F# - public literal e il post sul blog a http://blogs.msdn.com/b/chrsmith/archive/2008/10/03/f-zen-the-literal-attribute.aspx Non capisco il motivo per cui il seguente non funziona:attributo letterale non funziona

[<Literal>] 
let one = 1 

[<Literal>] 
let two = 2 

let trymatch x = 
    match x with 
    | one -> printfn "%A" one 
    | two -> printfn "%A" two 
    | _ -> printfn "none" 


trymatch 3 

Ciò mantiene la stampa '3', anche se penso che non dovrebbe. Che cosa non vedo qui?

risposta

21

Penso che i letterali debbano essere maiuscoli. Le seguenti opere di bene:

[<Literal>] 
let One = 1 
[<Literal>] 
let Two = 2 

let trymatch x = 
    match x with 
    | One -> printfn "%A" One 
    | Two -> printfn "%A" Two 
    | _ -> printfn "none" 


trymatch 3 

Inoltre, se si desidera una soluzione generale bello per questo senza usare letterali, è possibile definire un modello attivo con parametri in questo modo:

let (|Equals|_|) expected actual = 
    if actual = expected then Some() else None 

E poi basta scrivere

let one = 1 
let two = 2 

let trymatch x = 
    match x with 
    | Equals one -> printfn "%A" one 
    | Equals two -> printfn "%A" two 
    | _ -> printfn "none" 
+2

Sì, confermato. Il compilatore mi avvisa di tutti i tipi di cose ovvie, ma quando ne hai davvero bisogno ... –

2

non chiedetemi perché, ma funziona quando si scrivono i letterali maiuscolo:

[<Literal>] 
let One = 1 
[<Literal>] 
let Two = 2 

let trymatch (x:int) = 
    match x with 
    | One -> printfn "%A" One 
    | Two -> printfn "%A" Two 
    | _ -> printfn "none" 

trymatch 3 
7

Anche se non si vuole avere letterali maiuscole li si può mettere in un modulo (qui chiamato Cost):

module Const = 
    [<Literal>] 
    let one = 1 
    [<Literal>] 
    let two = 2 

let trymatch x = 
    match x with 
    | Const.one -> printfn "%A" Const.one 
    | Const.two -> printfn "%A" Const.two 
    | _ -> printfn "none" 

trymatch 3 
+2

Qualche idea se c'è una logica dietro quel comportamento? –

+0

@ Alexander: non lo so. Si noti che il nome del modulo qui non ha bisogno di essere in maiuscolo .. – Stringer

+1

@Alexander - questo comportamento è anche nelle specifiche. Presumibilmente il ragionamento è che se si tratta di un identificativo composto contenente un '.', allora non è certamente una variabile, quindi procedi con la risoluzione dei nomi. – kvb

13

Le altre risposte sono giuste - è necessario avviare l'identificativo con una lettera maiuscola . Vedere la sezione 7.1.2 of the spec (Patterns denominati), quale:

Se a lungo ident è un identificatore unico che non inizia con un carattere maiuscolo allora è sempre interpretata come un modello variabile vincolante e rappresenta una variabile che è vincolato al modello

+0

Ammiro la tua conoscenza enciclopedica delle specifiche, cercando di arrivarci ma ancora qualche mese di pausa, come sembra ... mi chiedo solo: in questo caso, non sarebbe stato più semplice basare l'intero meccanismo sul caso della prima lettera, cioè maiuscolo = corrispondente, minuscolo = vincolante; condividere la responsabilità tra l'attributo e il caso dell'identificatore sembra renderlo più complicato del necessario. –

+0

+1 per il riferimento alla sezione appropriata della specifica. – Frank

+1

@Alexander - Sono d'accordo sul fatto che questo comportamento sia fonte di confusione - non so perché il team abbia scelto l'approccio che hanno fatto. Sembra anche dato il comportamento attuale, alcuni avvisi del compilatore aggiuntivi sui letterali in lettere minuscole o corrispondenze usando nomi di variabili che i letterali delle ombre sarebbero giustificati. – kvb

Problemi correlati