2
votes

I've faced confusing for me difference between output in F# interactive and output on Console.

Overview of the problem:

Given an array A of length n Sort the indexes in the following order:

index[i] < index[j] if (A[i] < A[j]) or (A[i] = A[j] and i < j)

For example

[| 4; 2; 4; 2; 1; 1 |]  

the indexes here would be sorted like this

[| 4; 5; 1; 3; 0; 2 |]  


    let GetSorted (A:int[]) =
    let Comparer i j =
        match (A.[i], A.[j]) with
            | a1, a2 when a1 > a2 -> +1
            | a1, a2 when a1 < a2 -> -1
            | _, _ when i > j -> +1
            | _, _ -> -1

    let lenA = A |> Array.length

    [| 0 .. lenA - 1 |] |> Array.sortWith Comparer

let A = [| 0; 0; 0; 0; 0; 0; 0; 0; 42; 0; 0; 0; 0; 0; 0; 0; 41 |]

let sortedPositions = GetSorted A

When i run above script in F# interactive, i got the following:

val sortedPositions : int [] =
  [|0; 1; 2; 3; 4; 5; 6; 7; 9; 10; 11; 12; 13; 14; 15; 16; 8|]

Notice, the last two indexes are 16 and 8. Which is correct, because 41 < 42

when i tried to do it thru console run:

sortedPositions |> Array.iter(Console.WriteLine)

[|0; 1; 2; 3; 4; 5; 6; 7; 9; 10; 11; 12; 13; 14; 15; 8; 16|]

I didnt find another length of an array, so the two runs would give different results, so far only 17 was spotted.

Why is this happening? I have a suspicion that sorting works differently in F# Interactive, because when you look closer to my Comparer, it doesnt handle properly situation with the same indexes (although i don't know why sorting algorithm requires checks for same indexes). So, when i add another match for

| _, _ when i = j -> 0

It begins to work. But still, confused that without it i'm getting different results.

1
My guess, there is an earlier definition in one of the two approaches that is conflicting - John Palmer

1 Answers

6
votes

+1 to John Palmer's comment. Your FSI session is probably polluted with old function and value definitions you don't remember you created, which are interfering.

I can confirm that this works exactly the same in FSI and compiled to console app. Try fully resetting your FSI session and re-defining your functions/values.

C:\Users\latkin\Source
> type .\test.fsx
let GetSorted (A:int[]) =
    let Comparer i j =
        match (A.[i], A.[j]) with
            | a1, a2 when a1 > a2 -> +1
            | a1, a2 when a1 < a2 -> -1
            | _, _ when i > j -> +1
            | _, _ -> -1

    Array.init A.Length id |> Array.sortWith Comparer

[| 0; 0; 0; 0; 0; 0; 0; 0; 42; 0; 0; 0; 0; 0; 0; 0; 41 |]
|> GetSorted
|> printfn "%A"

C:\Users\latkin\Source
> & 'C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\Fsc.exe' .\test.fsx
Microsoft (R) F# Compiler version 14.0.22416.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

C:\Users\latkin\Source
> .\test.exe
[|0; 1; 2; 3; 4; 5; 6; 7; 9; 10; 11; 12; 13; 14; 15; 16; 8|]

C:\Users\latkin\Source
> & 'C:\Program Files (x86)\Microsoft SDKs\F#\4.0\Framework\v4.0\Fsi.exe' .\test.fsx
[|0; 1; 2; 3; 4; 5; 6; 7; 9; 10; 11; 12; 13; 14; 15; 16; 8|]