Recursive Multiplication in Scheme (positive numbers) - recursion

I am new to scheme and am trying to gain an understanding of how the following piece of code is able to recursively multiply two numbers provided (how is the function stack occurring here):
;Recursive Arithmetic
(define increment
(lambda (x)
(+ x 1)))
(define decrement
(lambda (x)
(- x 1)))
(define recursive-add
(lambda (x y)
(if (zero? y)
x
(recursive-add (increment x) (decrement y)))))
"Define Multiplication Recursively"
(define recursive-mult
(lambda (x y)
(if (zero? y)
0
(recursive-add x (recursive-mult x (decrement y)))))) ;else
(recursive-mult 9 5)
My first doubt is what part of the else section is executed first?
In the else section, if (decrement y) is executed first, then y is first decremented by 1, then the(recursive-mult x section runs next by which function calls itself, so the section (recursive-add x never gets called in this same line of code.
Now, if in the else section, the recursive-add x is executed first, x gets added first, then the recursive-mult x runs which runs the the whole function again and the (decrement y) is never reached.
Now I know either of my two assumptions above, or maybe both are wrong. Would someone be able to point me in the right direction please? I apologize if my question displays a high level of inadequacy in this subject but I really want to learn scheme properly. Thank you.

This is an answer in Common Lisp, in which I am more familiar, but the approach is the same. Here is a translation of your code:
(defpackage :so (:use :cl))
(in-package :so)
(defun add (x y)
(if (zerop y)
x
(add (1+ x) (1- y))))
(defun mul (x y)
(if (zerop y)
0
(add x (mul x (1- y)))))
The increment and decrement functions are not defined, I'm using 1+ and 1- which are equivalent.
In the else section, if (decrement y) is executed first, then y is first decremented by 1, then the(recursive-mult x section runs next by which function calls itself, so the section (recursive-add x never gets called in this same line of code.
You can use the substitution model to evaluate recursive functions.
(add (add 1 3) 1)
Let's evaluate first the first argument of the top-most and:
(add (add 2 2) 1)
(add (add 3 1) 1)
(add (add 4 0) 1)
(add 4 1)
Here the call eventually returned and the first argument is 4. Once the execution is resumed, the rest of the code for (add (add 1 3) 1) is executed, which is equivalent to:
(add 5 0)
And finally:
5
Each time you invoke the function a new frame is pushed on the call stack, which is what is shown in a trace:
(trace mul add)
The macro above in Common Lisp makes it so the mul and add functions are traced.
Now when I run a program, a trace is printed when they are entered and exited.
Let's try with small values:
(mul 2 3)
The trace is printed as follows (don't mind the SO:: prefix, this is part of the fully-qualified name of symbols):
0: (SO::MUL 2 3)
1: (SO::MUL 2 2)
2: (SO::MUL 2 1)
3: (SO::MUL 2 0)
3: MUL returned 0
3: (SO::ADD 2 0)
3: ADD returned 2
2: MUL returned 2
2: (SO::ADD 2 2)
3: (SO::ADD 3 1)
4: (SO::ADD 4 0)
4: ADD returned 4
3: ADD returned 4
2: ADD returned 4
1: MUL returned 4
1: (SO::ADD 2 4)
2: (SO::ADD 3 3)
3: (SO::ADD 4 2)
4: (SO::ADD 5 1)
5: (SO::ADD 6 0)
5: ADD returned 6
4: ADD returned 6
3: ADD returned 6
2: ADD returned 6
1: ADD returned 6
0: MUL returned 6
The difference with Scheme is that Scheme does not define the order by which function arguments are evaluated (it is left unspecified), so maybe your code would not exactly behave as above, but it should still compute the same answer (because there are no side effects).

Scheme has eager evaluation so if you have
(op1 expr1 (op2 1 (op3 expr2 expr3)))
Then op1 form will depend on expr1 and the form with op2 to be complete before op1 can be applied. If we have an implementation that
does left to right evaluation it will do it like this:
(let ((vexpr1 expr1)
(vexpr2 expr2)
(vexpr3 expr3))
(let ((vop3 (op3 vexpr2 vexpr3)))
(let ((vop2 (op2 1 vop3)))
(op1 vexpr1 vop2))))
So to answer your question the order in the same left to right Scheme will be:
(let ((vdy (decrement y)))
(let ((vrm (recursive-mult x vdy)))
(recursive-add x vrm)))
Same in CPS:
(decrement& y
(lambda (vdy)
(recursive-mult& x
vy
(lambda (vrm)
(recursive-add& x vrm continuation)))))
So in practice the application for the first round doesn't happen before the whole recursive-mult for the smaller expression happens first. Thus (recursive-mult 3 3) turns into
(recursive-add 3 (recursive-add 3 (recursive-add 3 0)))
And as you can see the last one is being done first, then the second one and the last addition to be performed is the one of the first round before recursion.

Related

How does scramble function works? (Chapter 1 of The Seasoned Schemer)

According to the book, this is what the function definition is,
The function scramble takes a non-empty tuple in which no argument is greater than its own index and returns a tuple of same length. Each number in the argument is treated as a backward index from its own position to a point earlier in tuple. The result at each position is obtained by counting backward from the current position according to this index.
And these are some examples,
; Examples of scramble
(scramble '(1 1 1 3 4 2 1 1 9 2)) ; '(1 1 1 1 1 4 1 1 1 9)
(scramble '(1 2 3 4 5 6 7 8 9)) ; '(1 1 1 1 1 1 1 1 1)
(scramble '(1 2 3 1 2 3 4 1 8 2 10)) ; '(1 1 1 1 1 1 1 1 2 8 2)
Here is the implementation,
(define pick
(λ (i lat)
(cond
((eq? i 1) (car lat))
(else (pick (sub1 i)
(cdr lat))))))
(define scramble-b
(lambda (tup rev-pre)
(cond
((null? tup) '())
(else
(cons (pick (car tup) (cons (car tup) rev-pre))
(scramble-b (cdr tup)
(cons (car tup) rev-pre)))))))
(define scramble
(lambda (tup)
(scramble-b tup '())))
This is a case where using a very minimal version of the language means that the code is verbose enough that understanding the algorithm is not perhaps easy.
One way of dealing with this problem is to write the program in a much richer language, and then work out how the algorithm, which is now obvious, is implemented in the minimal version. Let's pick Racket as the rich language.
Racket has a function (as does Scheme) called list-ref: (list-ref l i) returns the ith element of l, zero-based.
It also has a nice notion of 'sequences' which are pretty much 'things you can iterate over' and a bunch of constructs whose names begin with for for iterating over sequences. There are two functions which make sequences we care about:
in-naturals makes an infinite sequence of the natural numbers, which by default starts from 0, but (in-naturals n) starts from n.
in-list makes a sequence from a list (a list is already a sequence in fact, but in-list makes things clearer and there are rumours also faster).
And the iteration construct we care about is for/list which iterates over some sequences and collects the result from its body into a list.
Given these, then the algorithm is almost trivial: we want to iterate along the list, keeping track of the current index and then do the appropriate subtraction to pick a value further back along the list. The only non-trivial bit is dealing with zero- vs one-based indexing.
(define (scramble l)
(for/list ([index (in-naturals)]
[element (in-list l)])
(list-ref l (+ (- index element) 1))))
And in fact if we cause in-naturals to count from 1 we can avoid the awkward adding-1:
(define (scramble l)
(for/list ([index (in-naturals 1)]
(element (in-list l)))
(list-ref l (- index element))))
Now looking at this code, even if you don't know Racket, the algorithm is very clear, and you can check it gives the answers in the book:
> (scramble '(1 1 1 3 4 2 1 1 9 2))
'(1 1 1 1 1 4 1 1 1 9)
Now it remains to work out how the code in the book implements the same algorithm. That's fiddly, but once you know what the algorithm is it should be straightforward.
If the verbal description looks vague and hard to follow, we can try following the code itself, turning it into a more visual pseudocode as we go:
pick i [x, ...ys] =
case i {
1 --> x ;
pick (i-1) ys }
==>
pick i xs = nth1 i xs
(* 1 <= i <= |xs| *)
scramble xs =
scramble2 xs []
scramble2 xs revPre =
case xs {
[] --> [] ;
[x, ...ys] -->
[ pick x [x, ...revPre],
...scramble2 ys
[x, ...revPre]] }
Thus,
scramble [x,y,z,w, ...]
=
[ nth1 x [x] (*x=1..1*)
, nth1 y [y,x] (*y=1..2*)
, nth1 z [z,y,x] (*z=1..3*)
, nth1 w [w,z,y,x] (*w=1..4*)
, ... ]
Thus each element in the input list is used as an index into the reversed prefix of that list, up to and including that element. In other words, an index into the prefix while counting backwards, i.e. from the element to the left, i.e. towards the list's start.
So we have now visualized what the code is doing, and have also discovered requirements for its input list's elements.

Non-tail recursive function that returns the last element in list without using reverse?

Im trying to make a non-tail recursive function returns the last element of a list without using reverse, map, iteration, mutation of any sort (built in or user-built). So far I have successfully made a tail-recursive version and a non-tail version that uses reverse func. But I just cannot figure how to make a non-tail recursive function.
I really appreciate your help!
Imagine you have the tail recursive version like this:
(define (last-element lst)
(if base-case-expression
result-expression
recursion-expression))
Now in order to not make it tail recursive you just make your function do something with the result. eg. cache it in a binding and then return:
(define (last-element lst)
(if base-case-expression
result-expression
(let ((result recursion-expression))
result)))
Here the recursive call is not the tail position. However a sufficiently smart compiler might make compiled code that is tail recursive. Eg. a lot of Scheme implementations transform code to continuation passing style and then every call becomes a tail call and stack is replaced with growing closures. The result of that on both versions will be very similar.
Note: for some reason I wrote this answer using Common Lisp, before noticing that the question was tagged with scheme, racket, and lisp. In any case, Common Lisp falls under the latter tag, and the code is easily adapted to either Scheme or Racket.
For a function to be non-tail recursive, you need to place recursive calls so that they are not in tail position, i.e., so that no further operations are needed on the results of the recursive call before it is returned. So, you need a recursive strategy for getting to the last element of a list that does further operations on the result of recursive calls.
One strategy would be to build a "reversed list" on the way back up from the base case, taking that list apart at the same time so that the desired result is left at the end. Here is a reversal function to show the idea without taking anything apart:
(defun reversal (xs)
(if (cdr xs)
(cons (reversal (cdr xs)) (car xs))
xs))
The above function builds a nested dotted list with the elements of the input list in reverse:
CL-USER> (reversal '(1 2 3 4 5))
(((((5) . 4) . 3) . 2) . 1)
Now, the car function could be called numerous times on this result to get the last element of the input, but we can just do this as the new list is constructed:
(defun my-last (xs)
(car (if (cdr xs)
(cons (my-last (cdr xs)) (car xs))
xs)))
Here the my-last function is called after calling (trace my-last):
CL-USER> (trace my-last)
(MY-LAST)
CL-USER> (my-last '(1 2 3 4 5))
0: (MY-LAST (1 2 3 4 5))
1: (MY-LAST (2 3 4 5))
2: (MY-LAST (3 4 5))
3: (MY-LAST (4 5))
4: (MY-LAST (5))
4: MY-LAST returned 5
3: MY-LAST returned 5
2: MY-LAST returned 5
1: MY-LAST returned 5
0: MY-LAST returned 5
5
This solution requires two operations on the result of calling my-last, i.e., cons and car. It does seem possible that an optimizer could notice that car is being called on the result of a cons, and optimize my-last to something like:
(defun my-last-optimized (xs)
(if (cdr xs)
(my-last-optimized (cdr xs))
(car xs)))
If this were the case, then the optimized code would be tail recursive, and tail call optimizations could then be applied. I do not know if any lisp implementations can do this sort of optimization.
An alternate strategy would be to store the original list and then to take it apart on the way back up from the base case using cdr. Here is a solution using a helper function:
(defun my-last-2 (xs)
(car (my-last-helper xs xs)))
(defun my-last-helper (xs enchilada)
(if (cdr xs)
(cdr (my-last-helper (cdr xs) enchilada))
enchilada))
This also works as expected. Here is an example, again using trace to see the function calls. This time both my-last-2 and my-last-helper have been traced:
(trace my-last-2 my-last-helper)
(MY-LAST-2 MY-LAST-HELPER)
CL-USER> (my-last-2 '(1 2 3 4 5))
0: (MY-LAST-2 (1 2 3 4 5))
1: (MY-LAST-HELPER (1 2 3 4 5) (1 2 3 4 5))
2: (MY-LAST-HELPER (2 3 4 5) (1 2 3 4 5))
3: (MY-LAST-HELPER (3 4 5) (1 2 3 4 5))
4: (MY-LAST-HELPER (4 5) (1 2 3 4 5))
5: (MY-LAST-HELPER (5) (1 2 3 4 5))
5: MY-LAST-HELPER returned (1 2 3 4 5)
4: MY-LAST-HELPER returned (2 3 4 5)
3: MY-LAST-HELPER returned (3 4 5)
2: MY-LAST-HELPER returned (4 5)
1: MY-LAST-HELPER returned (5)
0: MY-LAST-2 returned 5
5
In this case, the only operation required after recursive calls to my-last-2 return is cdr, but that is enough to prevent this from being a tail call.

Is (lambda (x) ... ) with parenthesis placed in a certain way used for limiting scope?

A classic enumeration using unfold:
(unfold-left (lambda (x)
(if (> x 10)
(#;no values)
(+ x 1)))
#;from 0)
===> (0 1 2 3 4 5 6 7 8 9 10))
if limiting the scope is not needed is there any way to just write x without the lambda?
unfold is implemented like this:
(define (unfold p f g seed (tail-gen (λ (_) '())))
(let recur ((seed seed))
(if (p seed)
(tail-gen seed)
(cons (f seed)
(recur (g seed))))))
As you can see p, f, g, and tail-gen are all procedures since they get surrounded by parentheses in the implementation. If they are not procedures you will get an application: not a procedure error.
You are using unfold wrong. you need a procedure that takes the current value and return wether or not you are finished. Second is a procedure that takes the seed and return what value to collect and the third is a procedure to create the next seed. The optional tail-gen takes the seed and creates the tail where the empty list will be used if not provided. Here is how you make a list from 0 to 10:
#lang racket
(require srfi/1)
(require srfi/26)
(unfold (cut > <> 10) identity add1 0)
; ==> (0 1 2 3 4 5 6 7 8 9 10)
And of course, (range 11) gives the same answer.

Function only outputs a 1

I am trying to create a lisp code that reads 2 integers and outputs all numbers between the two. my current code is
(defun range (x y)
(if (< x y)
x
(1+ (range(x y))))
the code compiles and runs but only outputs "1".
Not sure what exactly you want but the closest I could come up with is:
(defun range (x y)
(when (< x y)
(print x)
(range (1+ x) y)))
Testing
CL-USER> (range 3 7)
3
4
5
6
NIL
Pay attention to
indent your code properly
use when (or cond or progn ...) if you want to do more than one action after a condition
the 1+ is used to increment a parameter, not the complete expression; think of it as a loop variable in a traditional language
your variable only becomes 'visible' outside the function if you print it, or add it to a result list.
Also, tag your question common-lisp for better visibility.
EDIT
proof that the original code does run on some instances of CLISP:
Welcome to GNU CLISP 2.49 (2010-07-07) <http://clisp.cons.org/>
[1]> (range 1 5)
*** - EVAL: undefined function RANGE
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead of (FDEFINITION 'RANGE).
RETRY :R2 Retry
STORE-VALUE :R3 Input a new value for (FDEFINITION 'RANGE).
ABORT :R4 Abort main loop
Break 1 [2]>
[3]> (defun range (x y)
(if (< x y)
x
(1+ (range(x y)))))
RANGE
[4]> (range 1 5)
1
[5]>

getting an interval of a vector

I want to take an interval of a vector in Scheme. I know there is a procedure named vector->values, but seems like it returns each element separately, while I want to get the result as a vector. How can I achieve this?
> (vector->values (vector 1 2 3 4 5) 0 3)
1
2
3
while I need:
#(1 2 3)
If you're using PLT, you have a few easy ways to get this:
(define (subvector v start end)
(list->vector (for/list ([i (in-vector v start end)]) i)))
(define (subvector v start end)
(build-vector (- end start) (lambda (i) (vector-ref v (+ i start)))))
(define (subvector v start end)
(define new (make-vector (- end start)))
(vector-copy! new 0 v start end)
new)
The last one is probably going to be the fastest. The reason that there is no such operation that is built-in is that people usually don't do that. When you're dealing with vectors in Scheme, you're usually doing so because you want to optimize something so returning a vector and a range instead of allocating a new one is more common.
(And if you think that this is useful, please suggest it on the PLT mailing list.)
The Scheme R6RS standard has make-vector, vector-ref, vector-set! and vector-length. With that you can write your own function subvector, which does not seem to be part of R6RS (!). Some Scheme implementation have something like subvector already.
You can also switch to Common Lisp, which provides the function SUBSEQ in the standard.
Here is a portable R6RS version using SRFI 43:
#!r6rs
(import (rnrs base)
(prefix (srfi :43) srfi/43:))
(srfi/43:vector-copy (vector 1 2 3 4 5) 0 3)
#lang scheme
(define (my-vector-value v l h c)
(if (and (>= c l) (< c h))
(cons (first v) (my-vector-value (rest v) l h (add1 c)))
empty))
(list->vector (my-vector-value (vector->list (vector 1 2 3 4 5)) 0 3 0))
Ghetto? Yes, very. But it only took two minutes to write and gets the job done.
(I find it's generally easier to play with lists in Scheme)
you want subvector:
(subvector (vector 1 2 3 4 5) 0 3)

Resources