How to create a function that multiplies all numbers between 1 and "x" with dotimes? - scheme

I'm making a function that multiplies all numbers between an 1 input and a "x" input with dotimes loop. If you please, check my function and say what's wrong since I don't know loops very well in Scheme.
(define (product x)
(let ((result 1))
(dotimes (temp x)
(set! result (* temp (+ result 1))))
result))

Use recursion. It is the way to do things in Scheme/Racket. And try to never use set! and other functions that change variables unless there really is no other choice.
Here's a textbook example of recursion in Scheme:
(define factorial
(lambda (x)
(if (<= x 1)
1
(* x (factorial (- x 1))))))

Related

Assigning variables in Scheme without using set

I am trying to create a global score in my scheme program and it will either increase by 1, decrease by 1 or not change for each iteration of my function. For example, I have this in my function when I want the score to increase by 1:
(set! score (+ score 1)))
I am able to do this using set! but I need a way to achieve it without using the set! operation. Any help would be appreciated!
The trick is to realise that you can replace something like this:
(define (my-game ...)
(let ([score 0])
(some-kind-of-looping-construct
...
(if <not-done>
(begin
(set! score <new-score-value>)
(continue-loop))
score))))
With something like this:
(define (my-game ...)
(define (loop ... score ...)
...
(if <not-done>
(loop ... <new-score-value> ...)
score))
(loop ... 0 ...))
In particular you can replace any kind of looping construct which repeatedly assigns to some variable by textually (but not actually) recursive calls to some function which repeatedly binds a variable.
To be concrete about this let's imagine we have a looping construct which looks like
(loop exit-fn form ...)
So loop is the loop construct, and exit-fn is the magic thing we call to exit the loop.
And I'll assume there is some function run-game-round which takes a round number and the current score, runs a round of the game and returns the new score.
So using this construct we can write the skeleton of some kind of game loop:
(let ((round 0)
(score 0))
(loop exit
(set! score (run-game-round round score))
(set! round (+ round 1))
(cond
[(> score 100)
(exit 'win)]
[(> round 100)
(exit 'lose)])))
And this is fairly horrible code.
But we can replace this code with this:
(begin
(define (run-game round score)
(cond [(> score 100)
'win]
[(> round 100)
'lose]
[else
(run-game (+ round 1)
(run-game-round round score))]))
(run-game 0 0))
And this code does exactly the same thing but there is no assignment anywhere.
No set!: We can input list or given number of args and use function recursive.
#lang racket
(define (play-game game-round-lst)
(local [(define (make-score s)
(cond
[(equal? s 'win) 1]
[(equal? s 'drew) 0]
[(equal? s 'lose) -1]))]
(apply + (map make-score game-round-lst))))
;;; TEST
(play-game '(lose win drew lose win)) ; 0
(play-game '(win lose drew win lose win lose)) ; 0
Use set! in local function.
In this method you can build new game without worry about lost state in each game.
#lang racket
(define (make-game)
(local [(define score 0)
(define (setup-score n)
(set! score (+ n score)))
(define (service-manager msg)
(cond
[(equal? msg 'win)
(setup-score 1)]
[(equal? msg 'drew)
(setup-score 0)]
[(equal? msg 'lose)
(setup-score -1)]
[(equal? msg 'show-score)
score]))]
service-manager))
;;; TEST
(define game1 (make-game))
(define game2 (make-game))
(game1 'win)
(game2 'win)
(game1 'drew)
(game2 'drew)
(game1 'lose)
(game2 'lose)
(game1 'show-score) ; 0
(game2 'show-score) ; 0

Scheme Test cases

I was asked to create a function that takes 2 functions as parameters and an integer. The functions are supposed to check for conditions, if they are met then it evaluates to true or false.
Here is my code, but how do I test my code. What parameters do I put into the function to test? I tried (find harmonic even? 6) and it gives me an error. Harmonic is a function that takes the nth number in harmonic and sums them all up. Can someone please help? What test cases can I use?
(define (find sequence test n)
(define (helper x found)
(let ((fx (sequence x)))
(if (test fx)
(if (= (+ found 1) n) fx
(helper (+ x 1) (+ found 1)))
(helper (+ x 1) found)))) (helper 1 0))

Meaning of letrec in Scheme/Racket

So as far as I understand, the following: let, let*, letrec and letrec* are synthetics sugars used in Scheme/Racket.
Now, if I have a simple program:
(let ((x 1)
(y 2))
(+ x y))
It is translated into:
((lambda (x y) (+ x y)) 1 2)
If I have:
(let* ((x 1)
(y 2))
(+ x y))
It is translated into:
((lambda (x) ((lambda (y) (+ x y))) 2) 1)
Now, for my first question, I understand the meaning of a letrec expression, which enables one to use recursion inside a let, but I do not understand how exactly it is done. What is letrec translated to?
For example, what will
(letrec ((x 1)
(y 2))
(+ x y))
be translated into?
The second question is similar about letrec* - But for letrec* I do not understand how exactly it differs from letrec? And also, what will a letrec* expression be translated into?
See the paper "Fixing Letrec: A Faithful Yet Efficient Implementation
of Scheme’s Recursive Binding Construct" by Oscar Waddell, Dipanwita Sarkar, and,
R. Kent Dybvig.
The paper starts with a simple version and proceeds to explain a more sophisticated expansion:
https://www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf
Since you example does not have any procedures and no real expressions I'd say you could implement it as:
(let ((x 1) (y 2))
(+ x y))
But to support the intention of the form a basic implementaiton might do something like this:
(let ((x 'undefined) (y 'undefined))
(let ((tmpx 1) (tmpy 2))
(set! x tmpx)
(set! y tmpy))
(+ x y))
Now. letrec is for lambdas to be able to call themselves by the name. So imagine this:
(let ((fib (lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2)))))))
(fib 10))
It's important to understand that this does not work and why. Transforming it into a lambda call makes it so easy to see:
((lambda (fib)
(fib 10))
(lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2))))))
Somehow you need to evaluate the lambda after fib is created. Lets imagine we do this:
(let ((fib 'undefined))
(set! fib (lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2))))))
(fib 10))
Alternatively you can do it with a Z combinator to make it pure:
(let ((fib (Z (lambda (fib)
(lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2)))))))))
(fib 10))
This requires more work by the implementation, but at least you do without mutation. To make it work with several mutual recursive bindings probably takes some more work but I'm convinced its doable.
These are the only two ways to do this properly. I know clojure has a recur which imitates recursion but in reality is a a goto.
For variables that do not make closures from the letrec bindings they work as let and later more like let* since Soegaards answer about fix is backwards compatible and some has adapted it. If you write compatible code though you should not be tempted to assume this.

Why Scheme requires apply in Y-combinator implementation, but Racket doesn't?

Here is the Y-combinator in Racket:
#lang lazy
(define Y (λ(f)((λ(x)(f (x x)))(λ(x)(f (x x))))))
(define Fact
(Y (λ(fact) (λ(n) (if (zero? n) 1 (* n (fact (- n 1))))))))
(define Fib
(Y (λ(fib) (λ(n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))
Here is the Y-combinator in Scheme:
(define Y
(lambda (f)
((lambda (x) (x x))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
(define fac
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
1
(* x (f (- x 1))))))))
(define fib
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
x
(+ (f (- x 1)) (f (- x 2))))))))
(display (fac 6))
(newline)
(display (fib 6))
(newline)
My question is: Why does Scheme require the apply function but Racket does not?
Racket is very close to plain Scheme for most purposes, and for this example, they're the same. But the real difference between the two versions is the need for a delaying wrapper which is needed in a strict language (Scheme and Racket), but not in a lazy one (Lazy Racket, a different language).
That wrapper is put around the (x x) or (g g) -- what we know about this thing is that evaluating it will get you into an infinite loop, and we also know that it's going to be the resulting (recursive) function. Because it's a function, we can delay its evaluation with a lambda: instead of (x x) use (lambda (a) ((x x) a)). This works fine, but it has another assumption -- that the wrapped function takes a single argument. We could just as well wrap it with a function of two arguments: (lambda (a b) ((x x) a b)) but that won't work in other cases too. The solution is to use a rest argument (args) and use apply, therefore making the wrapper accept any number of arguments and pass them along to the recursive function. Strictly speaking, it's not required always, it's "only" required if you want to be able to produce recursive functions of any arity.
On the other hand, you have the Lazy Racket code, which is, as I said above, a different language -- one with call-by-need semantics. Since this language is lazy, there is no need to wrap the infinitely-looping (x x) expression, it's used as-is. And since no wrapper is required, there is no need to deal with the number of arguments, therefore no need for apply. In fact, the lazy version doesn't even need the assumption that you're generating a function value -- it can generate any value. For example, this:
(Y (lambda (ones) (cons 1 ones)))
works fine and returns an infinite list of 1s. To see this, try
(!! (take 20 (Y (lambda (ones) (cons 1 ones)))))
(Note that the !! is needed to "force" the resulting value recursively, since Lazy Racket doesn't evaluate recursively by default. Also, note the use of take -- without it, Racket will try to create that infinite list, which will not get anywhere.)
Scheme does not require apply function. you use apply to accept more than one argument.
in the factorial case, here is my implementation which does not require apply
;;2013/11/29
(define (Fact-maker f)
(lambda (n)
(cond ((= n 0) 1)
(else (* n (f (- n 1)))))))
(define (fib-maker f)
(lambda (n)
(cond ((or (= n 0) (= n 1)) 1)
(else
(+ (f (- n 1))
(f (- n 2)))))))
(define (Y F)
((lambda (procedure)
(F (lambda (x) ((procedure procedure) x))))
(lambda (procedure)
(F (lambda (x) ((procedure procedure) x))))))

Not returning the answer i need

(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))(* n (car ls))(checksum-2 (cdr ls)))))
Ok, I have this code, its suppose to, if I wrote it right, the number (n) should increase by one every time it goes through the list, so n (in reality) should be like 1 2 3 4, but I want n to be multiplied by the car of the list.
Everything loads, but when the answer is returned I get 0.
Thanks!
If you format your code differently, you might have an easier time seeing what is going on:
(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))
(* n (car ls))
(checksum-2 (cdr ls)))))
Inside the let form, the expressions are evaluated in sequence but you're not using the results for any of them (except the last one). The results of the addition and multiplication are simply discarded.
What you need to do in this case is define a new helper function that uses an accumulator and performs the recursive call. I'm going to guess this is homework or a learning exercise, so I'm not going to give away the complete answer.
UPDATE: As a demonstration of the sort of thing you might need to do, here is a similar function in Scheme to sum the integers from 1 to n:
(define (sum n)
(define (sum-helper n a)
(if (<= n 0)
a
(sum-helper (- n 1) (+ a n))))
(sum-helper n 0))
You should be able to use a similar framework to implement your checksum-2 function.

Resources