* [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
* 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 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 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: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