# Bit stumped as to why this code compiles but doesn't work

**URL:** <https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416>\
**Category:** General\
**Tags:** beginners\
**Created:** [November 22, 2023, 7:20am UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416 "2023-11-22T07:20:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![k776](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/k776/32/1266_2.png) [@k776](https://forums.fsharp.org/u/k776)\
**Post date:** [November 22, 2023, 7:20am UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/1 "2023-11-22T07:20:49Z")

</div>

I have just started picking up F# as part of a personal project to implement Conways Game of Life in many different languages, and I’ve run into an issue when trying to set a value on a Dictionary within a class.

```auto
module World

open System.Collections.Generic

type World() =
  member private this.cells = new Dictionary<string, int>()
  
  member this.add_cell(): int =
    printfn "%A" this.cells
    this.cells.Add("0-0", 123)
    printfn "%A" this.cells
    this.cells["0-0"]

let world = new World()
world.add_cell() |> ignore

```

This gives me the following output:

```auto
seq []
seq []
Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key '0-0' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at World.World.add_cell()

```

As you can see, there are some weird things happening.

1. The this.cells, which should be a dictionary, is outputting as a seq ?
2. Immediately after adding a value to the dictionary, the output of this.cells is still blank
3. When trying to get the dictionary value using a key I just added, it does a runtime exception

Can anyone help me understand why this is the case? What am I missing here?

Thanks.

---

<div class="post-metadata">

**Author:** ![unfinished](https://avatars.discourse-cdn.com/v4/letter/u/9fc348/32.png) [@unfinished](https://forums.fsharp.org/u/unfinished)\
**Post date:** [November 22, 2023, 11:43am UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/2 "2023-11-22T11:43:13Z")

</div>

That is because this.cells is a member. Thus every time you call this.cells, it returns a new Dictionary, and thus you cannot persist the items you add.  
If you use a private variable, it should work:

```auto
type World() =
  let cells = new Dictionary<string, int>()
  
  member this.add_cell(): int =
    printfn "%A" cells
    cells.Add("0-0", 123)
    printfn "%A" cells
    cells["0-0"]

let world = new World()
world.add_cell() |> ignore

```

---

<div class="post-metadata">

**Author:** ![Prash](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/prash/32/815_2.png) [@Prash](https://forums.fsharp.org/u/Prash)\
**Post date:** [November 22, 2023, 2:25pm UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/3 "2023-11-22T14:25:45Z")

</div>

In F#, all class members are re-evaluated every time they are called. So your `cells` member is returning a new dictionary each time it is accessed. It’s quite a common for newcomers to find this behaviour to be unexpected.

To create a single private value you can a plain `let` inside the class. Here’s an example where I’ve also updated the casing and indentation to be idiomatic for F#:

```fsharp
open System.Collections.Generic

type World() =
    let cells = new Dictionary<string, int>()
  
    member _.AddCell(): int =
        printfn "%A" cells
        cells.Add("0-0", 123)
        printfn "%A" cells
        cells["0-0"]

let world = new World()
world.AddCell() |> ignore

// seq []
// seq [[0-0, 123]]

```

PS: Welcome to the forums 👋🏾😊

---

<div class="post-metadata">

**Author:** ![GarryP](https://avatars.discourse-cdn.com/v4/letter/g/da6949/32.png) [@GarryP](https://forums.fsharp.org/u/GarryP)\
**Post date:** [November 23, 2023, 12:32pm UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/4 "2023-11-23T12:32:30Z")

</div>

Welcome to the forums from me too.

This is a bit ‘off-topic’, and I don’t know how you will be using your code, but trying to implement a class-based workflow in F# can give you a ‘bad taste in the mouth’ when it comes to reviewing the F# code in relation to other languages (if that’s what you are doing).

You can often end up ‘jumping through hoops’ to get what you want, rather than re-working the workflow to utilise the benefits which the language can give you, ending up with something way more complicated than it needs to be.

I’ve written a more F#-idiomatic version of your code which, to me (with some limited F# experience, I’m still very much in the learning phase), is easier to read and understand:

```auto
type World = { Cells : Map<string,int> } 

let addCell key value (world : World) = 
    { world with Cells = world.Cells |> Map.add key value }

```

The type `World` defines a record type, rather than a class, containing `Cells` (which is an immutable map – kind of a dictionary but different – with a string key and int value), instances of which will always remain the same (immutable) and therefore can be totally trusted to always have the same value as they had when they were created.

The `addCell` function takes a World instance and creates a new World instance which is the same as the original but with the new cell added to it giving a new (again, immutable) World as output.

You could use the code like this:

```auto
let startWorld = { Cells = Map.empty } 

let newWorld = startWorld |> addCell "0-0" 123 

let anotherWorld = newWorld |> addCell "0-1" 234 

let oneTwoThree = anotherWorld.Cells["0-0"] 

// val startWorld: World = { Cells = map [] }
// val newWorld: World = { Cells = map [("0-0", 123)] }
// val anotherWorld: World = { Cells = map [("0-0", 123); ("0-1", 234)] }    
// val oneTwoThree: int = 123

```

Hopefully you can see how much more ‘clean’ the code is by using an immutable type rather than a class.

---

<div class="post-metadata">

**Author:** ![k776](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/k776/32/1266_2.png) [@k776](https://forums.fsharp.org/u/k776)\
**Post date:** [November 26, 2023, 3:50am UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/5 "2023-11-26T03:50:05Z")

</div>

Hey Prash. Thank you for your clear explanation. The fact that class members re-evaluate each time they are called was surprising. I’ve not yet come across another language that does that.

With this change and use of `member val ... with get,set`, I was able to complete my F# implementation, which you’re welcome to view here: [https://github.com/KieranP/Game-Of-Life-Implementations/tree/master/f%23](https://github.com/KieranP/Game-Of-Life-Implementations/tree/master/f%23)

I understand the casing and indentation are not idiomatic, but I’ve intentionally done that to be consistent with the other implementations I’ve done for comparison (unless a language enforces it to be different). Besides those things, I’d be keen to hear any thoughts on some small syntax things.

e.g. is this the best/fastest way to append to a List?

```auto
cell.neighbours <- neighbour.Value :: cell.neighbours

```

or is that the best/fastest way to increment an integer?

```auto
alive_neighbours <- alive_neighbours + 1

```

---

<div class="post-metadata">

**Author:** ![k776](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/k776/32/1266_2.png) [@k776](https://forums.fsharp.org/u/k776)\
**Post date:** [November 26, 2023, 3:57am UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/6 "2023-11-26T03:57:04Z")

</div>

Hey Garry. I complete agree that using a functional language to implement OO-like structure is not the best approach, and if I were making just a F# program that needed immutability in order to prevent data race issues, I would go about it completely differently than I have, utilising patterns like your example.

But in this case, the motivation is to have implementations of the same code be as identical as possible for comparison. You’re welcome to checkout the final result here: [https://github.com/KieranP/Game-Of-Life-Implementations/tree/master/f%23](https://github.com/KieranP/Game-Of-Life-Implementations/tree/master/f%23)

---

<div class="post-metadata">

**Author:** ![Prash](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/prash/32/815_2.png) [@Prash](https://forums.fsharp.org/u/Prash)\
**Post date:** [November 26, 2023, 12:39pm UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/7 "2023-11-26T12:39:57Z")

</div>

> [@k776](#):
>
> e.g. is this the best/fastest way to append to a List?
> 
> ```auto
> cell.neighbours <- neighbour.Value :: cell.neighbours
> 
> ```

Using `::` is the fastest and ultimately the only way to add items to a list. Any other method you use will end up appending in this way once or more because it’s fundamental to the data structure. It’s a bit unusual to assign an immutable list to a mutable value, but there might be reasons for doing so. You might consider just using an mutable data structure like `ResizeArray`.

> [@k776](#):
>
> or is that the best/fastest way to increment an integer?
> 
> `alive_neighbours <- alive_neighbours + 1`

Yep.

---

<div class="post-metadata">

**Author:** ![ntwilson](https://yyz2.discourse-cdn.com/flex030/user_avatar/forums.fsharp.org/ntwilson/32/984_2.png) [@ntwilson](https://forums.fsharp.org/u/ntwilson)\
**Post date:** [November 27, 2023, 2:38pm UTC](https://forums.fsharp.org/t/bit-stumped-as-to-why-this-code-compiles-but-doesnt-work/3416/8 "2023-11-27T14:38:20Z")

</div>

> [@k776](#):
>
> The fact that class members re-evaluate each time they are called was surprising. I’ve not yet come across another language that does that.

It is indeed surprising, though C# kinda does that too, it just uses `=>` instead of `=`. The F# program you posted would translate to this C# program:

```auto
using System;
using System.Linq;
using System.Collections.Generic;

var world = new World();
world.add_cell();

class World {
  private Dictionary<string, int> cells => new();
  
  public int add_cell() {
    Console.WriteLine($"[{String.Join(";", this.cells.Select(a => $"{a.Key}: {a.Value}"))}]");
    this.cells.Add("0-0", 123);
    Console.WriteLine($"[{String.Join(";", this.cells.Select(a => $"{a.Key}: {a.Value}"))}]");
    return this.cells["0-0"];
  }
}

```

which outputs

```auto
[]
[]
Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key '0-0' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at World.add_cell() in C:\Users\nathan.wilson\workspace\fs-discourse-help\CsPropReevaluate\Program.cs:line 16
   at Program.<Main>$(String[] args) in C:\Users\nathan.wilson\workspace\fs-discourse-help\CsPropReevaluate\Program.cs:line 7

```
