"and" and tail recursion - recursion

Can I build iterative process using recursive call in and statement?
For example, purpose, we have function foo that doesn't do anything. What kind of process it will create (iterative or recursion)?
(define (foo? bar)
(if (< bar 0) true (and (> 10 1) (foo? (- bar 1)))))

Yes, and is OK - you can read this in the standard.

For Lamberts sake, lets expand the syntax.
(define (foo? bar)
(if (< bar 0)
#t ; tail position, but no call
(if (> 10 1)
(foo? (- bar 1)) ; tail position
#f))) ; tail position, but no call

Related

Accessing call stack depth in Scheme

In order to demonstrate the effectiveness of tail recursion, I would like a way to access the depth of the call stack dynamically in Scheme.
Is there a way to do this? If not, is there a way to do this in other major functional languages (OCaml, Haskell, etc.)?
Racket allows you to store values in the call stack.
You can use this to keep track of the depth.
Here is how I would do it:
#lang racket
;;; This module holds the tools for keeping track of
;;; the current depth.
(module depth racket
(provide (rename-out [depth-app #%app])
current-depth)
(define (extract-current-continuation-marks key)
(continuation-mark-set->list (current-continuation-marks) key))
(define (current-depth)
(car (extract-current-continuation-marks 'depth)))
(define-syntax (depth-app stx)
(syntax-case stx ()
[(_depth-app proc args ...)
#'(let ([p (with-continuation-mark 'depth (+ (current-depth) 1)
proc)]
[as (with-continuation-mark 'depth (+ (current-depth) 1)
(list args ...))])
(apply p as))])))
;;; Importing the #%app from the depth module will override
;;; the standard application to use depth-app which keeps
;;; track of the depth.
(require 'depth)
(with-continuation-mark 'depth 0 ; set the initial depth to 0
(let ()
;;; Example: foo is tail recursive
(define (foo n)
(displayln (list 'foo n (current-depth)))
(if (< n 5)
(foo (+ n 1))
'done))
;;; bar is not tail recursive
(define (bar n)
(displayln (list 'bar n (current-depth)))
(if (< n 5)
(cons n (bar (+ n 1)))
'()))
;;; Call the examples
(foo 0)
(bar 0)))
The output is:
(foo 0 2)
(foo 1 2)
(foo 2 2)
(foo 3 2)
(foo 4 2)
(foo 5 2)
(bar 0 2)
(bar 1 3)
(bar 2 4)
(bar 3 5)
(bar 4 6)
(bar 5 7)
'(0 1 2 3 4)
The output shows that the depth doesn't increase in foo and that it does in bar.
There is no standard way of doing it.
Tail call optimization == no call stack increase. You demonstrate it by writing what normally would blow the stack and run it.
You might get a short stack trace when signalling an error deep in, but how it looks like is implentation specific.
In CL you can trace functions and you'll see no output on consecutive tail calls when it's tail call optimized.
Lazy languages do not need tail recursion since evaluation is by need.

is let working as a goto instruction in tail recursion?

I have found the following implementation of the Binary Search in Scheme:
(define (binary-search value vector)
(let helper ((low 0)
(high (- (vector-length vector) 1)))
(if (< high low)
#f
(let ((middle (quotient (+ low high) 2)))
(cond ((> (vector-ref vector middle) value)
(helper low (- middle 1)))
((< (vector-ref vector middle) value)
(helper (+ middle 1) high))
(else middle))))))
according to what it says in the comments, the above function uses tail-recursion to call to the help function. I was wondering if this works like a GOTO instruction, because I do not see that there is a proper "recursive" call to the binary-search function.
In this case it is proper to say that works like a goto instruction?
What you're seeing is called a named let. (I wrote a blog post about how named let works, if you're curious.) The code you have is exactly the same as:
(define (binary-search value vector)
(define (helper low high)
(if (< high low)
#f
(let ((middle (quotient (+ low high) 2)))
(cond ((> (vector-ref vector middle) value)
(helper low (- middle 1)))
((< (vector-ref vector middle) value)
(helper (+ middle 1) high))
(else middle)))))
(helper 0 (- (vector-length vector) 1)))
In other words, it is tail-recursing, on helper rather than on binary-search. But tail recursion is happening.
Some people think of tail-recursion like goto, but I don't consider that a helpful comparison. The only thing in common between the two is that you can implement loops with tail recursion, much like you can do with goto. But the similarities end there: tail-recursion is a special kind of recursion (where the current call frame is replaced with the tail call), but it's still recursion; goto jumps to an arbitrary point in the code, but it's a totally imperative operation with no relation to recursion.
A let is just syntactic sugar for lambdas. So for example:
(let ((i 2)
(j 5)
(* i j))
is equivalent to
((lambda (i j) (* i j)) 2 5)
The let in your code is called a named let, because you provided a label for it. So basically, your lambda in disguise is bound to a name. In that sense, it is a goto. However, you need to be in the scope of the let to be able to "jump" to it. The function is tail recursive because you are not deferring any computations. At any point in time, you only require the current values of i and j to be able to proceed with the computation.

How do I get rid of the #<void> that results from this recursive Scheme function?

I'm supposed to write a recursive function that applies another function to a set of consecutive integers and returns a list. If start is > than stop, I'm just supposed to return an empty set.
Here's what I've got. I'm not sure this is the best solution to the problem, but...
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)(myfunction (+ start 1) stop fn)))
)
(define (foo val1) ; just to demonstrate myfunction
(* val1 2))
When I try to use it in the scheme interpreter, I get this:
(myfunction 0 5 foo)
(0 2 4 6 8 10 . #<void>)
What can I do to get rid of the void thing? I'm a bit confused.
Consider what happens if you do:
> (list (if #f 'then-value))
;=> (#<void>)
Your function has an if without an "else" part.
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
; missing something here
))
What should the list be when it's not the case that (<= start stop)? I'd guess that a reasonable default would be the empty list, so that when (myfunction (+ start 1) stop fn) is finally called with values of start and stop such that start is greater than stop, you get the empty list, so that (cons (fn start) (myfunction ...)) has an empty list as its second argument:
(define (myfunction start stop fn)
(if (<= start stop)
(cons (fn start)
(myfunction (+ start 1) stop fn))
'()))
(myfunction 0 5 (lambda (x) (* x 2)))
;=> (0 2 4 6 8 10)
For more about why the output was (<elements> . #<void>) (i.e., why it's got the dot at the end), have a look at this answer (disclaimer: it's my answer) to Recursive range in Lisp adds a period?.

Tail Recursive counting function in Scheme

The function is supposed to be tail-recursive and count from 1 to the specified number. I think I'm fairly close. Here's what I have:
(define (countup l)
(if (= 1 l)
(list l)
(list
(countup (- l 1))
l
)
)
)
However, this obviously returns a list with nested lists. I've attempted to use the append function instead of the second list to no avail. Any guidance?
Here's an incorrect solution:
(define (countup n)
(define (help i)
(if (<= i n)
(cons i (help (+ i 1)))
'()))
(help 1))
This solution:
uses a helper function
recurses over the numbers from 1 to n, cons-ing them onto an ever-growing list
Why is this wrong? It's not really tail-recursive, because it creates a big long line of cons calls which can't be evaluated immediately. This would cause a stack overflow for large enough values of n.
Here's a better way to approach this problem:
(define (countup n)
(define (help i nums)
(if (> i 0)
(help (- i 1)
(cons i nums))
nums)))
(help n '()))
Things to note:
this solution is better because the calls to cons can be evaluated immediately, so this function is a candidate for tail-recursion optimization (TCO), in which case stack space won't be a problem.
help recurses over the numbers backwards, thus avoiding the need to use append, which can be quite expensive
You should use an auxiliar function for implementing a tail-recursive solution for this problem (a "loop" function), and use an extra parameter for accumulating the answer. Something like this:
(define (countup n)
(loop n '()))
(define (loop i acc)
(if (zero? i)
acc
(loop (sub1 i) (cons i acc))))
Alternatively, you could use a named let. Either way, the solution is tail-recursive and a parameter is used for accumulating values, notice that the recursion advances backwards, starting at n and counting back to 0, consing each value in turn at the beginning of the list:
(define (countup n)
(let loop ((i n)
(acc '()))
(if (zero? i)
acc
(loop (sub1 i) (cons i acc)))))
Here a working version of your code that returns a list in the proper order (I replaced l by n):
(define (countup n)
(if (= 1 n)
(list n)
(append (countup (- n 1)) (list n))))
Sadly, there is a problem with this piece of code: it is not tail-recursive. The reason is that the recursive call to countup is not in a tail position. It is not in tail position because I'm doing an append of the result of (countup (- l 1)), so the tail call is append (or list when n = 1) and not countup. This means this piece of code is a normal recusrive function but to a tail-recursive function.
Check this link from Wikipedia for a better example on why it is not tail-recusrive.
To make it tail-recursive, you would need to have an accumulator responsible of accumulating the counted values. This way, you would be able to put the recursive function call in a tail position. See the difference in the link I gave you.
Don't hesitate to reply if you need further details.
Assuming this is for a learning exercise and you want this kind of behaviour:
(countup 5) => (list 1 2 3 4 5)
Here's a hint - in a tail-recursive function, the call in tail position should be to itself (unless it is the edge case).
Since countup doesn't take a list of numbers, you will need an accumulator function that takes a number and a list, and returns a list.
Here is a template:
;; countup : number -> (listof number)
(define (countup l)
;; countup-acc : number, (listof number) -> (listof number)
(define (countup-acc c ls)
(if ...
...
(countup-acc ... ...)))
(countup-acc l null))
In the inner call to countup-acc, you will need to alter the argument that is checked for in the edge case to get it closer to that edge case, and you will need to alter the other argument to get it closer to what you want to return in the end.

Dolist evaluation error

I'm a CommonLisp noob with a question. I have these two functions below.
A helper function:
(defun make-rests (positions rhythm)
"now make those positions negative numbers for rests"
(let ((resultant-rhythm rhythm))
(dolist (i positions resultant-rhythm)
(setf (nth i resultant-rhythm) (* (nth i resultant-rhythm) -1)))))
And a main function:
(defun test-return-rhythms (rhythms)
(let ((positions '((0 1) (0)))
(result nil))
(dolist (x positions (reverse result))
(push (make-rests x rhythms) result))))
When I run (test-return-rhythms '(1/4 1/8)), it evaluates to: ((1/4 -1/8) (1/4 -1/8))
However, I expected: (test-return-rhythms '(1/4 1/8)) to evaluate to: ((-1/4 -1/8) (-1/4 1/8)).
What am I doing wrong?
Your implementation of make-rests is destructive.
CL-USER> (defparameter *rhythm* '(1/4 1/4 1/4 1/4))
*RHYTHM*
CL-USER> (make-rests '(0 2) *rhythm*)
(-1/4 1/4 -1/4 1/4)
CL-USER> *rhythm*
(-1/4 1/4 -1/4 1/4)
So, if you run your test, the second iteration will see (-1/4 -1/8), and (make-rests '(0) '(-1/4 -1/8)) returns (1/4 -1/8). Your use of let in make-rests does not copy the list, it just creates a new binding that references it. Use copy-list in your let, or write a non-destructive version in the first place:
(defun make-rests (positions rhythm)
(loop for note in rhythm
for i from 0
collect (if (member i positions) (* note -1) note)))

Resources