Using "do" in Scheme - scheme

What is the difference between CODE SNIPPET 1 and CODE SNIPPET 2?
;CODE SNIPPET 1
(define i 0)
(do ()
((= i 5)) ; Two sets of parentheses
(display i)
(set! i (+ i 1)))
;CODE SNIPPET 2
(define i 0)
(do ()
(= i 5) ; One set of parentheses
(display i)
(set! i (+ i 1)))
The first code snippet produces 01234 and the second produces 5. What is going on? What does the extra set of parentheses do? Also, I have seen [(= i 50)] used instead of ((= i 5)). Is there a distinction? Thanks!

The general structure of a do form is like this:
(do ((<variable1> <init1> <step1>)
...)
(<test> <expression> ...)
<command> ...)
Paraphrasing http://www.r6rs.org/final/html/r6rs-lib/r6rs-lib-Z-H-6.html#node_chap_5, each iteration begins by evaluating <test>, if it evaluates to a true value, <expression>s are evaluated from left to right and the last value is returned as the result of the do form. In your second example = would be evaluated as a boolean meaning true, then i would be evaluated and at last 5 is the return value of the form. In the first case (= i 5) is the test and the do form returns an undefined value. The usual way to write a loop would be more like this:
(do ((i 0 (+ i 1)))
((= i 5) i) ; maybe return the last value of the iteration
(display i))
You don't need an explicit mutation of the loop variable as this is handled by the <step> expression.

In the first case, ((= i 5)) functions as a test for termination. So the do loop is repeated until i = 5.
In the second case, (= i 5) isn't a test. The do loop simply executes the first form, which returns 5.
--
(Per the attached comments) brackets are interchangeable in some dialects of scheme. It is sometimes considered idiomatic to use [] for parameters (i.e. to the parent do).

Related

How to skip on an if statement in scheme

