Why in the next code, nothing is displayed when we work on Normal eval (lazy one).
;;; [Number, Number -> Number]
(define (printing-sub x y)
(display x)
(- x y))
;;; [Number, Number -> Number]
(define (f a b)
(if (< a 0)
a
(f b (printing-sub b a))))
(f 0 0)
I'll exmplain: In the first iteration, we will got (f 0 (printing-sub 0 0)), in the 2nd: (f (prining-sub 0 0) (prining sub (printing sub 0 0) 0). Now, in the 3rd, we have to calculate (printing-sub 0 0) because we want to know (if (<a 0). In this iteration 0 will print out.
What am I missing?
Thank you.
I too don't know what you mean by "normal eval", but I don't understand why you would expect anything but 0 to be printed out with that code. In fact it'll cause an infinite loop, printing out endless zeroes.
Note that (printing-sub 0 0) will always just display 0 and return 0, because (- 0 0) is 0. So in the first iteration you get (f 0 (printing-sub 0 0)) which reduces back to (f 0 0) which causes the infinite loop.
In other words, the if always evaluates to #f because a will never become anything other than 0.
Related
(define ZERO (lambda (f x) x))
(define ONE (lambda (f x) (f x)))
(define SUCC (lambda (n) (lambda (f x) (f (n f x)))))
(display (ZERO 1 0))
(display (ONE 1 0))
(display ((SUCC ZERO) 1 0))
The ZERO function works fine. When I run this code, I get an error,
ERROR: invalid application: (1 0)
for ONE, SUCC function.
How can I fix my code to make it work?
This is the Church encoding of numbers; the number K is represented by K applications of a function f to some argument x.
(The identities of the function and that argument are, surprisingly enough, irrelevant - you can build all of mathematics without caring.)
You can make it make a bit of sense with suitable choices of f and x - try, for instance, 0 and
(define (inc x) (+ x 1))
so the number K is represented by adding 1, K times, to 0.
> (ZERO inc 0)
0
> (ONE inc 0)
1
> ((SUCC ONE) inc 0)
2
You can also add some convenience with an evaluation function:
> (define (number n) (n inc 0))
> (number ZERO)
0
> (number ONE)
1
> (number (SUCC (SUCC (SUCC (SUCC ONE)))))
5
I accidentally forgot to put the else in the following cond expression, and something strange occurred.
(define (abs x)
(cond ((< x 0) x)
((= x 0) 0)
(+ 1 2 1001)
))
> (abs 1)
1001
>
the result of (abs 1) is not the result of (+ 1 2 1001),which is 1004, but the last element of the arguments of the expression (+ 1 2 1001).
the cond form is
(cond (<p1>,<e1>)
(<p2>,<e2>)
(<p3>,<e3>)
...
(<pn>,<en>))
there is no predicate in the expression (+ 1 2 1001), so I wonder if the procedure + has been considered as predicate, and if it always evaluates as true, selecting the last element to return. Is that how it works???
Sequencing: begin form in Racket allows you to sequence multiple expressions. It evaluates each expression from left to right and the final result is the last expression.
Syntax: The syntax for cond shows that multiple expressions can be sequenced in the rhs of a clause without a begin. Such a thing is called an implicit begin.
Semantics: According to the documentation, cond evaluates the rhs of a clause if the lhs is anything but #f. Therefore + in the position of the test-expression evaluates the rhs of the clause.
Style: By convention, using square brackets in a few key places makes Racket code even more readable. The clause of a cond is one of these places.
The following snippet is equivalent to your snippet:
#lang racket
(define (abs x)
(cond [(< x 0) x]
[(= x 0) 0]
[+ (begin 1
2
1001)]))
(abs 1)
; => 1001
cond works like this:
(cond (test-expr then-body)
(test-expr2 then-body2)
(else then-body3))
The test-exprs are tested one by one, and the first test-expr that returns a non-false value causes its corresponding then-body to be executed. The last value in the executed then-body is the value of the whole cond.
In Scheme, anything not #f is considered true. Therefore, + is considered true. In your cond, + acts like an else because it is always true. In fact, your code could be written like this without any change in behavior:
(define (abs x)
(cond ((< x 0) x)
((= x 0) 0)
(else 1 2 1001)))
In your original code, the first test-expr that returns a non-false value is +. Since 1001 is the last value of the executed then-body, 1001 is the value of the whole cond. That's why you got 1001.
cond is a way to do if-elseif*-else in lisp and getting a flatter structure than with nesting of if. Since cond is derived form you could write your conditional in terms of if. Your procedure would become:
(define (abs x)
(if (< x 0)
x
(if (= x 0)
0
(if +
(begin
1
2
1001)))))
The last if checks if + is truthy. Every expression not evaluating to #f is truthy so all procedures are truty. It will then evaluate every part 1, 2, then 1001 and since that is the tail expression that is the result of the evaluation. You can have as many consequences in each cond term, but all before the tail is just for effect.
You could add one extra pair of parentheses and it would work as you expected:
(define (abs x)
(cond ((< x 0) x)
((= x 0) 0)
((+ 1 2 1001))))
Here it has no addictional consequences and the truthy result of the predicate is the result for (abs 1). One would want the code to be as clear as possible so using else here is a much better option:
(define (abs x)
(cond ((< x 0) x)
((= x 0) 0)
(else (+ 1 2 1001))))
This helps with another problem as well. While a number is always thruthy if you do the predicate trick with something that may be #f the result is undefined in the spec. Thus:
(cond ((other-proc x)))
; ==> ??
If the call to other-proc is truthy the result is that, if it is #f you get the result chosen by the implementers. These are almost always truthy values with crazy visualizations like #<undefined> but can be anything like "BaNaNa" or even #f. Thus it is wise to have an else term so that you and not some other developer gets to choose the outcome :-)
How do I return a function using conditionals in scheme? What I want to do is to return the product of 2 numbers (when r = 0), or the sum (when r=1) or the difference (when r=2) or 0 (otherwise) depending on the value of r.
What I tried is below, but the return value is always 0. How do I fix that?
(define (f r)( lambda (x y)
(cond (equal? r 0)
((* x y))
( (equal? r 1)
( (+ x y)))
( (equal? r 2))
( (- x y))
(else
0 ))))
(( f 0) 2 3)
I would expect 6, but I get 0. Thanks in advance.
cond works like this:
(cond (test-expr then-body)
(test-expr2 then-body2)
(else then-body3))
The test-exprs are tested one by one, and the first test-expr that returns a non-false value causes its corresponding then-body to be executed. The last value in the executed then-body is the value of the whole cond.
To know why you got 0 (and not 6), look carefully at your first cond clause: (cond (equal? r 0) ...). equal? is the test-expr, and since equal? itself is not false, its then-body is executed (i.e. r and 0 are executed). Since 0 is the last value in the then-body, 0 is the value of the whole cond. That's why you got 0.
Note that nearly all lines in your cond have parentheses that have been incorrectly placed. Here's a fixed version:
(define (f r)
(lambda (x y)
(cond ((equal? r 0) ; <- Parentheses fixed.
(* x y)) ; <- Parentheses fixed.
((equal? r 1) ; <- Parentheses fixed.
(+ x y)) ; <- Parentheses fixed.
((equal? r 2) ; <- Parentheses fixed.
(- x y)) ; <- Parentheses fixed.
(else 0))))
Here's an arguably better way to define the same function:
(define (f r)
(cond ((= r 0) *)
((= r 1) +)
((= r 2) -)
(else (lambda _ 0))))
For example:
((f 0) 2 3)
;; '(f 0)' returns '*', so this reduces to: (* 2 3)
;; Answer:
6
This version is technically better as it is not restricted to taking only two arguments. For example, you can now do this: ((f 1) 1 2 3 4 5 6) (reduces to (+ 1 2 3 4 5 6)).
The cond expression in your code has some syntax errors:
There are brackets missing in each condition
You must not surround a procedure application with double brackets, this is a mistake: ((* x y))
Notice that you require to return an arithmetic procedure and, for example, we can simply return + which is similar to returning (lambda (x y) (+ x y)) (except that it'll work for more than two parameters, but that's a win!).
Bear in mind that in Racket the solution can be written in a more concise way: for example, by using case to simplify the conditions and const for the last case, when we want to return a procedure that returns 0 no matter what are the parameters. Here's how:
(define (f r)
(case r
((0) *)
((1) +)
((2) -)
(else (const 0))))
It works as expected, by returning a procedure that you can apply to the given arguments:
((f 0) 6 7)
=> 42
((f 3) 2 3)
=> 0
I'm working through Structure and Interpretation of Computer Programs and have a question concerning exercise 1.10, which, using Ackermann's function defined as
(define (A x y)
(cond ((= y 0) 0)
((= x 0) (* 2 y))
((= y 1) 2)
(else (A (- x 1)
(A x (- y 1))))))
determine the value of the expression (A 1 10).
Now, I know the answer should be (A 1 10) = 2^10 = 1024, but when working through the computation, I get the following:
(A 1 10)
(A (- 1 1) (A 1 (- 10 1)))
(A 0 (A 1 9))
(A 0 (A 0 (A 1 8)))
...
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0(A 0 (A 0 (A 0(A 0 (A 0 (A 0 ( A 0 0)))))))))))))
Now, the way I understood it, Scheme will start by evaluating the deepest expressions first, i.e. the (A 0 0) on the far right. This has the value 0, as the first condition of the function is met with (= y 0). The same happens for the next step and we end up reducing all brackets until we end up with the last (A 0 0) which will also have the value 0 for analogous reasons. Now, I get that the last line should be something like
(*2 (*2 (*2 (*2 (*2 (*2 (*2 (*2 (*2 (*2 (*2 (A 0 0)))))))))))))
So, if all of this is correct, why does the last (A 0 0) yield 2 instead of 0? Or, more generally, can you spot where the error in my reasoning is? I'm pretty sure it either has something do to with the evaluation procedure of recursive calls OR with how conditional statements are evaluated.
Solved: As noted by leppie the (= y 1) gets evaluated first, getting 2 as value for (A 0 1) before getting to (A 0 0)
You never get all the way to
(A 0 0)
The expansion proceeds
(A 0 (A 1 9))
(A 0 (A 0 (A 1 8)))
(A 0 (A 0 (A 0 (A 1 7))))
...
(A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 0 (A 1 1))))))))))
and now the (A 1 1) is evaluated to 2.
How would you use set! in a simple procedure f such that evaluating (+ (f 0) (f 1)) will return 0 if the arguments to + are evaluated from left to right but will return 1 if the arguments are evaluated from right to left?
Easiest approach is probably to store some external state and have the implementation of f affect it's contents.
(define x 0)
(define (f n) (let ((tmp x)) (set! x n) tmp))
Thus, x is initially 0 and each call to f will return the current value of x and save the argument as the new value of x. Thus (f 0) followed by (f 1) will both return 0, leaving the final x value of 1. While evaluating (f 1) followed by (f 0) will yield 0 then 1, with a final x of 0.
With call/cc.
(define (f)
(call/cc
(lambda (c) (+ (c 0) (c 1)))))
(write (f))
Invoking c within either argument to + causes f to return immediately, yielding 0 or 1 depending which argument is evaluated first.
But I suspect it will always evaluate left-to-right and thus return 0.