How to skip on an if statement in scheme - 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.

Related

Why is the empty list produced here in this iteration?

Let's take the following function to get a pair of numbers:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
Why does the above produce '() as the first element of the output? Comparing this with python, I would expect it to just give the three pairs, something like:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
I suppose maybe it has to do with when i is 1?
(map (lambda (j) (list 1 j)) '())
; ()
Is that just an identity in Scheme that a map with an empty list is always an empty list?
When i is 1, the inner map is over (range 1 0), which is () by your own definition. Since map takes a procedure and a list (or lists) of values, applies the procedure to each value in the list in turn, and returns a list containing the results, mapping any procedure over a list containing no values will return a list containing no values.
It might help to create a simple definition for map to see how this might work. Note that this definition is not fully featured; it only takes a single list argument:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
Here, when the input list is empty, there are no values to map over, so an empty list is returned. Otherwise the procedure proc is applied to the first value in the input list, and the result is consed onto the result of mapping over the rest of the list.
A couple of observations:
First, the empty list is not represented by nil in either standard Scheme or vanilla Racket, and you should not be using it. In the early days of Scheme nil was allowed as a crutch for programmers coming from other lisps, but this has not been the case for a long time. I don't think that it was ever in any of the RnRS standards, but nil may have survived in some specific implementations until maybe R4RS (1991). SICP was from that era. Today you should use '() to represent empty list literals in Scheme so that your code can run on any Scheme implementation. Racket's #lang sicp allows code directly from the book to be run, but that should not keep you from using the common notation. Note that Common Lisp does use nil as a self-evaluating symbol to represent both the empty list, and boolean false. Seeing this in Scheme just doesn't look right today.
Second, you will probably be led astray more often than to wisdom by thinking in terms of Python when trying to understand Scheme code. In this particular case, map is an iteration construct, but it is not the same thing as a for loop. A for loop is usually used for side-effects, but map is used to transform a list. Scheme has a for-each form which is meant to be used for its side-effects, and in that sense is more like a for loop. The Python version that is posted above is not at all like the Scheme version, though. Instead of returning the results in a list, the results are printed. In the Scheme code, when i is 1, the inner mapping is over (range 1 0) --> (). But, in the Python code, when i is 1, the inner loop is over range(1, 1), so the body of this for loop is not executed and nothing is printed.
Better to think carefully about the Scheme code you want to understand, falling back on basic definitions, than to cobble together a model based on Python that has possibly unconsidered corner cases.

Lisp : how to use recursion to defun a function that given a nonnegative integer N, produce the list of all integers from 1 up to and including N?

write a function in lisp called number(N) that you have to use a nonnegative integer N, and produce the list of all integers from 1 up to and including N.
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
I checked some questions, but most of them use loop and range, but this question doesn't allowed me to do this, so I have to use recursion instead:
here is my code, but this code keeps giving me warning:
; caught STYLE-WARNING:
; The variable N is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 1 STYLE-WARNING condition
I think my algorithm is correct ,but because I am new to lisp, I still don't know how to write the function properly. It is grateful if anyone could gave me any help.
IF has generally a common syntax, but there are exceptions
Generally in Lisps like Common Lisp the if operator allows the following syntax:
IF test-form then-form [else-form]
This means that in Lisp usually zero or one else-form are allowed. An example is if in Common Lisp.
In Emacs Lisp multiple else-forms are allowed. Emacs Lisp has the following syntax:
IF test-form then-form else-form*
This means that in Emacs Lisp zero or more else-forms are allowed.
Thus: it's important to mention which language&dialect you are actually using.
Your code
a) Let's assume that you use Common Lisp with its IF syntax.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Your code has the problem, that there are more than one else clauses. You need to write a version which has a single else clause.
b) Let's assume that you use Emacs Lisp with its IF syntax with multiple else forms.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Here the (cons N nil) form is allowed, but has no effect. Its return value is not used and it has no side effect. You could delete it and it would make no difference. Again: you would need how to combine its effect with the form (numbers (- N 1)).
Syntax error: missing closing parenthesis
There is another problem in your code. The s-expressions are not complete -> a closing parenthesis is missing:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
As you can see a closing parenthesis is missing at the end.
Thus your code can not be read by Lisp.
There are two ways one generally can avoid this problem:
count the parentheses and set them accordingly
use the editor to count the parentheses
Most people prefer the latter.
The way to think about this is to think about what the algorithm should be:
To compute the numbers from 1 to n:
if n is less than 1 then there are no numbers, so this is the empty list;
otherwise we want a list which looks like (... n), where ... is all the numbers from 1 to n-1.
Note that we want the numbers in forward order: this is going to be critical.
Doing this is slightly difficult in Lisp because we want the number to be at the end of the list, and access to the ends of lists is hard.
Here is the start of a version which builds the list backwards (so this is not the right answer).
(defun numbers (n)
(if (< n 1)
'() ;the empty list
;; n 1 or more, so build a list which is (n . ...)
(cons n <some function involving n>)))
Well, OK, what function should we call recursively? Do we have a function which returns the list we want? Well, yes: it's numbers, with an argument which is one less than n!
(defun numbers (n)
(if (< n 1)
'()
(cons n (numbers (- n 1)))))
And this function works. But it gets the wrong answer: the list is backwards:
> (numbers 10)
(10 9 8 7 6 5 4 3 2 1)
There are two fixes to this problem: the first is to build the list forwards, using append. This version looks like this (remember append wants to append two lists: it doesn't append an element to the end of a list):
(defun numbers (n)
(if (< n 1)
'()
(append (numbers (- n 1)) (list n))))
This gets the right answer:
> (numbers 10)
(1 2 3 4 5 6 7 8 9 10)
but it's a terrible answer: append has to walk all the way down the list (lists in Lisp are chains of conses: there is no fast access to the end of a list), copying it as it goes, to append the new element. So this has absolutely terrible space & time complexity. Programs written like this are why 'Lisp is slow'.
A better approach is to build the list backwards and then reverse it.
(defun numbers (n)
(reverse (numbers-backwards n)))
(defun numbers-backwards (n)
(if (< n 1)
'()
(cons n (numbers-backwards (- n 1)))))
The problem with this, from the homework perspective, might be that using reverse is not allowed. That's OK, we can write it, recursively. The implementation is slightly fiddly, but this is going to help us below.
(defun reverse-list (l)
;; in real life reverse-list-accumulator would be a local function
(reverse-list-accumulator l '()))
(defun reverse-list-accumulator (l accum)
(if (null l)
accum
(reverse-list-accumulator (rest l) (cons (first l) accum))))
The way this works is that reverse-list calls this auxiliary function with an extra argument. The auxiliary function then checks the list, and if it's not empty it calls itself with the tail of the list and the head of the list consed onto the auxiliary argument. If it is empty, it returns the auxiliary argument. It's a little subtle but you can see that this in fact reverses the list.
So now we can write our function using only recursive functions we wrote:
(defun numbers (n)
(reverse-list (numbers-backwards n)))
But now there should be a moment of inspiration: why are we doing this whole
build-it-backwards-and-reverse-it thing? Why don't we just make numbers do the accumulator trick itself! Well, we can do that:
(defun numbers (n)
(numbers-accumulator n '()))
(defun numbers-accumulator (n accum)
(if (< n 1)
accum
(numbers-accumulator (- n 1) (cons n accum))))
And now we don't need to reverse the list, and for added value our
function is 'tail recursive' and will generally be compiled much more
efficiently.
A real-life version of numbers might look more like this, using a local function:
(defun numbers (n)
(labels ((numbers-accumulator (m accum)
(if (< m 1)
accum
(numbers-accumulator (- m 1) (cons m accum)))))
(numbers-accumulator n '())))
Here is a comparison between the version of numbers using append and the above function, on an argument small enough that the append version does not overflow the stack.
> (time (progn (numbers/append 2000) (values)))
Timing the evaluation of (progn (numbers/append 2000) (values))
User time = 0.024
System time = 0.001
Elapsed time = 0.017
Allocation = 32176304 bytes
97 Page faults
> (time (progn (numbers 2000) (values)))
Timing the evaluation of (progn (numbers 2000) (values))
User time = 0.000
System time = 0.000
Elapsed time = 0.001
Allocation = 32000 bytes
0 Page faults
You can see how terrible the append version is, and how good the other one is: this is a 64-bit Lisp, and conses are two words or 16 bytes: it has allocated precisely 2000 cons cells which is the minimum it could do.

Name of this state representation idea without local variables

I know this is maybe an oddball idea, but I thought might as well give it a try to ask here.
I was experimenting in Racket about state representation without local variables.
The idea was defining a function that prints it's parameter value and if called again gives me another value. Since pure functions called with the same parameter always produce the same result, my workaround-idea got me the following.
(define (counter n)
(displayln n)
(λ () (counter (add1 n)))) ; unapplied lambda so it doesn't go in a loop
Then I devised a function to call counter and its resulting lambdas a certain number of times.
(define (call proc n)
(unless (zero? n)
(let ([x (proc)])
(call x (sub1 n)))))
Which results in this:
> (call (counter 0) 5)
0
1
2
3
4
5
What is the name for the concept applied here? Propably it's something trivial what you need in real applications all the time, but since I have no experience in that respect yet so I can't pinpoint a name for it. Or maybe I just complicated something very simple, but nonetheless I would appreciate an answer so I can look further into it.
Sorry if my question is not clear enough, but english is not my first language and to ask about things I have no name for makes me feel kinda uncertain.
You're using closures to save state: a lambda form stores the environment in which it was defined, and you keep redefining the procedure (called x in your code), so each time it "remembers" a new value for n.
Another way to do the same would be to let the procedure itself keep track of the value - in other words, counter should remember the current n value between invocations. This is what I mean:
(define (counter initial)
(let ((n (sub1 initial)))
(lambda ()
(set! n (add1 n))
n)))
In the above code, the first invocation of counter returns a new lambda that closes over n, and each invocation of that lambda modifies n and returns its new value. Equivalently, we could use Racket-specific syntax for currying and the begin0 special form to achieve the same effect:
(define ((counter n))
(begin0
n
(set! n (add1 n))))
Either way, notice how the procedure "remembers" its previous value:
(define proc (counter 0))
(proc)
=> 0
(proc)
=> 1
And we would call it like this:
(define (call proc n)
(unless (zero? n)
(displayln (proc))
(call proc (sub1 n))))
(call (counter 0) 5)
=> 0
1
2
3
4
Also notice that the above fixes an off-by-one error originally in your code - the procedure was being called six times (from 0 to 5) and not five times as intended, that happened because call invokes counter five times, but you called counter one more time outside, when evaluating (counter 0).

Scheme notation for "and" conditional

For an SICP course we are learning Scheme and we had an assignment that asked us to check if a point was in an axis-aligned rectangular. I did it like this:
(define in-rect?
(lambda (px py rx1 ry1 rx2 ry2)
(<= (* (- px rx1) (- px rx2)) 0) and
(<= (* (- py ry1) (- py ry2)) 0)))
I did this according to my previous C habits and forgot about Polish notation for a while there. The interpreter that our online tutor program uses runs this code "correctly", as I intended. However, AFAIK, this usage of 'and' should syntactically be wrong. DrRacket points out a syntax error when I try to run this.
Then how did this evaluate to correct values for every test case on the online tutor? Is this option also valid maybe?
The syntax for and is the same as for most expression - it uses prefix notation; also it can have zero or more arguments, which don't necessarily have to be boolean expressions:
(and <exp1> <exp2> <exp3> ...)
For your code it should look as follows:
(define in-rect?
(lambda (px py rx1 ry1 rx2 ry2)
(and (<= (* (- px rx1) (- px rx2)) 0)
(<= (* (- py ry1) (- py ry2)) 0))))
As to why your code seemed to work in the online tutor, it's because the interpreter probably evaluated the body of the lambda inside an implicit begin with three expression (first <= expression, and special form, second <= expression), returning just the value of the last condition. Although it's weird that it worked at all, because an and without arguments generally rises a "bad syntax" or similar error - it all depends on how it was implemented, but doesn't seem like a standards-compliant interpreter.
To make sure everything's clear, take a look at the documentation, because and behaves slightly different than what you'd expect, coming from a C background. Remember that and short-circuits at the first false condition:
(and (+ 1 1) #f (/ 1 0)) ; will work without a division by zero error
^
evaluation stops here
=> #f
And notice that and returns the value of the last expression it encounters, because in Scheme anything that is not explicitly #f, is considered true:
(and #t (* 2 3) (+ 1 1))
^
evaluation stops here
=> 2
(<= (* (- px rx1) (- px rx2)) 0)
and
(<= (* (- py ry1) (- py ry2)) 0)
Is actually three different (potential) values/expressions. Because you didn't wrap it in a begin, the interpreter might return the leftmost or the rightmost as the value of the lambda depending on your implementation.
Your online interpreter probably implemented and as a primitive function, rather than a macro or syntax, or simply isn't strick about not using macros/syntactic keywords as expressions.
If the interpreter thinks and has some sort of value (and/or is a valid expression) it can proceed to returning the value of the first of third expression in your lambda body.

Using "do" in 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).

Resources