Scheme-- how do procedures take other procedures as arguments? - scheme

Write a Scheme procedure named 'proc4' which takes 2 procedures as arguments (w,x) [note that w and x can be expected to work correctly when given two numbers as arguments]
and returns a procedure which takes 2 numbers (y,z) as arguments and returns the
procedure (w or x) which results in the greatest number when applied to y and z
(i.e. in C++ pseudocode if ((y w z) > (y x z)) {return w; } else {return x;} )
So I started
(define proc4(lamdda ( w x) (lambda y z)...
Then I wanted to do the if part. Something like
(if (> (apply w ( y z)) (apply x( w z))) but I keep getting errors.
I've been trying to find help on internet but everything I've seen so far does not make sense to me.

You can invoke function objects directly, without using apply:
(define (proc4 f g)
(lambda (x y)
(if (> (f x y) (g x y))
f
g)))

A bit of syntactic sugar for #ChrisJester-Young's answer - you can declare a procedure that returns another procedure like this:
(define ((proc4 f g) x y)
(if (> (f x y) (g x y))
f
g))
In the above code, the first procedure receives as parameters the procedures f and g, and in turn returns a procedure that receives as parameters x and y. We know that f and g are procedures because the way they're used inside the body of the definition, but they can have any name you want. Of course you can call the procedure in the usual way:
((proc4 + *) 10 20)
=> #<procedure:*>
The point of interest in this example is that procedures can also be passed as parameters (and returned as values), you don't need to apply them, just invoke the procedures received as parameters as you would with any other procedure. Also notice that all the answers to this question are equivalent, but the short-hand syntax that I'm using might not be available in all interpreters.

I cannot make much sense of this (obviously homework) question but I'd go for this:
(define proc4
(lambda (w x)
(lambda (y z)
(if (> (w y z) (x y z))
w
x))))

Related

Understanding church numerals

I'm working my way through SICP, and it gives the following definition for zero for Church Numerals:
(define zero (lambda (f) (lambda (x) x)))
I have a few questions about that:
Why the complicated syntax? It seems to be quite readable by just having the following instead:
(define (zero f)
(lambda (x) x))
where we can see it's a function called zero that takes one (unused) argument f and returns a function-of-one-parameter that will return its parameter. It almost seems like the definition is just intended to be as non-straightforward as possible.
What is the x there for? For example doing something like:
((zero square) 100)
returns 100. Is x just the default value returned?
There is no x in (lambda (x) x). None.
The x in (lambda (x) x) is bound. It could be named by any name whatever. We can not talk about x in (lambda (x) x) any more than we could talk about y in (lambda (y) y).
There is no y in (lambda (y) y) to speak of. It is just a placeholder, an arbitrary name whose sole purpose in the body is to be the same as in the binder. Same, without regard for which specific name is used there as long as it is used twice -- first time in the binder, and the other time in the body.
And in fact there is this whole 'nother notation for lambda terms, called De Bruijn notation, where the same whole thing is written (lambda 1). With 1 meaning, "I refer to the argument which the binder 1 step above me receives".
So x is unimportant. What's important is (lambda (x) x) which denotes a function which returns its argument as is. The so called "identity" function.
But even this is not important here. The Church encoding of a number is really a binary function, a function expecting two arguments -- the f and the z. The "successor step" unary function f and the "zero" "value" z, whatever that might be, as long as the two go together. Make sense together. Work together.
So how come we see two unary functions there when it is really one binary function in play?
That is the important bit. It is known as currying.
In lambda calculus all functions are unary. And to represent a binary function an unary function is used, such that when given its (first) argument it returns another unary function, which, when given its (now, second) argument, performs whatever thing our intended binary function ought to perform, using those two arguments, the first and the second.
This is all very very simple if we just write it in combinatory (equational) notation instead of the lambda notation:
zero f z = z
one f z = f z
two f z = f (f z) = f (one f z) = succ one f z
succ one f z = f (one f z)
where every juxtaposition denotes an application, and all applications associate on the left, so we imagine the above being a shortcut notation for
zero f = lambda z. z
zero = lambda f. (lambda z. z)
......
......
succ = lambda one. (lambda f. (lambda z. f (one f z) ))
;; such that
succ one f z = (((succ one) f) z)
= ((((lambda one. (lambda f. (lambda z. f (one f z) ))) one) f) z)
= ....
= (f ((one f) z))
= f (one f z)
but it's the same thing. The differences in notation are not important.
And of course there is no one in lambda one. (lambda f. (lambda z. f (one f z) )). It is bound. It could just be named, I dunno, number:
succ number f z = f (number f z) = f ((number f) z)
meaning, (succ number) is such a number, which, given the f and the z, does with them one more f step compared to what number would do.
And so, ((zero square) 100) means, use the number zero with the successor step square and the zero value of 100, and have zero perform its number of successor steps for us -- that is to say, 0 steps -- starting from the zero value. Thus returning it unchanged.
Another possible use is ((zero (lambda (x) 0)) 1), or in general
((lambda (n) ((n (lambda (x) 0)) 1)) zero)
;; or even more generally, abstracting away the 0 and the 1,
((((lambda (n) (lambda (t) (lambda (f) ((n (lambda (x) f)) t)))) zero) 1) 0)
which is just another way of writing
zero (lambda x. 0) 1 ;; or
foo n t f = n (lambda x. f) t ;; and calling
foo zero 1 0
Hopefully you can see what foo is, easily. And also how to read aloud this t and this f. (Probably the original f would be better named s, for "successor", or something like that).

set of x and x does not work in let in Scheme

I'm trying to run this line in Scheme:
(let ((x y) (y x)) (set! x x) (set! y y))
where at the start of the program x is defined to be 1 and y is defined to be 2.
I want the output to be x=2 and y=1 but I get x=1 and y=2
Appreciate your help!
My end goal is to switch their values only with commands, not with temporary variables
It looks like racket supports set!-values, so you can swap your variables without using any explicit temporary variables like so:
(define x 1)
(define y 2)
(set!-values (x y) (values y x))
;;; x is now 2 and y is 1
(It's even the example in the linked documentation)
In this expression:
(set! x x)
Both x reference the same variable, the one introduced by the let binding. Any change you do to x inside the let (and here, the actual value is unchanged) is not visible outside the let, because outside the let the x symbol is bound to another variable.
If you rename your temporary variables a and b for example:
(let ((a y) (b x)) (set! x a) (set! y b))
You will observe a different behaviour.

Scheme, higher order functions, and curried functions

I need to write a Scheme higher-order function that takes a function of two parameters as its parameter and returns a curried version of the function. I understand this much so far in terms of curried functions:
(define curriedFunction (lambda (x)
(if (positive? x)
(lambda (y z) (+ x y z))
(lambda (y z) (- x y z)))))
(display ((curriedFunction -5) 4 7))
(display "\n")
(display ((curriedFunction 5) 4 7))
If x is negative, it subtracts x y and z. If x is positive, it adds x, y, and z.
In terms of higher order functions I understand this:
(display (map (lambda (x y) (* x y)) '(1 2 3) '(3 4 5)))
And thirdly I understand this much in terms of passing functions in as arguments:
(define (function0 func x y)
(func x y))
(define myFunction (lambda (x y)
(* x y)))
(display (function0 myFunction 10 4))
In the code directly above, I understand that the function "myFunction" could have also been written as this:
(define (myFunction x y)
(* x y))
So now you know where I am at in terms of Scheme programming and syntax.
Now back to answering the question of writing a Scheme higher-order function that takes a function of two parameters as its parameter and returns a curried version of the function. How do I connect these concepts together? Thank you in advance, I truly appreciate it.
Here is a possible solution:
(define (curry f)
(lambda (x)
(lambda (y)
(f x y))))
The function curry takes the function f and returns a function with a single argument x. That function, given a value for its argument, returns another function that takes an argument y and returns the result of applying the original function f to x and y. So, for instance, (curry +) returns a curried version of +:
(((curry +) 3) 4) ; produces 7

Scheme High Order Functions [duplicate]

I was just beginning to feel I had a vague understanding of the use of lambda in racket and scheme when I came across the following 'alternate' definitions for cons and car in SICP
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
(define (cdr z)
(z (lambda (p q) q)))
For the life of me I just cannot parse them.
Can anybody explain how to parse or expand these in a way that makes sense for total neophytes?
This is an interesting way to represent data: as functions. Notice that this
definition of cons returns a lambda which closes over the parameters x
and y, capturing their values inside. Also notice that the returned lambda
receives a function m as a parameter:
;creates a closure that "remembers' 2 values
(define (cons x y) (lambda (m) (m x y)))
;recieves a cons holding 2 values, returning the 0th value
(define (car z) (z (lambda (p q) p)))
;recieves a cons holding 2 values, returning the 1st value
(define (cdr z) (z (lambda (p q) q)))
In the above code z is a closure, the same that was created by cons, and in
the body of the procedure we're passing it another lambda as parameter,
remember m? it's just that! the function that it was expecting.
Understanding the above, it's easy to see how car and cdr work; let's
dissect how car, cdr is evaluated by the interpreter one step at a time:
; lets say we started with a closure `cons`, passed in to `car`
(car (cons 1 2))
; the definition of `cons` is substituted in to `(cons 1 2)` resulting in:
(car (lambda (m) (m 1 2)))
; substitute `car` with its definition
((lambda (m) (m 1 2)) (lambda (p q) p))
; replace `m` with the passed parameter
((lambda (p q) p) 1 2)
; bind 1 to `p` and 2 to `q`, return p
1
To summarize: cons creates a closure that "remembers' two values, car
receives that closure and passes it along a function that acts as a selector for
the zeroth value, and cdr acts as a selector for the 1st value. The key
point to understand here is that lambda acts as a
closure.
How cool is this? we only need functions to store and retrieve arbitrary data!
Nested Compositions of car & cdr are defined up to 4 deep in most LISPs. example:
(define caddr (lambda (x) (car (cdr (cdr x)))))
In my view, the definitive trick is reading the definitions from the end to the beginning, because in all three of them the free variables are always those that can be found in the lambda within the body (m, p and q). Here is an attempt to translate the code to English, from the end (bottom-right) to the beginning (top-left):
(define (cons x y)
(lambda (m) (m x y))
Whatever m is, and we suspect it is a function because it appears right next to a (, it must be applied over both x and y: this is the definition of consing x and y.
(define (car z)
(z (lambda (p q) q)))
Whatever p and q are, when something called z is applied, and z is something that accepts functions as its input, then the first one of p and q is selected: this is the definition of car.
For an example of "something that accepts functions as its input", we just need to look back to the definition of cons. So, this means car accepts cons as its input.
(car (cons 1 2)) ; looks indeed familiar and reassuring
(car (cons 1 (cons 2 '()))) ; is equivalent
(car '(1 2)) ; is also equivalent
(car z)
; if the previous two are equivalent, then z := '(1 2)
The last line means: a list is "something that accepts a function as its input".
Don't let your head spin at that moment! The list will only accept functions that can work on list elements, anyway. And this is the case precisely because we have re-defined cons the way that we have.
I think the main point from this exercise is "computation is bringing operations and data together, and it doesn't matter in which order you bring them together".
This should be easy to understand with the combinatory notation (implicitly translated to Scheme as currying functions, f x y = z ==> (define f (λ (x) (λ (y) z)))):
cons x y m = m x y
car z = z _K ; _K p q = p
cdr z = z (_K _I) ; _I x = x _K _I p q = _I q = q
so we get
car (cons x y) = cons x y _K = _K x y = x
cdr (cons x y) = cons x y (_K _I) = _K _I x y = _I y = y
so the definitions do what we expect. Easy.
In English, the cons x y value is a function that says "if you'll give me a function of two arguments I'll call it with the two arguments I hold. Let it decide what to do with them, then!".
In other words, it expects a "continuation" function, and calls it with the two arguments used in its (the "pair") creation.

Getting the median of 3 values using scheme's

The problem this time is to get the median of three values (easy)
I did this:
(define (med x y z) (car(cdr(x y z)))
and it was accepted but when testing it:
(med 3 4 5)
I get this error:
Error: attempt to call a non-procedure
(2 3 4)
And when entering letters instead of number i get:
(md x y z)
Error: undefined varia
y
(package user)
Using something besides x y z I get:
(md d l m)
Error: undefined variable
d
(package user)
the question was deleted dont know how anyway
write a function that return the median of 3 values
Sorry for editing the question I got that I should put the values in order first not just a sill car and cdr thing so I did so
33> (define (med x y z)
(if(and(
(<x y) (<y z) y
if(and(
(<y x) (<x z) x z)))))
Warning: invalid expression
(if (and< (<x y) (<y z) y if (and ((<y x) (<x z) x z))))
but as u see Im getting a warning so what is wronge ?
You probably want to create a list, like this:
(define (med x y z) (car(cdr(list x y z)))
However, it seems like a waste to bundle up the values into a list just to undo them again. This would have the same effect:
(define (med x y z) y)
Note that as defined, (med . rest) is equivalent to (cadr rest) (except that med only takes three values). Personally, I would expect a function that's supposed to return the median of values to return, well, the median, regardless of list order. For example, (med 4 2 5) would return 4 and (3 0 9 6 5) would return 5.
As for the syntax error (which doesn't matter so much for writing med, since there is a better way using sort, length and list-ref), you don't have your parentheses in the right spots. Here's another way of writing what you have now, lining up terms with their siblings and to the right of their ancestors:
(if (and (
(<x y)
(<y z)
y
if
(and (
(<y x)
(<x z)
x
z
) ) ) ) )
The format for if is:
(if test-expr true-expr false-expr)
All of your terms are sub-terms of the conditional, and there's no true-expr or false-expr. You'd want to write your code as:
(if (and ...)
y
(if (...) ; we know that (not (and (< x y) (< y z))
x
z))
Note that you might be ably to simplfy the later tests, since you know the earlier tests are false.
You could also use a cond, which is clearer than a nested sequence of ifs:
(cond (test result)
(test result)
(test result)
... )
For your code, it would be:
(cond ((and ...) y)
((...) x)
(else z))
There's nothing too special about else (it's a syntactical construct rather than an expression, not that it matters much). You can use any value that evaluates to true (e.g. #t) instead.
Remember, parentheses surround both the function and arguments in Lisp ((foo 1 2 3), not foo(1, 2 ,3)), unlike mathematical notation where parentheses surround just the arguments.
while outis did a pretty good job of explaining the issue, there's one other important bit you need to know
(<x y)
calls the function named <x with the parameter y. you need to make sure you add a space inbetween the < and the x, like so:
(< x y)

Resources