I have the following function to do a recursive countdown in scheme:
(define (countdown n)
(display n)
(if (> n 0)
(countdown (- n 1))
0 ; how to make this "do nothing" and *not* print zero?
)
)
And a run of it:
(countdown 7)
(countdown 6)
765432100
65432100
You'll notice that after the countdown has finished, it prints the zero (or maybe it 'evaluates' to zero). How can I get rid of that so it only prints "7654321" and then exits ?
Additionally, if I try and put both statements inside the if:
(define (countdown n)
(if (> n 0) (
(display n)
(countdown (- n 1)))
0
)
)
(countdown 7)
I get the following error:
7654321TypeError: Cannot read property 'toString' of undefined
Current Eval Stack:
-------------------------
0: (countdown (- n 1))
1: (countdown (- n 1))
2: (countdown (- n 1))
3: (countdown (- n 1))
4: (countdown (- n 1))
5: (countdown (- n 1))
6: (countdown 7)
What does that mean exactly?
The First Program
The countdown procedure always prints its argument, since (display n) occurs first in the procedure. When n is zero, it is printed in that call, then the if expression checks whether n is zero. That explains why 0 is printed the first time.
0 is printed for a second time, not by the program, but by the REPL. You are running the program in the REPL (Read Evaluate Print Loop) when you invoke it by calling (countdown 7) in the REPL. The REPL evaluates the expressions, and prints the results in the REPL. The last expression of the countdown procedure is returned from the procedure, to the REPL, which kindly prints it out for you. Because it is a REPL, doing what REPLs do. If you ran this program as a script from the command line you would not see this last zero.
Now, a stylistic note: do not leave hanging parentheses in lisps. It is unidiomatic to do so, and it gets harder to read lisp code with such errant parentheses when code gets larger. There are some rare cases when it is appropriate, but generally you should collect closing parenths together.
A first attempt to fix up the posted code might look like:
(define (countdown n)
(if (> n 0)
(begin (display n)
(countdown (- n 1)))
0))
Here the begin form is needed because if only evaluates one expression for each of its arms, and two expressions need to be evaluated to print n and recursively call countdown. This program will print 0 once in the REPL (because it is still returning 0), and not at all in a command-line script.
The countdown procedure is still returning a number, which the REPL is still printing. Procedures always return values in Scheme, so something will have to be returned from countdown, no matter what. One could punt and just omit the second arm of the if form:
(define (countdown n)
(if (> n 0)
(begin (display n)
(countdown (- n 1)))))
This is perfectly legal Scheme, but the if form returns an unspecified value when its first test evaluates to #f and the second arm has been omitted. When I ran this in Chez Scheme, the unprintable value #<void> was returned, so the behavior is exactly what OP is expecting.
But there may be a better way to write this; many Schemes (Chez Scheme, for one) have a when form that only tests one expression, i.e., when is one-armed. when also returns unspecified values when its single test evaluates to #f. But, when has an added advantage, in that it can evaluate multiple expressions when the test evaluates to true; this means that the begin form is not needed when using when:
(define (countdown n)
(when (> n 0)
(display n)
(countdown (- n 1))))
This works as desired in the REPL:
> (countdown 7)
7654321>
The Second Program
(define (countdown n)
(if (> n 0)
((display n)
(countdown (- n 1)))
0))
As already mentioned, if evaluates one expression per arm. We have already seen that expressions can be grouped together by using a begin form. Here an attempt is made to combine two expressions by grouping them with parentheses, but this won't work. In short, parentheses carry semantic meaning in lisps, and one cannot arbitrarily add them wherever one likes.
In Scheme a form that looks like (something something-else-1 ...) is interpreted as a procedure call, unless something is bound as a syntactic keyword (i.e., unless something is a macro identifier). Procedure calls always evaluate their operator expressions and all of their argument expressions in an unspecified order. Since the order of evaluation depends on the implementation, the detailed behavior will vary, but consider:
((display n) (countdown (- n 1)))
When (display n) is evaluated (at which point n is evaluated and display is evaluated, in unspecified order, and the results are used to make a procedure call), the result of the call is to return an unspecified value, and to cause a side effect, i.e., the printing of the value of n. display is a procedure that always returns an unspecified value.
When the expression (countdown (- n 1)) is evaluated, control will pass to the next recursive call, with n diminished by 1 each time, until n is 0. At this point, 0 is returned to the previous call, ((display 1) (countdown 0)), so that we now have ((display 1) 0).
(display n) may not have been evaluated yet in any of the forms; this is the case in Chez Scheme. So in that case, ((display 1) 0) --> (#<some-unspecified-value> 0) with the side-effect now of printing 1. It should be clear that attempting to use the procedure #<some-unspecified-value> is not the path to joy.
TypeError: Cannot read property 'toString' of undefined
Alternatively, the Scheme implementation might evaluate the operator expression before the argument expressions, in which case the count-down numbers will all have been printed before encountering the error. OP shows 7654321 preceding the error message, which seems to indicate that this is the behavior in OP's Scheme.

Will a procedure be considered as a predicate, <p> , when the special form cond is missing the key word else?

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 use and/or instead of if/cond?

I'm new to Scheme programming and I've gotten this task that I just can't find out how to work correctly. I'm supposed to define a procedure with one parameter (a number). If the number is positive I want 1 to be returned, -1 if the number is negative and 0 if it is 0, using only and/or. If and cond is not allowed. I only get #t or #f returned, but you see that's not what I want. Any help or pointers is appreciated
You can solve your problem if you look at the following equivalence, valid when every expj has a value different from #f:
(cond (test1 exp1) (or (and test1 exp1)
(test2 exp2) (and test2 exp2)
... ≡ ...
(testn expn) (and testn expn)
(else expn+1)) expn+1)
Since the function that gets the sign of a number can simply be written in this way:
(define (sign x)
(cond ((> x 0) +1)
((< x 0) -1)
(else 0)))
after applying the above equivalence, since every result is an integer, different from #f, this function becomes equal to the solution proposed also in another answer:
(define (sign x)
(or (and (> x 0) +1)
(and (< x 0) -1)
0))
So, which is the reason of the above equivalence? It depends on the fact that and evaluates its arguments in turn; as soon as one of them is #f, it stops by returning #f, otherwise returns its last argument (and this explains the single branches (and testj expj)); while or evaluates its arguments in turn; as soon as one of them is not #f, it stops by returning it, otherwise returns its last argument (and this explains the chain (or (and ...) (and ...) ... expn+1)).
(define test
(lambda (n)
(or (and (< n 0) -1)
(and (= n 0) 0)
1)))
Part of the trick is understanding that and, if everything evaluates to true, will return the last item it evaluated, while or will return the first thing that successfully evaluates to true. The other part is realizing that everything except for #f is considered "true."
The transformation of and is seen in the report but to not include the actual macros it's basically this:
; only one argument
(and a) ; ===>
a
; one of more
(and a b ...) ; ==>
(if a
(and b ...)
#f)
All arguments must be evaluate to a positive value and the last value is the result, else #f. It short circuits so when something is #f the rest of the expressions are never evaluated.
For or is like this:
(or a) ; ==>
a
(or a b ...) ; ==>
(let ((a-value a))
(if a-value
a-value
(or b ...)))
The first argument that does not evaluate to #f gets returned. If all values are #f the last #f will be the result.
Thus if you want:
(if a b c) ; ==>
(let ((tmpa a))
(or (and atmpa b)
(and (not atmpa) c)) ; not part only important if b can be #f
I use let to prevent evaluating the same expression several times. eg. if you had one that printed something like (begin (display "hello") #f) or it's an expensive calculation then it's necessary or else you can just substitute the variable with the expression. eg. the last would become:
(or (and a b)
(and (not a) c))
That transformed back with no temporary variables become:
(if (if a b #f)
(if a b #f)
(if (not a) c #f))
If b is #f value, then the result is #f because of the last if. Thus everytime a is true b is the result. Everytime it's false, c is the answer. Thus
(if a b c)
So imagine you want to return the first true value in a list.
(define (first-true lst)
(and (not (null? lst))
(car lst)
(first-true (cdr lst))))

Racket - Map a function which takes an argument

I wanna map a function which takes an argument:
(map best-play (cdr tree) true) ;true is the argument I wanna pass
Is it possible?
Yes. You can use a function called curry (or its sibling, curryr), which permits partial application, allowing you to pass in arguments without calling the function to yield a new function.
To understand that, consider this example.
> (define add2 (curry + 2))
> (add2 1)
3
> (add2 2)
4
Effectively, calling curry on + and passing a single argument creates a new function which is equivalent to this:
(lambda (x) (+ 2 x))
The function curryr is similar, but it passes arguments starting from the right, rather than the left. This is useful in functions where order matters.
> (define sub2 (curryr - 2))
> (sub2 4)
2
You can use these functions to perform the mapping you want. If the true argument comes second, then you'd want to use curryr, like this:
(map (curryr best-play true) (cdr tree))

have a function in Scheme return value (or do something else) and call itself

I would like to have two expressions evaluated in function body. How would I go about it?
Given the following:
(define (f)
((+ 2 2) (+ 4 4)))
I would like both to have 2+2 and 4 + 4 evaluated (obviously the above doesn't work).
Basically, if I understand it correctly, in a spot where I can get a single thing done, I would like to have two things done. For example instead of calling just one function as a consequent in the if expression, I'd like to call two functions. Or ideally return a value and have the function call itself.
I am not sure if this makes sense but conceptually having such a mechanism seems plausible.
The body of a procedure evaluates from top-to-bottom, no matter how many expressions are at the beginning, only the value of the last one is returned. For instance, if we write this:
(define (f)
(+ 2 2) ; evaluates to 4, but we don't do anything with it, so it's lost
(+ 4 4)) ; evaluates to 8, this is the returned value
... When we call (f) the returned value is 8, the first expression's value is lost. Perhaps you meant to say, that you want multiple values returned? this is possible depending on the interpreter, for instance in Racket:
(define (f)
(values (+ 2 2) (+ 4 4)))
(f)
=> 4
8
Now (f) returns two values, if we are going to use them, we need special forms to "capture" the multiple returned values. In this example, I'll use let-values:
(let-values (((x y) (f))) ; 4 is bound to x, 8 is bound to y
(+ x y))
=> 12
Another interpretation of your question, regarding the use of an if expression: if you need to write more than one expression inside an if, then you have to pack all the expressions inside a begin form (by the way: the body of a procedure is implicitly inside a begin).
But again, even tough all the expressions are executed in sequence, only the value of the last one is returned as a result - so all the expressions in the middle should be executed only for the effect, not for the value. For example:
(if (= 1 1) ; condition is true
(begin ; execute a sequence of expressions
(+ 2 2) ; evaluates to 4, but the value is lost
(+ 4 4)) ; evaluates to 8, this is the returned value
(begin
(+ 1 1)
(+ 3 3)))
=> 8
Of course, in the above example it'd be simpler to just use a cond, which has an implicit begin. This is equivalent to the previous snippet:
(cond
((= 1 1) ; condition is true, implicit `begin`
(+ 2 2) ; evaluates to 4, but the value is lost
(+ 4 4)) ; evaluates to 8, this is the returned value
(else
(+ 1 1)
(+ 3 3)))
=> 8
I am not sure I understand what you mean, you simply call the functions one after another:
(define (f)
(display "calling-function-1")
(newline)
(display "calling-function-2"))
Output:
Welcome to DrRacket, version 5.3.5 [3m].
Language: SICP (PLaneT 1.17); memory limit: 128 MB.
> (f)
calling-function-1
calling-function-2
If you did this with addition:
(define (f)
(+ 2 2) (+ 4 4))
It would still work correctly, and just return the last value:
Welcome to DrRacket, version 5.3.5 [3m].
Language: SICP (PLaneT 1.17); memory limit: 128 MB.
> (f)
8
If you want to evaluate a sequence of expressions in a place where only a single one is allowed (i.e. an if consequence), you need to use begin. This isn't the case for the body of a define.

Resources