Scheme how to define var in if condition - scheme

I am newbie to Scheme programming and trying to define a var in if condition. For example, I have:
(if (< x y) (define x y) ) ;(GOAL: if x < y, than x=y..)
But I got the error:
let: bad syntax (not an identifier and expression for a binding) in:...
Any ideas how to resolve this, would be greatly appreciated.
p.s. Sorry for my English

Unlike imperative languages you should refrain not use define or set! to update variables where you can avoid it. In some circumstances it's needed, like in generators.
Since you don't have a full code example where you'd like to do this I cannot see what obvious solution is to be used.
The way to store intermediate values if by let or recursion:
;; within the let block x shadows the original x
;; with the smalles of the outer x and y
(let ((x (if (< x y) x y)))
(do-something x))
You can do several intermediates by let*
(let* ((tmp (+ x y))
(tmp2 (* tmp y))) ; tmp is bound here
(do-something-with tmp2)); or tmp and tmp2
You you can use recursion, where you update cur and lst in th innner procedure by recursion:
(define (mmin x . xs)
(define (min-aux cur lst)
(cond ((null? lst) cur)
((<= cur (car lst)) (min-aux cur (cdr lst)))
(else (min-aux (car lst) (cdr lst)))))
(min-aux x xs)) ; start recursion
It is an error to define something that is already defined so thats why I defined
If you need to do this top level you can:
(define min_xy (if (< x y) x y))
min_xy. To alter a binding destructively (get it to reference another value) you can use set!
(set! x (+ x 1)) ; increases x
You'll alter the most local definition and it's an error if it doesnæt already exist. This can be used for creating generators:
(define (generator start alter-proc)
(lambda () ; returns a procedure taking 0 arguments
(let ((old start)) ; temporary store what start points to
(set! start (alter-proc start)) ; change what the local start points to
old))) ; return the old value
(define counter (generator 1 (lambda (x) (+ x 1))))
(counter) ; ==> 1
(counter) ; ==> 2
(define doubler (generator 1 (lambda (x) (* x 2))))
(doubler) ; ==> 1
(doubler) ; ==> 2
(doubler) ; ==> 4

Using define is wrong; you are not defining a function here. There are two solutions:
(if (< x y) (set! x y) (void)) ; if x < y set x = y; else do nothing
Or
(set! x (if (< x y) y x)) ; sets x to y if (x<y) is true; else sets x to x

Related

How to duplicate a list in Scheme x times?

