Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4109332
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T21:46:58+00:00 2026-05-20T21:46:58+00:00

I have an F# function that returns a list of numbers starting from 0

  • 0

I have an F# function that returns a list of numbers starting from 0 in the pattern of skip n, choose n, skip n, choose n… up to a limit. For example, this function for input 2 will return [2, 3, 6, 7, 10, 11...].

Initially I implemented this as a non-tail-recursive function as below:

let rec indicesForStep start blockSize maxSize =
    match start with
    | i when i > maxSize -> []
    | _ -> [for j in start .. ((min (start + blockSize) maxSize) - 1) -> j] @ indicesForStep (start + 2 * blockSize) blockSize maxSize

Thinking that tail recursion is desirable, I reimplemented it using an accumulator list as follows:

let indicesForStepTail start blockSize maxSize =
    let rec indicesForStepInternal istart accumList =
        match istart with
        | i when i > maxSize -> accumList
        | _ -> indicesForStepInternal (istart + 2 * blockSize) (accumList @ [for j in istart .. ((min (istart + blockSize) maxSize) - 1) -> j])
    indicesForStepInternal start []

However, when I run this in fsi under Mono with the parameters 1, 1 and 20,000 (i.e. should return [1, 3, 5, 7...] up to 20,000), the tail-recursive version is significantly slower than the first version (12 seconds compared to sub-second).

Why is the tail-recursive version slower? Is it because of the list concatenation? Is it a compiler optimisation? Have I actually implemented it tail-recursively?

I also feel as if I should be using higher-order functions to do this, but I’m not sure exactly how to go about doing it.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T21:46:59+00:00Added an answer on May 20, 2026 at 9:46 pm

    As dave points out, the problem is that you’re using the @ operator to append lists. This is more significant performance issue than tail-recursion. In fact, tail-recursion doesn’t really speed-up the program too much (but it makes it work on large inputs where the stack would overflow).

    The reason why you’r second version is slower is that you’re appending shorter list (the one generated using [...]) to a longer list (accumList). This is slower than appending longer list to a shorter list (because the operation needs to copy the first list).

    You can fix it by collecting the elements in the accumulator in a reversed order and then reversing it before returning the result:

    let indicesForStepTail start blockSize maxSize =
        let rec indicesForStepInternal istart accumList =
            match istart with
            | i when i > maxSize -> accumList |> List.rev
            | _ -> 
               let acc = 
                 [for j in ((min (istart + blockSize) maxSize) - 1) .. -1 .. istart -> j] 
                 @ accumList
               indicesForStepInternal (istart + 2 * blockSize) acc
        indicesForStepInternal start []
    

    As you can see, this has the shorter list (generated using [...]) as the first argument to @ and on my machine, it has similar performance to the non-tail-recursive version. Note that the [ ... ] comprehension generates elements in the reversed order – so that they can be reversed back at the end.

    You can also write the whole thing more nicely using the F# seq { .. } syntax. You can avoid using the @ operator completely, because it allows you to yield individual elemetns using yield and perform tail-recursive calls using yield!:

    let rec indicesForStepSeq start blockSize maxSize = seq {
        match start with
        | i when i > maxSize -> ()
        | _ -> 
          for j in start .. ((min (start + blockSize) maxSize) - 1) do
            yield j
          yield! indicesForStepSeq (start + 2 * blockSize) blockSize maxSize }
    

    This is how I’d write it. When calling it, you just need to add Seq.toList to evaluate the whole lazy sequence. The performance of this version is similar to the first one.

    EDIT With the correction from Daniel, the Seq version is actually slightly faster!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

We have a table value function that returns a list of people you may
I have a function, that returns the next higher value of a Dictionary-Keys-List compared
I have a function that returns a float from 0 to 255. I would
I have a function that returns a date from a stored procedure, and it
If I have a function that returns an object, but this return value is
I have the jquery code below that returns a list of ID's like this
I have a function client_groups in a model that returns a list of Group
I have a function that returns a list. When I know the number of
I want to have a function that will return the reverse of a list
I have a function that returns an entry on a dictionary, based on the

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.