-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Functional Refactor #3
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments on choices and showcasing F# syntax.
|
||
type Status = ``💀`` = 0 | ``😁`` = 1 | ||
type RNG = Security.Cryptography.RandomNumberGenerator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Want a single type, but not bulky name? Use a type alias!
let aliveNeighbors = | ||
(seq { -1 .. 1 }, seq { -1 .. 1 }) | ||
||> Seq.allPairs | ||
|> Seq.choose (function | (0, 0) -> None | x -> Some x) //skip center |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function |
is a special lambda of match cases.
Thread.Sleep(timeout) | ||
let private stringify (grid: Status [,]) = | ||
grid | ||
|> Array2D.mapi (fun _ y -> if y = columns - 1 then sprintf "%A\n" else string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curried form functions means multiple arguments can be invoke like nested single argument functions and vice versa. Many might not be a fan of this, but I like, the if expression returns a choice of functions from inside a two argument function to make a three argument function!
let work = async { | ||
// randomly initialize our grid | ||
let mutable grid = | ||
Array2D.init rows columns (fun _ _ -> RNG.GetInt32(0, 2) |> enum) | ||
while true do | ||
// Displaying the grid | ||
Console.SetCursorPosition(0, 0) | ||
grid |> stringify |> Console.Write | ||
grid <- nextGeneration grid | ||
do! Async.Sleep timer | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
async
, unlike task
, doesn't start where you declare it (cold rather than hot). Makes it easier to structure and compose.
runSimulation <- false | ||
Console.WriteLine("\n👋 Ending simulation.")) | ||
let cts = new CancellationTokenSource() | ||
Console.CancelKeyPress.Add(fun _ -> cts.Cancel(); Console.WriteLine "\n👋 Ending simulation.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
F# doesn't need semicolons, but you can swap with a new line for most things.
|> Array2D.mapi (fun r c -> | ||
let aliveNeighbors = | ||
(seq { -1 .. 1 }, seq { -1 .. 1 }) | ||
||> Seq.allPairs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
||>
will pipe tuple items into two arguments
nextGeneration
print
to pure functionstringily