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

Call an F# function with its previous result until the output no longer changes

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

Problem

Basically I have a function of the type 'a -> 'a (an optimization function on a AST) and I want to call it (passing the previous result) until it returns the same thing as the input.

Right now I have this:

let performOptimizations ast = 
  Seq.initInfinite (fun _ -> 0)
  |> Seq.scan (fun last _ -> optimizeAst last) ast
  |> Seq.pairwise
  |> Seq.find (fun (first, second) -> first = second)
  |> fst


This seems really convoluted because it is created an infinite sequence of ints just so that the scan will continue until the ast is no longer modified. I realized that I could also do something like this:

let performOptimizations ast = 
  let mutable newAst = optimizeAst ast
  let mutable lastAst = ast
  while newAst <> lastAst do
    lastAst <- newAst
    newAst <- optimizeAst newAst

  newAst


However, I would prefer to avoid mutation.

What's the functional, idiomatic way of doing this in F#?

Solution

I general, I agree with what mavnn said in his answer, I just think the function can be written in a simpler way:

let rec performOptimizations ast =
    let optimized = optimizeAst ast
    if ast = optimized then
        ast
    else
        performOptimizations optimized


This method also sounds like a good candidate for making it more generic, something like:

let rec doWhileNotSame seed getNextValue =
    let nextValue = getNextValue seed
    if seed = nextValue then
        seed
    else
        doWhileNotSame nextValue getNextValue

Code Snippets

let rec performOptimizations ast =
    let optimized = optimizeAst ast
    if ast = optimized then
        ast
    else
        performOptimizations optimized
let rec doWhileNotSame seed getNextValue =
    let nextValue = getNextValue seed
    if seed = nextValue then
        seed
    else
        doWhileNotSame nextValue getNextValue

Context

StackExchange Code Review Q#27230, answer score: 7

Revisions (0)

No revisions yet.