Racket: Identifying tail recursion?

浪尽此生 提交于 2019-12-05 08:32:39

You are correct, in the first version the recursive call returns to and, whereas in the second version the recursive call is a tail call.

However, and is a macro, and is generally expanded using if

(define (ascending list)
  (if (<= (length list) 1)
      #t
      (if (< (car list) (car (cdr list)))
          (ascending (cdr list))
           #f)))

which is tail recursive.

DrRacket can help you determine whether a call is in tail position or not. Click the "Syntax Check" button. Then move the mouse pointer to the left parenthesis of the expression in question. In your example I get this:

The purple arrow shows that the expression is in tail-position.

From the manual:

Tail Calls: Any sub-expression that is (syntactically) in tail-position with respect to its enclosing context is annotated by drawing a light purple arrow from the tail expression to its surrounding expression.

One of the requirements for a function to be in tail position is that it's return value be usable as the return value of the parent function without modification or inspection. That is, the parent function should be able to return immediately, having evaluated the tail position statement.

On first appearance, your first function,inspects the return value of ascending. It seems that doesn't return ascending's value but, instead, a value derived from it. However, according to the relevant section of the R5RS spec, the final expression in an and statement is in tail position. (When I'm properly awake, I know this)

So you are wrong.

http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-6.html#%_sec_3.5

(Note: edited to correct my initial hasty answer).

Racket's documentation on tail positions says that the place to check what's in tail position and what's not is the documentation for the particular form:

Tail-position specifications provide a guarantee about the asymptotic space consumption of a computation. In general, the specification of tail positions goes with each syntactic form, like if.

Racket's docs on and say (emphasis added):

(and expr ...)

If no exprs are provided, then result is #t.

If a single expr is provided, then it is in tail position, so the results of the and expression are the results of the expr.

Otherwise, the first expr is evaluated. If it produces #f, the result of the and expression is #f. Otherwise, the result is the same as an and expression with the remaining exprs in tail position with respect to the original and form.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!