mark.warren
2019-1-4 14:15:06

I am (more than) a little confused about tail call optimisation. Does there have to be only one recursive call in the function for it to be optimised? Or can you have more than one as long as it is the last part of that function call? Sorry that is not very clear is it. This is a binary search function for a tree, (define (binary-search value tree) (cond [(null? tree) null] [(= value (tree-node-value tree)) tree] [(< value (tree-node-value tree)) (binary-search value (tree-node-left tree))] [(> value (tree-node-value tree)) (binary-search value (tree-node-right tree))] [else (display "Bad")]))


mark.warren
2019-1-4 14:15:15

```


mark.warren
2019-1-4 14:16:24

Are both binary-search calls tail calls or is this rubbish design?


andreiformiga
2019-1-4 15:42:13

I believe both are in tail position and will be optimized


andreiformiga
2019-1-4 15:43:18

it’s possible to check this taking a look at the generated bytecode


mark.warren
2019-1-4 15:44:22

@andreiformiga Thanks, I hoped they should be but was concerned that they weren’t. Haven’t got around to doing bytecode inspection yet, just the basics.


andreiformiga
2019-1-4 15:51:22

heh, actually I think they’re tail calls in the byte code as well


andreiformiga
2019-1-4 15:51:56

you’d have to look at the generated assembly to see if they become jumps, but I’m almost certain they do


andreiformiga
2019-1-4 15:52:28

you can test this by passing a really big tree and see if the memory footprint keeps growing


soegaard2
2019-1-4 15:52:56

@mark.warren Note: You can get DrRacket to show you, whether a call is a tail call or not: https://stackoverflow.com/a/12933639/23567


mark.warren
2019-1-4 15:53:05

Yeah, I will do that soon in some tests. Just checking I was on the right track.


mark.warren
2019-1-4 15:53:25

@soegaard2 Sweet, thanks.


soegaard2
2019-1-4 15:54:29

Also check out the description on tail call in R5RS. They show exactly which call positions give you a tail call.



mark.warren
2019-1-4 15:56:24

Thanks guys, that very useful.


greg
2019-1-4 16:03:35

You’ll run into people who are super picky about calling it “tail call optimization” vs. “tail call elimination”. In some languages, it’s an optimization the compiler might do. In Scheme and Racket, it’s guaranteed, you can depend on it (if something is truly in tail position). Which is why some people tend to get picky about saying “tail call elimination”.

Also it avoids fiery debates about whether it is spelled ‘optimisation’ vs. the obviously correct “optimization”. :grinning: