Till functions

Just wanted to share a couple little functions that I was playing with since it made my code terse and readable. At first I needed a way to fold a function until a predicate. This way I could stop and didn’t have to continue through the whole list. Then I needed to be able to do the same kind of thing but choosing all elements up until a predicate.


First, folding. I wanted to be able to get all the characters up until white space. For example:

let (++) a b = a.ToString() + b.ToString()

let upToSpaces str = foldTill Char.IsWhiteSpace (++) "" str

Which led me to write the following fold function. Granted it’s not lazy evaluated, but for me that was OK.

let foldTill check predicate seed list= 
    let rec foldTill' acc = function
        | [] -> acc
        | (h::t) -> match check h with 
                        | false -> foldTill' (predicate acc h) t
                        | true -> acc
    foldTill' seed list

Running this gives

> upToSpaces "abcdef gh";;
val it : string = "abcdef"

Here’s a more general way of doing it for sequences. Granted it has mutable state, but its hidden in the function and never leaks. This is very similar to how fold is implemented in F# core, I just added the extra check before it calls into the fold predicate

let foldTill check predicate seed (source:seq<'a>) =     
    let finished = ref false     
    use e = source.GetEnumerator() 
    let mutable state = seed 
    while e.MoveNext() && not !finished do
        match check e.Current with 
            | false -> state <- predicate state e.Current
            | true -> finished := true

Anyways, fun!

Leave a Reply

Your email address will not be published. Required fields are marked *