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

Tail-recursive query string builder in F#

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

Problem

I have a situation where I'm generating a URL based on a set of query string parameters for use in an API. I know ahead of time that the values passed to this function are URL-safe and the tuples are complete, so I don't need to serialize the data or do data validation beyond just checking the length of the array.

This is a function where I'm generating a url from a (string * string)[]. I'm trying to avoid using mutable values, so this uses a tail-recursive function to build the string, with the URL being the "accumulator" value for the tail-recursion.

What I'm looking for is ways to better organize the function, flaws in the logic of the workflow, ways to make the function more readable, and just improvements in general.

let ComposeUrl (valuePairs:(string * string)[]) =
    let Composer (valuePairs:(string * string)[]) =
        let rec ComposerRec (valuePairs:(string * string)[]) (url:string) =
            match valuePairs.Length > 0 with
            | false -> url
            | true  -> 
                let tail = valuePairs.[1..valuePairs.Length - 1]
                let url = url + sprintf "&%s=%s" (fst valuePairs.[0]) (snd valuePairs.[0])
                ComposerRec tail url

        let tail = valuePairs.[1..valuePairs.Length - 1]
        let url = sprintf "?%s=%s" (fst valuePairs.[0]) (snd valuePairs.[0])
        ComposerRec tail url

    match valuePairs.Length > 0 with
    | false -> ""                     // No query string parameters
    | true  -> Composer valuePairs

Solution

As Mauricio suggested:

let ComposeUrl valuePairs = 
    if Seq.isEmpty valuePairs then ""
    else 
        let values = valuePairs |> Seq.map (fun (k, v) -> sprintf "%s=%s" k v)
        "?" + String.Join("&", values)

Code Snippets

let ComposeUrl valuePairs = 
    if Seq.isEmpty valuePairs then ""
    else 
        let values = valuePairs |> Seq.map (fun (k, v) -> sprintf "%s=%s" k v)
        "?" + String.Join("&", values)

Context

StackExchange Code Review Q#60736, answer score: 5

Revisions (0)

No revisions yet.