I am just starting to learn Scheme and using cons is a little confusing to me. I have a function duplicate (s number) where s is a list, and number is the number of times the list should be duplicated.
If I enter (duplicate '(1 2) 3), the output should be ((1 2) (1 2) (1 2))
My program looks like this, but when I run it, there is nothing in the output
(define (duplicate s number)
(cond [(null? s) '()]
[(> 0 number) (cons (list s) (duplicate s(- number 1)))]
))
What am I doing wrong here?
We want second input n become zero complete all list.
And we want output is a list so we use cons.
You can build your code by using minimum sample than add more complex data.
If input is (duplicate x 0) we want output is '().
If input is (duplicate x 1) we want output is '(x).
So your code should looks like this
(define (duplicate x n)
(cond
[(= n 0) '()]
[else
(cons x ...)]))
But we already know we want output is '(x) which is (cons x '()).
Obvious '() is (duplicate x 0)'s output. So we add (duplicate x (- n 1)) in second condition.
#lang racket
(define (duplicate x n)
(cond
[(= n 0) '()]
[else
(cons x (duplicate x (- n 1)))]))
;;; TEST
(duplicate '() 0)
(duplicate '() 3)
(duplicate '() 5) ; '(() () () () ())
(duplicate '(1 2) 5) ; '((1 2) (1 2) (1 2) (1 2) (1 2))
Or you can think like this way.
We have employee help us copy document.
employee-1 : We give him a number than he minus 1 than order employee-2 do his job
employee-2 : He copy a document than send message to employee-3
employee-3 : He supervision finish or not (number become zero). If not finish send message to employee-1.
So we want something like this
finish? -> no -> minus-1 -> copy -> finish? -> no -> minus-1 -> ...
#lang racket
(define x 1)
(define result '())
(define (employee-1 n)
(employee-2 (- n 1)))
(define (employee-2 n)
(begin
(set! result (cons x result))
(employee-3 n)))
(define (employee-3 n)
(if (= n 0)
result
(employee-1 n)))
;;; TEST
(employee-3 3) ; '(1 1 1)
Than we combine employee-1 to employee-3
(define x 1)
(define result '())
; (define (employee-1 n) (employee-2 (- n 1)))
(define (employee-2 n)
(begin
(set! result (cons x result))
(employee-3-v2 n)))
(define (employee-3-v2 n)
(if (= n 0)
result
(employee-2 (- n 1))))
;;; TEST
(employee-3-v2 3) ; '(1 1 1)
We use function input replace define global variable. So we have to remove set! and change input parameter.
; (define x 1)
; (define result '())
; (define (employee-1 n) (employee-2 (- n 1)))
(define (employee-2-v2 n x result)
(employee-3-v2 n x (cons x result)))
(define (employee-3-v2 n x result)
(if (= n 0)
result
(employee-2-v2 (- n 1) x result)))
;;; TEST
(employee-3-v2 3 1 '()) ; '(1 1 1)
Than we combine employee-2-v2 to employee-3-v2. Remember we have to change input parameter.
(define (employee-3-v3 n x result)
(if (= n 0)
result
(employee-3-v3 (- n 1) x (cons x result))))
;;; TEST
(employee-3-v3 3 'x '()) ; '(x x x)
Now we want remove not necessary input parameter result.
(define (employee-3-v4 n x)
(if (= n 0)
'()
(cons x (employee-3-v4 (- n 1) x))))
;;; TEST
(build-list 10 (λ (n) (employee-3-v4 n 'x)))
#|
output:
'(()
(x)
(x x)
(x x x)
(x x x x)
(x x x x x)
(x x x x x x)
(x x x x x x x)
(x x x x x x x x)
(x x x x x x x x x))
|#

dont understood lambda expression on scheme

i try to realize what this expiration, and don't get it.
( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))
i think,
a is a number, and b is #t or #f,
on the if statement we ask if b is true, if yes return first expression(sum 3 numbers), else the second(Subtract 3 numbers)
what i need to write on Racket to run this?
i try
(define question( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))))
and than
(question 5 #f)
and nothing not going well in this language.
This is not a complete answer as I don't want to do your homework for you.
First of all formatting and indenting your code is going to help you in any programming language. You almost certainly have access to an editor which will do this. Below I've done this.
So, OK, what does a form like (λ (...) ...) denote? Well, its a function which takes some arguments (the first ellipsis) and returns the value of the last form in its body (the second ellipsis), or the only form in its body in a purely functional language.
So, what does:
(λ (a b)
(λ (x y)
...))
Denote? It's a function of two arguments, and it returns something: what is the thing it returns? Well, it's a form which looks like (λ (...) ...): you know what those forms mean already.
And finally we can fill out the last ellipsis (after correcting an error: (-x ...) is not the same as (- x ...)):
(λ (a b)
(λ (x y)
(if b
(+ x y a)
(- x y a))))
So now, how would you call this, and how would you make it do something interesting (like actually adding or subtracting some things)?
(lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a))))
is a function that takes two arguments (that's what (lambda (a b) ...) says).
You can use the substitution method to discover what it produces.
Apply it to 5 and #f:
((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f)
[Replace a with 5 and b with #f in the body]:
(lambda (x y) (if #f (+ x y 5) (- x y 5)))
And this is a function that takes two numbers and produces a new number.
(Note that the #f and the 5 became fixed by the application of the outer lambda.)
It's easier to use the function if we name it (interactions from DrRacket):
> (define question (lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))))
> (question 5 #f)
#<procedure>
which is as expected, based on the reasoning above.
Let's name this function as well:
> (define answer (question 5 #f))
and use it:
> (answer 3 4)
-6
or we could use it unnamed:
> ((question 5 #f) 3 4)
-6
or you could do it all inline, but that's a horrible unreadable mess:
> (((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f) 3 4)
-6

Scheme: Not a procedure (Dr. Racket)

I'm running this program in Dr. Racket using R5RS scheme and am getting this error on the line (+ 1 IntDivide((- x y) y)):
"application: not a procedure; expected a procedure that can be
applied to arguments given: 5 arguments...:"
The procedure is supposed to return the quotient of the division between two integers using subtraction. Since this is a homework problem, I'm not going to ask whether my solution is correct (I can debug that later), but rather what is causing this error. It seems to be commonly caused by excess brackets, but I can't seem to find them. Any help would be appreciated.
(define IntDivide (lambda (x y)
(if (eqv? (integer? x) (integer? y))
(begin
(if (= y 0)
(begin
(write "Can't divide by zero") (newline)
-1
)
)
(if (= (- x y) 0)
1
)
(if (< x y)
0
)
(if (> x y)
(+ 1 IntDivide((- x y) y))
)
)
)
(write "Please only input integers")
))
Thanks in advance!
In addition to moving the operator inside the parens, you also need to replace the if with a cond:
(define IntDivide
(lambda (x y)
(if (eqv? (integer? x) (integer? y))
(cond ((= y 0) (write "Can't divide by zero")
(newline)
-1)
((= x y) 1)
((< x y) 0)
((> x y) (+ 1 (IntDivide (- x y) y))))
(write "Please only input integers"))))
The way you have it now, with the interior if expressions, won't work because they don't automatically return. They just evaluate and then the result gets thrown away.
Call IntDivide the same way you would any other function.
(+ 1 (IntDivide (- x y) y))

Nested while loop in Scheme with Gimp?

I'm writing a Gimp Script-Fu script, and trying to use a nested while loop. x is set to 15, y is set to 30. y loops up to 35, yet x stays at 15 and the loop quits. What is wrong here? Why is the value of x not changed?
(while (< x 20)
(while (< y 35)
(gimp-message (string-append (number->string x) "-" (number->string y)))
(set! y (+ y 1)))
(set! x (+ x 1)))
y is never being reset back to 0. Your code will increment y up to 35, then increment x 20 times, however on each subsequent increment of x y is still set to 35.
If you wanted to go over each combination of values of x and y then you would need code more like this:
(while (< x 20)
(set! y 0)
(while (< y 35)
(gimp-message (string-append (number->string x) "-" (number->string y)))
(set! y (+ y 1))
)
(set! x (+ x 1))
)
Here is a more complete example now that I've had time to work through this question with Gimp (I'm using print instead of gimp-message because I'm working in the console, but it should be interchangeable). To start I'm defining a function called SO that accepts the arguments, x, y that both represents pairs of min and max values:
(define (SO x y)
(let* ((x! (car x)) (y! (car y)))
(while (< x! (car (cdr x)))
(set! y! (car y))
(while (< y! (car (cdr y)))
(print (string-append (number->string x!) "-" (number->string y!)))
(set! y! (+ y! 1))
)
(set! x! (+ x! 1))
)
)
)
Inside this function, I'm pulling out the first and last values of x and y (with (car x) and (car (cdr x)) then I'm using let* to create two inner variables calledx!andy!that I will be altering the value of (to remove side effects of havingxandy` change after the function is called). If you call this function like so:
(SO '(15 20) '(30 35))
You get the following output:
"15-30"
"15-31"
"15-32"
"15-33"
"15-34"
"16-30"
"16-31"
"16-32"
"16-33"
"16-34"
"17-30"
"17-31"
"17-32"
"17-33"
"17-34"
"18-30"
"18-31"
"18-32"
"18-33"
"18-34"
"19-30"
"19-31"
"19-32"
"19-33"
"19-34"

Computing a list containing the numbers from x to y

How can I create a method which takes two numbers and prepare a list from first number to second number. The first number is always positive and less than second number? I tried the following but the I am not sure how to have a global variable in Scheme to hold previous values.
(define preplist
(let ((temp '()))
(lambda (x y)
(cond ((= x y) (append temp (list x)))
(else (append temp (list x))
(display x)
(preplist (+ x 1) y))))))
Expected result is: (preplist 3 7) => (3 4 5 6 7)
Can some one please help to resolve this problem?
The solution for (x, y) can be computed as: put x on the front of (x+1, y). It is thus clearly recursive. Like this:
(define (preplist x y)
(if (= x y)
(list y)
(cons x (preplist (+ x 1) y))))
See, it works:
> (preplist 1 4)
(1 2 3 4)
> (preplist 5 7)
(5 6 7)
There are several mistakes in your code, for starters you don't need a global variable defined in a let for storing the result, it's enough to build the answer as you advance in the recursion. And don't use append in this case, if the solution template is followed closely, a cons will suffice for building the output list.
You should stick to the recipe for building a new list recursively; this is how the problem should be solved using that recipe, it's perhaps a bit more idiomatic like this:
(define preplist
(lambda (x y)
(cond ((> x y) ; if the exit condition is met
empty) ; then return the empty list
(else ; otherwise
(cons x ; cons the current element
(preplist (add1 x) y)))))) ; and advance the recursion
An altogether different approach would be to write a tail-recursive solution. This is more efficient because a constant amount of stack is used. It doesn't follow the design recipe as outlined above, but is somewhat more similar to the solution you had in mind - but bear in mind that this doesn't use global variables (only a named let for the iteration) and the solution is accumulated and passed around as a parameter:
(define (preplist x y)
(let loop ((i y) ; named let for iteration
(acc empty)) ; define and initialize parameters
(if (> x i) ; if exit condition is met
acc ; return accumulated value
(loop (sub1 i) ; otherwise advance recursion
(cons i acc))))) ; and add to the accumulator
Of course, as pointed by #dyoo in the comments, in a practical setting you'd use the built-in range procedure which does basically the same as the preplist procedure.

Resources