Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Literal Attribute not working

Tags:

f#

After reading Chris' answer to F# - public literal and the blog post at http://blogs.msdn.com/b/chrsmith/archive/2008/10/03/f-zen-the-literal-attribute.aspx I don't get why the following is not working:

[<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

This keeps printing "3", although I think it shouldn't. What is it that I don't see here?

like image 608
Alexander Rautenberg Avatar asked Oct 08 '10 11:10

Alexander Rautenberg


4 Answers

I think that literals need to be Uppercase. The following works fine:

[<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

In addition, if you want a nice general solution for this without using literals, you can define a parameterized active pattern like this:

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

And then just write

let one = 1
let two = 2

let trymatch x =
    match x with
    | Equals one -> printfn "%A" one
    | Equals two -> printfn "%A" two
    | _ -> printfn "none"
like image 87
Tomas Petricek Avatar answered Oct 25 '22 18:10

Tomas Petricek


The other answers are right - you must start your identifier with an uppercase letter. See section 7.1.2 of the spec (Named Patterns), which states that:

If long-ident is a single identifier that does not begin with an uppercase character then it is always interpreted as a variable-binding pattern and represents a variable that is bound by the pattern

like image 21
kvb Avatar answered Oct 25 '22 16:10

kvb


Also if you don't want to have Uppercase literals you can put them in a module (here named Const):

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
like image 34
Stringer Avatar answered Oct 25 '22 17:10

Stringer


Don't ask me why, but it works when you write your literals uppercase:

[<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
like image 36
Frank Avatar answered Oct 25 '22 18:10

Frank