What causes an unbound variable error in Scheme? - scheme

I've started out with SICP and I'm new to Scheme. I've tried debugging this piece of code and even compared it to similar solutions.
(def (myFunc x y z)
(cond ((and (<= x y) (<= x z)) (+ (* y y) (* z z)))
((and (<= y x) (<= y z)) (+ (* x x) (* z z)))
(else (+ (* x x) (* y y)))))
This function returns the sum of the squares of two largest numbers.
When I run this, the interpreter gives out ";Unbound variable: y". Could you please explain the cause behind this error?
Help is greatly appreciated :)

The function-defining primitive in Scheme is called define, not def.
As it is, the whole (def ...) expression was treated as a function call to def. So its arguments' values needed to be found. The first argument (myFunc x y z) is a function call so its argument values needed to be found. Apparently your implementation wanted to find out the value of y first.
The R5RS standard says "The operator and operand expressions are evaluated (in an unspecified order) and the resulting procedure is passed the resulting arguments."
It is likely your implementation chooses the rightmost argument first, which leads to (<= x y) being evaluated first (because of special rules of evaluating the cond and and special forms), with y in its rightmost position.

Related

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

Adding the results of two functions in Scheme

I try to make a function in Scheme that adds the squares of two numbers.
(define (sum-of-two-squares X Y)
(+ square(X) square(Y)))
(sum-of-two-squares 3 5)
As error it tells me that "5 is not a function". How do you add the results of this two functions without giving you error?
just write (square X) instead of square(X).
In Scheme, (X) means "call X as a function, without any arguments".
And (square X) means "call square as a function, with X as its argument".
I think what you want is:
(define (sum-of-two-squares X Y)
(+ (square X) (square Y)))

what is difference between (define (add x y) (+ x y)) and (define add (lambda (x y) (+ x y)))?

I am now writing a scheme's interpreter by using c++. I got a question about define and lambda.
(define (add x y) (+ x y))
is expanded as
(define add (lambda (x y) (+ x y)))
by lispy.py
what's the difference between this two expression?
why need expand the expression? Just because it is easy to evaluate the expression?
They are the same, since one gets expanded into the other. The first expression is easier to both write & read; having it expand into the second simplifies the interpreter (something you should appreciate).
They are equivalent in R5RS:
5.2 Definitions
(define (<variable> <formals>) <body>)
<Formals> should be either a sequence of zero or more variables, or a
sequence of one or more variables followed by a space-delimited period
and another variable (as in a lambda expression). This form is
equivalent to
(define <variable>
(lambda (<formals>) <body>)).

Why does `(= (car x) 'z)` work?

I was stumbling through the Arc tutorial when I got sort of confused with this:
Quoted from the Arc Tutorial:
Like Common Lisp assignment, Arc's = is not just for variables, but
can reach inside structures. So you can use it to modify lists:
arc> x
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)
But lisp is executed recursively, right? It says that car returns the first value in a list. So:
arc> (car x)
a
which makes sense, but then why isn't (= (car x) 'z) equal to (= a 'z), which would result in:
arc> a
z
arc> x
(a b) ; Note how this hasn't changed
but it doesn't. Instead, it appears that (= (car x) 'z) seems to have the effects of (= x (list 'z (car (cdr x)))):
arc> (= x '(a b))
(a b)
arc> (= (car x) 'z)
z
arc> x
(z b)
...
arc> (= x '(a b))
(a b)
arc> (= x (list 'z (car (cdr x))))
(z b)
arc> x
(z b)
So why exactly does (= (car x) 'z) work that way and what is it that I'm missing here?
Note: this is my first introduction to LISP.
= is a special operator, it's not a function. So its arguments are not evaluated according to the normal recursive process. The first argument is treated specially, it identifies a place to assign to, not the value already in that place. It may have to evaluate subexpressions within it to find the place, but once it gets to the place, it stops evaluating. The second argument will be evaluated normally, to get the value to assign there.
= appears to be an assignment operator in Arc, the equivalent in Common Lisp would be setf. In this case, (car x) returns the place that is to be modified:
? (defparameter x '(a b))
X
? x
(A B)
? (setf (car x) 'z)
Z
? x
(Z B)
See also here.
= is a macro or rather "special operator", which is just a fancy name for built-in macro. Macros' arguments (unlike functions' arguments) aren't evaluated at all, so the = operator gets (car x) unevaluated ==> it get's the list (car x) itself! Now, that = operator contains miniature code walker that traverses the list (car x) and figures out what place would be read from if the list was evaluated. And assigns to that place.
What does it assign? The result of evaluating the second argument, it evaluates that one manually.
So the effective evaluation scheme for = is in fact
(= <unevaluated-argument> <evaluated-argument>)
EDIT:
Another example of macro or special operator is if. in (if <cond> <a> <b>), if starts being evaluated first and gets arguments <cond>, <a> and <b> raw - unevaluated. Then it manually evaluates <cond> and depending on the result, it either evaluates <a> or <b> and returns result of that. If everything was really evaluated recursively, you could never have working if or cond or loop or short-circuit and and or and so on...
NOTE: = is probably (= I suppose) a macro and not special operator, at least its equivalent setf in common lisp is a macro. I doubt that P. Graham embedded = directly into the compiler. But it's not really important to know.
If you have the book "ANSI Common Lisp", there is such sentence in chapter 3.3 Why Lisp Has No Pointers:
One of Secrets to understanding Lisp is to realize that variables have values in the same way that lists have elements. As conses have pointers to their elements, variables have pointers to their values.
If x is assigned a list:
arc> (= x '(a b))
(a b)
It formulates as such, the variable x points to a list. The 1st position of the list points to the symbol a and the 2nd points to the symbol b:
When car of x is assigned with 'z in (= (car x) 'z), simply the 1st position points the new symbol z.
Finally, in the expression (= a 'z), a variable a is assigned and thus points to the symbol z

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