Bobby Tables
Bobby Tables

Reputation: 1184

Array Out Of Bounds F#

While attempting to learn more about sorting algorithims and F#, I wrote an Insertion Sort in F#. I am a complete noob to F# and functional programming.

let insert (a: array<int>) i item =
    i = i - 1
    while i >= 0 && item < a.[i] do
        a.[i + 1] = a.[i]
        i = i - 1
    a.[i + 1] = item
    a

let sort (a: array<int>) =
    for i in 1 .. (a.Length - 1) do
        a = insert a i a.[i]
    a
let a = [|3; 4; 1; 3;|]
a = sort a
for i in a do
    printfn "%d" i

The code compiles fine, but when i run the executable...

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the boun
ds of the array.
   at Isort.insert(Int32[] a, Int32 i, Int32 item)
   at Isort.sort(Int32[] a)
   at <StartupCode$isort>.$Isort.main@()

The exception is kind of unhelpful, as it doesn't say where the out of range exception was... Is there a way to fix this error in my code?

Upvotes: 1

Views: 542

Answers (1)

pad
pad

Reputation: 41290

Several comments:

  • F# values are immutable by default. If you want to modify values, declare them as mutable.
  • = is equality while <- is assignment to mutable values.
  • Pay attention to warnings in F#. In this case, there are a lot of errors since you ignore values of comparisons.

An improved version:

let insert (a: int []) j item =
    let mutable i = j - 1
    while i >= 0 && item < a.[i] do
        a.[i + 1] <- a.[i]
        i <- i - 1
    a.[i + 1] <- item

let sort (b: int []) =
    let a = Array.copy b
    for i in 1 .. (a.Length - 1) do
        insert a i a.[i]
    a
let a = [|3; 4; 1; 3; 5; 6; 5|]
let a' = sort a
for i in a' do printfn "%d" i

I modified names of a few variables for clarity. Moreover, auxiliary function insert could return unit while sort has better return a new copy instead of mutating the input array.

Upvotes: 4

Related Questions