Last active
October 13, 2015 20:40
-
-
Save lulu-berlin/9998fdc03d9708eaf2b7 to your computer and use it in GitHub Desktop.
F# unfold without tuples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Seq.unfold (https://msdn.microsoft.com/en-us/library/ee340363.aspx) | |
// works with a generator function that gets a state and returns | |
// Some (element, state) to generate another iterator, or | |
// None to stop the iteration. | |
// The problem is that tuples are allocated every single iteration. | |
// | |
// The solution below uses instead a generator function that gets | |
// a state and an iterator function. The iterator function can be called | |
// to yield a new element and set a new state for the next iterator. If the | |
// generator function returns a unit, i.e. (), the iteration stops. | |
// | |
// See example at the end. | |
let unfoldf<'T, 'State> (f: 'State -> ('T -> 'State -> unit) -> unit) | |
(state: 'State) = | |
let mutable _state = state | |
let mutable _element = None | |
let iterFunc (e: 'T) (s: 'State) = | |
_element <- Some e | |
_state <- s | |
f _state iterFunc | |
seq { | |
while _element.IsSome do | |
yield _element.Value | |
_element <- None | |
f _state iterFunc | |
} | |
// Example: | |
// Start with 0 as the initial state and yield its string representation, | |
// incrementing the state until it reaches 100. | |
let iter = | |
unfoldf (fun state iter -> | |
if state < 100 | |
then iter (sprintf "%d" state) (state + 1) | |
else () // this part can be omitted | |
) 0 | |
for x in iter do printfn "%s" x | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment