5
let ints = [1..40000]
// create [{1};{2};.....{40000}]
let a1 = ints |> List.map Seq.singleton 
// tail recursively append all the inner list
let a2 = a1 |> List.fold Seq.append Seq.empty
// tail recursively loop through them
let a3 = a2 |> Seq.forall (fun x -> true) // stack overflow...why?

my reason for asking is concern that I have code that will recursively append and I need to be sure it wont blow up....so I ran this example in order establish what was going

both in debug and running as an app.

asked May 30, 2014 at 12:33
5
  • Are you running it in debug mode? Commented May 30, 2014 at 12:39
  • I am running in debug...let me update the question Commented May 30, 2014 at 12:42
  • Running in debug = no tail call eliminatin. Commented May 30, 2014 at 12:44
  • It seems to crash even running as an app....when you say running in debug...do you mean running in the ide OR do you mean compiling to the debug config. Commented May 30, 2014 at 12:46
  • Actually it crashed in debug, as a debug release and as a release release. Commented May 30, 2014 at 12:47

1 Answer 1

3

The first thing to note is that the function causing the SO exception is:

let a2 = a1 |> List.fold Seq.append Seq.empty

but you don't see the SO until you evaluate the next line because sequences are lazily evaluated.

Because you are using Seq.append, each new item you add to your sequence creates a new sequence which contains the previous sequence. You can construct a similar sequence directly like so:

> seq {
 yield! seq { 
 yield! seq { 
 yield 1
 }
 yield 2
 }
 yield 3
}
val it : seq<int> = seq [1; 2; 3]

Notice how, to get to the very first item (1) you have to go to depth 3 of the sequence. In your case that would be depth 40000. The sequence isn't tail recursive, so each level of the sequence ends up as a stack frame when iterating it.

answered May 30, 2014 at 12:59
4
  • but it isnt that its..sorry...give me some minutes to work it out Commented May 30, 2014 at 13:19
  • OK....I sort of understand that.... (using the wrong syntax its) this is... ((([] ++ [1]) ++ [2]) ++ [3]), so retrieving the 1st elememt I have to go down 40000....let me run a different scenario though...because I am actually going (in my real code) ([] ++ ([1] ++ ([2] ++ [3])) Commented May 30, 2014 at 13:37
  • hmmmmm now I'm really confused...my real code uses a hand rolled difflist to ease the o(n*n) effieciency of the above concats...this works...the efficiency but...I still get the stack overflow....I'll go away and think. Commented May 30, 2014 at 13:45
  • acchhh.....but original code DOESNT get a stack overflow!...and runs in linear time....its my messing around with sequences to try to work out how they work that failed......double thanks. Commented May 30, 2014 at 13:50

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.