Nick
Nick

Reputation: 93

F# Mutable list is returning an error stating it is not mutable

I'm trying to implement a queue in F#. One way I thought about going about it is using a mutable list. I believe the logic is all right, however when I run the code I get the error

/home/runner/main.fs(12,5): error FS0027: This value is not mutable. Consider using the mutable keyword, e.g. 'let mutable queue = expression'.
compiler exit status 1
^[[3;1R

This is my implementation code

let create_job_list jobCount resultLis =
    let resultLis =
        [for i in 1..jobCount do yield System.Random().Next(10)]
    resultLis

let job_list = create_job_list 10 []

let mutable queue = []

let push x queue =
    printfn "%A" x
    queue <- (x::queue)

let pop resQueue =
    let resQ = resQueue |> List.rev
    match resQ with
    | head::tail -> printfn "%A" head; queue <- (tail |> List.rev)
    | [] -> failwith "No more jobs to do right now." 

let rec jobQueue job_list =
    match job_list with
    | head::tail when head%2=1 -> (push head queue) |> ignore; jobQueue tail
    | head::tail when head%2=0 -> (pop queue) |> ignore; jobQueue tail
    | _ -> failwith "Empty list"

The error tells me to use let mutable queue = expression but I'm using let mutable queue = []

Where am I going wrong? Thanks

Upvotes: 1

Views: 163

Answers (2)

torbonde
torbonde

Reputation: 2459

What you need is to pass queue by reference. Your push function should then look something like this:

let push x (queue: byref<_>) =
    printfn "%A" x
    queue <- (x::queue)

and the jobQueue like this

let rec jobQueue job_list =
    match job_list with
    | head::tail when head%2=1 -> (push head &queue) |> ignore; jobQueue tail
    | head::tail when head%2=0 -> (pop queue) |> ignore; jobQueue tail
    | _ -> failwith "Empty list"

I haven't tried this code, but it should at least get you started.

By the way, I guess you are aware that .Net already has a Queue implementation?

Upvotes: 2

3615
3615

Reputation: 3875

You have declared queue as mutable, but you are passing it as an argument that isn't mutable anymore. Since your queue variable is visible inside the push and pop you don't need to have it as parameters.

This should compile:

  let create_job_list jobCount resultLis =
    let resultLis =
        [for i in 1..jobCount do yield System.Random().Next(10)]
    resultLis

  let job_list = create_job_list 10 []

  let mutable queue = []

  let push x=
      printfn "%A" x
      queue <- (x::queue)

  let pop resQueue =
      let resQ = resQueue |> List.rev
      match resQ with
      | head::tail -> printfn "%A" head; queue <- (tail |> List.rev)
      | [] -> failwith "No more jobs to do right now." 

  let rec jobQueue job_list =
      match job_list with
      | head::tail when head%2=1 -> (push head) |> ignore; jobQueue tail
      | head::tail when head%2=0 -> (pop) |> ignore; jobQueue tail
      | _ -> failwith "Empty list"

Upvotes: 2

Related Questions