Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Array instantiates with 5 items but not with 6

Tags:

arrays

f#

I am new to F#, so I am probably missing something trivial but here goes.

This works -

let monthsWith31Days = [| MonthType.January; 
                          MonthType.March;
                          MonthType.May;
                          MonthType.July;
                          MonthType.December |]

But this doesn't

let monthsWith31Days = [| MonthType.January; 
                          MonthType.March;
                          MonthType.May;
                          MonthType.July;
                          MonthType.August;
                          MonthType.December |]

What I have noted is that it's not the content itself, but the number of items that matter (even if I change the actual items used). The problem starts when number of items exceed 5.

This is the error I get when I run my NUnit tests -

System.ArgumentException: Value does not fall within expected range.

Any ideas what I'm missing?

Edit:

Entire type definition (two types are related so showing both here) -

type public Month(monthType:MonthType, year:Year) = 
        member public this.Year 
            with get () = year
        member public this.MonthType 
            with get () = monthType

        member public this.GetDaysCount () = 
            let monthsWith31Days = [| MonthType.January; 
                                      MonthType.March;
                                      MonthType.May;
                                      MonthType.July;
                                      MonthType.August;
                                      MonthType.December |]

            let has31 = monthsWith31Days |> Array.filter(fun n -> (int)n = (int)this.monthType) |> Array.length

            if (has31 > 0)
            then 31
//            else if (this.MonthType = MonthType.February)
//            then (if this.Year.Leap then 29 
//                  else 28)
            else 30


    and public Year(ad:int) = 
        member public this.AD
            with get() = ad

        member public this.Months = Enum.GetValues(typeof<MonthType>).Cast().ToArray()
                                    |> Array.map(fun n -> new Month (n, this))

        member public this.GetMonth (index:int) = 
            (this.Months |> Array.filter(fun p-> (int)p.MonthType = index)).First()

        member public this.GetMonth (monthName:string) = 
            let requiredMonthType = Enum.Parse(typeof<MonthType>, monthName) |> unbox<MonthType>
            (this.Months |> Array.filter(fun p-> p.MonthType = requiredMonthType)).First()

        member public this.Leap = 
            if this.AD % 400 = 0 then true
            else if this.AD % 100 = 0 then false
            else if this.AD % 4 = 0 then true
            else false

        member this.DaysCount = if this.Leap then 366 else 365
like image 767
Roopesh Shenoy Avatar asked Feb 22 '12 05:02

Roopesh Shenoy


1 Answers

I actually vaguely recall some bug about creating array literals full of enums on some target CLR platform, where if you had more than 5, then some bad code was generated or something. Maybe you're hitting that? Are you targeting x64 and CLR2? You can work around the bug by avoiding array literals, and use e.g. a list and then call List.ToArray.

like image 89
Brian Avatar answered Nov 05 '22 09:11

Brian