* [Caml-list] tail call optimization @ 2003-11-19 5:24 Dustin Sallings [not found] ` <3FBB0247.2000401@cs.caltech.edu> 2003-11-19 6:50 ` Brian Hurt 0 siblings, 2 replies; 7+ messages in thread From: Dustin Sallings @ 2003-11-19 5:24 UTC (permalink / raw) To: Caml Mailing List I read something on the list about how a function may be tail recursive, but not be compiled with tail call optimization. What kinds of things might cause this? Specifically, I've got an ``iter_lines'' function I'd like to turn into a ``fold_lines'' function that looks something like this (a few different functions for different things): let rec fold_lines f init_value ch = try let v = f (input_line ch) init_value in fold_lines f v ch with End_of_file -> init_value; ;; So, I have these other two functions: let operate_on_file f fn = let ch = open_in fn in try let rv = f ch in close_in ch; rv with x -> close_in ch; raise x ;; let fold_file_lines f init_value fn = operate_on_file (fold_lines f init_value) fn ;; I now want to count the lines in a file: dustinti:~/prog/eprojects/snippets/ocaml/lib 586% wc -l numbers 4769526 numbers # Fileutils.fold_file_lines (fun x y -> y + 1) 0 "numbers";; Stack overflow during evaluation (looping recursion?). Am I doing something wrong? -- SPY My girlfriend asked me which one I like better. pub 1024/3CAE01D5 1994/11/03 Dustin Sallings <dustin@spy.net> | Key fingerprint = 87 02 57 08 02 D0 DA D6 C8 0F 3E 65 51 98 D8 BE L_______________________ I hope the answer won't upset her. ____________ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <3FBB0247.2000401@cs.caltech.edu>]
* Re: [Caml-list] tail call optimization [not found] ` <3FBB0247.2000401@cs.caltech.edu> @ 2003-11-19 6:07 ` Dustin Sallings 0 siblings, 0 replies; 7+ messages in thread From: Dustin Sallings @ 2003-11-19 6:07 UTC (permalink / raw) To: Aleksey Nogin; +Cc: Caml Mailing List On Nov 18, 2003, at 21:40, Aleksey Nogin wrote: > On 18.11.2003 21:24, Dustin Sallings wrote: > >> Specifically, I've got an ``iter_lines'' function I'd like to >> turn into a ``fold_lines'' function that looks something like this (a >> few different functions for different things): >> let rec fold_lines f init_value ch = >> try >> let v = f (input_line ch) init_value in >> fold_lines f v ch >> with End_of_file -> init_value; > > My guess is that because the recursive call is inside the "try", the > function is not really tail recursive. > > May be the following will work: > > let rec fold_lines f init_value ch = > match > try > Some (f (input_line ch) init_value) > with End_of_file -> None > with > Some v -> fold_lines f v ch > | None -> init_value Well, this does work, but I don't really like it. How expensive is the match? It seems to me that the try call shouldn't be relevant since the return value comes from the bottom of it. -- SPY My girlfriend asked me which one I like better. pub 1024/3CAE01D5 1994/11/03 Dustin Sallings <dustin@spy.net> | Key fingerprint = 87 02 57 08 02 D0 DA D6 C8 0F 3E 65 51 98 D8 BE L_______________________ I hope the answer won't upset her. ____________ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] tail call optimization 2003-11-19 5:24 [Caml-list] tail call optimization Dustin Sallings [not found] ` <3FBB0247.2000401@cs.caltech.edu> @ 2003-11-19 6:50 ` Brian Hurt 2003-11-19 6:24 ` Dustin Sallings 1 sibling, 1 reply; 7+ messages in thread From: Brian Hurt @ 2003-11-19 6:50 UTC (permalink / raw) To: Dustin Sallings; +Cc: Caml Mailing List On Tue, 18 Nov 2003, Dustin Sallings wrote: > > I read something on the list about how a function may be tail > recursive, but not be compiled with tail call optimization. What kinds > of things might cause this? > > Specifically, I've got an ``iter_lines'' function I'd like to turn > into a ``fold_lines'' function that looks something like this (a few > different functions for different things): > > let rec fold_lines f init_value ch = > try > let v = f (input_line ch) init_value in > fold_lines f v ch > with End_of_file -> init_value; > ;; This function is not tail recursive. Basically, if the recursive call either a) is wrapped in a try block, or b) has it's return value modified in any way, the function isn't tail recursive. Your function violates clause a, the following function violates clause b: let append a b = match a with | [] -> b | h :: t -> h :: (append t b) ;; Since we're appending h to the return value of the recursive call, it isn't tail recursive. I recommend coding the your function like: let rec fold_lines f init_value ch = let line, eof = try (input_line ch), false with End_of_file -> "", true in if eof then init_value else fold_lines f (f line init_value) ch ;; Now that the recursive call is outside the try block, and you aren't modifying the return value, so all is good. > dustinti:~/prog/eprojects/snippets/ocaml/lib 586% wc -l numbers > 4769526 numbers > # Fileutils.fold_file_lines (fun x y -> y + 1) 0 "numbers";; > Stack overflow during evaluation (looping recursion?). Stack overflows are a classic sign of a function you thought was tail recursive not being tail recursive. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] tail call optimization 2003-11-19 6:50 ` Brian Hurt @ 2003-11-19 6:24 ` Dustin Sallings 2003-11-19 11:40 ` Frederic van der Plancke 2003-11-19 17:22 ` Brian Hurt 0 siblings, 2 replies; 7+ messages in thread From: Dustin Sallings @ 2003-11-19 6:24 UTC (permalink / raw) To: Brian Hurt; +Cc: Caml Mailing List On Nov 18, 2003, at 22:50, Brian Hurt wrote: > This function is not tail recursive. Basically, if the recursive call > either a) is wrapped in a try block, or b) has it's return value > modified > in any way, the function isn't tail recursive. Your function violates > clause a, the following function violates clause b: > > let append a b = > match a with > | [] -> b > | h :: t -> h :: (append t b) > ;; I guess I don't understand the point of clause a. The try block doesn't seem like it should prevent the optimization. >> dustinti:~/prog/eprojects/snippets/ocaml/lib 586% wc -l numbers >> 4769526 numbers >> # Fileutils.fold_file_lines (fun x y -> y + 1) 0 "numbers";; >> Stack overflow during evaluation (looping recursion?). > > Stack overflows are a classic sign of a function you thought was tail > recursive not being tail recursive. Yes, this file was my test for tail recursion. :) -- SPY My girlfriend asked me which one I like better. pub 1024/3CAE01D5 1994/11/03 Dustin Sallings <dustin@spy.net> | Key fingerprint = 87 02 57 08 02 D0 DA D6 C8 0F 3E 65 51 98 D8 BE L_______________________ I hope the answer won't upset her. ____________ ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] tail call optimization 2003-11-19 6:24 ` Dustin Sallings @ 2003-11-19 11:40 ` Frederic van der Plancke 2003-11-19 17:22 ` Brian Hurt 1 sibling, 0 replies; 7+ messages in thread From: Frederic van der Plancke @ 2003-11-19 11:40 UTC (permalink / raw) Cc: Caml Mailing List Dustin Sallings wrote: > > On Nov 18, 2003, at 22:50, Brian Hurt wrote: > > > This function is not tail recursive. Basically, if the recursive call > > either a) is wrapped in a try block, or b) has it's return value > > modified > > in any way, the function isn't tail recursive. Your function violates > > clause a, the following function violates clause b: > > > > let append a b = > > match a with > > | [] -> b > > | h :: t -> h :: (append t b) > > ;; > > I guess I don't understand the point of clause a. The try block > doesn't seem like it should prevent the optimization. Any work your function has to do before the called function returns prevents tail-call optimisation. Unsetting a "try" exception handler is work that has to be done at the level of the corresponding "with". Frédéric ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] tail call optimization 2003-11-19 6:24 ` Dustin Sallings 2003-11-19 11:40 ` Frederic van der Plancke @ 2003-11-19 17:22 ` Brian Hurt 2003-11-19 17:45 ` Dustin Sallings 1 sibling, 1 reply; 7+ messages in thread From: Brian Hurt @ 2003-11-19 17:22 UTC (permalink / raw) To: Dustin Sallings; +Cc: Caml Mailing List On Tue, 18 Nov 2003, Dustin Sallings wrote: > > On Nov 18, 2003, at 22:50, Brian Hurt wrote: > > > This function is not tail recursive. Basically, if the recursive call > > either a) is wrapped in a try block, or b) has it's return value > > modified > > I guess I don't understand the point of clause a. The try block > doesn't seem like it should prevent the optimization. What would happen if f just happened to throw an End_of_file exception? Not to mention the fact that it's tricky for the compiler to determine that the call to fold_lines can't throw an End_of_file. So the compiler just assumes that both might, and thus has to keep the try/catch block, and the context (stack frame) of the function, alive until both are complete. -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Caml-list] tail call optimization 2003-11-19 17:22 ` Brian Hurt @ 2003-11-19 17:45 ` Dustin Sallings 0 siblings, 0 replies; 7+ messages in thread From: Dustin Sallings @ 2003-11-19 17:45 UTC (permalink / raw) To: Brian Hurt; +Cc: Caml Mailing List On Nov 19, 2003, at 9:22, Brian Hurt wrote: > What would happen if f just happened to throw an End_of_file exception? > Not to mention the fact that it's tricky for the compiler to determine > that the call to fold_lines can't throw an End_of_file. So the > compiler > just assumes that both might, and thus has to keep the try/catch block, > and the context (stack frame) of the function, alive until both are > complete. Ooh, this is the key, the compiler doesn't know that that exception can't be thrown. This goes back to exception handling thread from earlier, I think. If the compiler knew the exception wouldn't be thrown, then the tail call optimization would be possible. Anyway, I think this clears up my confusion, thanks. -- Dustin Sallings ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2003-11-19 17:46 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-11-19 5:24 [Caml-list] tail call optimization Dustin Sallings [not found] ` <3FBB0247.2000401@cs.caltech.edu> 2003-11-19 6:07 ` Dustin Sallings 2003-11-19 6:50 ` Brian Hurt 2003-11-19 6:24 ` Dustin Sallings 2003-11-19 11:40 ` Frederic van der Plancke 2003-11-19 17:22 ` Brian Hurt 2003-11-19 17:45 ` Dustin Sallings
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox