HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

My Brainfuck interpreter in F#

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
brainfuckinterpreterstackoverflow

Problem

I'm very new to functional world. I've written a simple brainfuck interpreter as my first F# program.

What I would like to know:

  • Am I using the right data structure for each situation?



  • Is my code easy to understand?



  • Is my code style similar to common F# codes (naming, organization etc)?



  • Is my code "very declarative" or I'm still thinking in the imperative way?



What is not so relevant:

  • Performance (but if I've made something very bad, let me now!)



  • More features



Obs.: I assume input is always a valid brainfuck code and that's ok to me.

```
open System
open System.IO

let getValue (position:int) (memory:Map) =
match Map.tryFind position memory with
| None -> 0
| value -> value.Value

let calcAccumulator (acc:int) (instruction:char) (search:char) (miss:char) =
match instruction with
| x when x = search -> acc+1
| x when x = miss -> acc-1
| _ -> acc

let rec findMatch (code:string) (search:char) (miss:char) (inc:int) (current:int) (acc:int) =
let instruction = code.[current]

match instruction, acc with
| x, 0 when x = search -> current+1
| _ -> findMatch code search miss inc (current+inc) (calcAccumulator acc instruction search miss)

let updateMemory (instruction:char) (position:int) (memory:Map) =
let oldValue = getValue position memory
let newValue =
match instruction with
| '+' -> oldValue + 1
| '-' -> oldValue - 1
| ',' -> Console.ReadKey().KeyChar |> Convert.ToInt32
| _ -> oldValue

Map.add position newValue memory

let updateOutput (instruction) (value:int) =
if instruction = '.'
then Console.Write ((char) value)

let updatePosition (instruction:char) (position:int) =
match instruction with
| '>' -> position+1
| ' position-1
| _ -> position

let updateIndex (code:string) (index:int) (value:int) =
match code.[index], value with
| '[', 0 -> findMatch code ']' '[' 1 (index+1) 0
| ']', x when x <> 0 -> fin

Solution

Let me make a few comments:

-
F# has a good system of type inference. You don't need to specify the type explicitly, the compiler in many cases will do it for you. You can read more about it here.

-
In function getValue. Usually, matched with None|Some value:

match Map.tryFind position memory with
    | None  -> 0
    | Some value -> value


Although you can rewrite this code with using defaultArg

let getValue position memory =
    defaultArg (Map.tryFind position memory) 0


-
In function updateIndex you can check the value with 0 in match:

let updateIndex (code:string) index value =
    match code.[index], value = 0 with
    | '[', true  -> findMatch code ']' '['  1 (index + 1) 0
    | ']', false -> findMatch code '[' ']' -1 (index - 1) 0
    | _      -> index + 1


-
The helper functions better write as nested:

let interpret (code:string) =
    let rec interpretHelper index memory position =


You can read more about it here

-
In function interpretHelper, use if-then-else instead of PM:

let rec interpretHelper index memory position =
    if code |> String.length = index  then
        memory
    else ...

Code Snippets

match Map.tryFind position memory with
    | None  -> 0
    | Some value -> value
let getValue position memory =
    defaultArg (Map.tryFind position memory) 0
let updateIndex (code:string) index value =
    match code.[index], value = 0 with
    | '[', true  -> findMatch code ']' '['  1 (index + 1) 0
    | ']', false -> findMatch code '[' ']' -1 (index - 1) 0
    | _      -> index + 1
let interpret (code:string) =
    let rec interpretHelper index memory position =
let rec interpretHelper index memory position =
    if code |> String.length = index  then
        memory
    else ...

Context

StackExchange Code Review Q#126408, answer score: 6

Revisions (0)

No revisions yet.