Why is the word "list" showing up in my results? - scheme

Very new to Scheme, so I'm sorry for a basic question. Whenever I print out something as a test, my result always contains the word "list" in the list that is printed.
My code:
(define get-lower-half
(lambda (lst n)
(if (< n (quotient (length lst) 2))
(cons (list-ref lst n) (get-lower-half lst (+ n 1)))
'())))
(get-lower-half '(1 2 3 4 5) 0)
My result is then:
(list 1 2)
instead of just
(1 2)
The examples of using cons I find online don't have this problem, what the heck am I doing wrong here? I'm using DrRacket as my IDE with Intermediate Student with Lambda as the language.

I'm pretty sure you're expecting '(1 2) (a list), and not (1 2).
(1 2) is not a valid procedure in Racket or in the intermediate language.
In the intermediate language, lists are represented with the list procedure, (list 1 2) and not '(1 2) like in regular Racket. What you are seeing is regular intermediate language behaviour.

In Scheme there are the concepts of datum and datum syntax.
A datum is the mathematical part of an object. For example, the number 3 or the pair (x y) is a datum. A datum syntax is a way to represent datum. For example, #x03 or 3 or #b11 are datum syntax for representing the datum 3. In the same way, the datum (x y) can be represented in syntax as (x y) or (x . (y . ())).
The scheme output has many options to print the datum. Some output functions print the datum such that what they print to be valid code that creates the given datum or they can print the datum as valid syntax as data that will create that datum.
See io-ports and datum definitions.

Related

What is supposed to happen when a procedure's argument is given multiple values when it expects one value only?

(+ (values 1) (values 2)) returns 3. What is (+ 1 (values 2 3)) supposed to return? In R7RS-small, is the second value in a (values ...) automatically ignored when only one value is needed? In Guile 3.0.7, (+ 1 (values 2 3)) returns 3, but it gives an error in MIT Scheme 11.2 and Chibi 0.10.0.
(+ (values 1) (values 2)) is fine, and the result should be 3. But it is not the case that unneeded values are automatically ignored in a values expression; in fact the behavior of (+ 1 (values 2 3)) is unspecified in both R6RS and R7RS Scheme.
From the entry for values from R6RS 11.15 [emphasis mine]:
Delivers all of its arguments to its continuation....
The continuations of all non-final expressions within a sequence of
expressions, such as in lambda, begin, let, let*, letrec,
letrec*, let-values, let*-values, case, and cond forms,
usually take an arbitrary number of values.
Except for these and the continuations created by call-with-values,
let-values, and let*-values, continuations implicitly accepting a
single value, such as the continuations of <operator> and
<operand>s of procedure calls or the <test> expressions in
conditionals, take exactly one value. The effect of passing an
inappropriate number of values to such a continuation is undefined.
R7RS has similar language in 6.10:
The effect of passing no values or more than one value to continuations that were not created in one of these ways is unspecified.
The reason that (+ (values 1) (values 2)) is ok is that continuations of operands in procedure calls take exactly one value. (values 1) and (values 2) each provide exactly one value for their respective continuations.
call-with-values is meant for connecting producers of multiple values with procedures which consume those values. The first argument to call-with-values should be a procedure which takes no arguments and produces values to be consumed. The second argument should be a procedure which accepts the number of values produced by the first procedure:
> (call-with-values (lambda () (values 2 3))
(lambda (x y) (+ 1 x y)))
6
Note that the above use of call-with-values requires the consumer to accept the number of values produced by the producer since Scheme requires that implementations raise an error when a procedure does not accept the number of arguments passed to it:
> (call-with-values (lambda () (values 2 3 4))
(lambda (x y) (+ 1 x y)))
Exception: incorrect argument count in call (call-with-values (lambda () (values 2 3 4)) (lambda (x y) (+ 1 x y)))
If it is desirable for extra arguments to be ignored, the consumer must be designed towards that goal. Here the consumer is designed to ignore all but its first argument:
> (call-with-values (lambda () (values 2 3 4))
(lambda (x . xs) (+ 1 x)))
3

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.

Finding the largest list in a definition of lists in lists?

I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.

while loop in racket?

I am familiar with while loops in other languages but here I have written a small function that computes the derivative of a sum of terms but it only does the first 2 I was wondering if there was a way to alter this to take into account more than 2?
expressions, E, are represented as lists so 2x + 2y + x^3 is represented as (+ (* 2 x) (* 2 y) (expt x 3))
note that I already have functions written to compute the exponential but it is part of a sum and it stops after the first 2
(define (make-sum v1 v2)
(list '+ v1 v2))
(define (diff-sum x E)
(make-sum (diff x (first-operator E)) (diff x (last-operator E))))
In professional-level Racket, for loops are a standard approach to do something to a sequence. For example, the following produces a simple multiplication table:
(define numbers (list 1 2 3 4 5 6))
(for/list ([item numbers])
(list item (* item 2) (* item 3)))
It's a loop that walks through each number, processes it, and produces a new list of results. Fairly standard; almost every programming language has a notion of iteration across a collection.
In the kind of Racket that you'd have to write for an introductory computer science class, you might have to resort to explicit recursion or a higher order function like map instead, depending on your instructor. These other ways of expressing iteration have the same power as the above loop: we just phrase it a little differently.
For example, the same computation to create the small multiplication table above would be expressed as the following with explicit recursion:
(define (my-loop numbers)
(cond [(empty? numbers) '()]
[else
(define item (first numbers))
(cons (list item (* item 2) (* item 3))
(my-loop (rest numbers)))]))
(my-loop numbers)
and implicitly with the use of map:
(define (f item)
(list item (* item 2) (* item 3)))
(map f numbers)

Unusual way of parameter passing in Scheme

I'm trying to implement a function in scheme that splits the given list with the function that is also given as parameter to function. To exemplify:
(splitby '("a" "b" "cc" "ab" "abc" "a" "b")
(lambda (x y) (= (string-length x) (string-length y))))
should return (("a" "b") ("cc "ab") ("abc") ("a" "b"))
I'm pretty beginner in Scheme so it is really hard to understand how this 'function like' parameter works, and while implementing such a function what should I do?
In Scheme, functions are objects like numbers, strings, etc. So in this case, your example is equivalent to this:
(define (equal-length x y)
(= (string-length x) (string-length y)))
(splitby '("a" "b" "cc" "ab" "abc" "a" "b") equal-length)
The use of the function is to allow the splitting criterion to be customised. In this case, items are in the same group for as long as the given function returns a true value; otherwise a new group is created.
To get started, write a group-equal function, that groups equal elements together:
(define (group-equal lst)
...)
where, for example,
(group-equal '(1 2 2 3 3 3 4))
returns
((1) (2 2) (3 3 3) (4))
If you successfully implement that, then it's identical to your splitby function, except that you use the given function (equal-length, for example) instead of equal? (as group-equal might use).
Firstly, in Scheme, everything is inside parentheses. So If you want to apply the function f to values x and y, you write:
(f x y)
So you simply need to put splitby inside the first set of parens.
Secondly, functions can be passed as values into other functions, just like data is passed.
So if I have a functions:
(define (double x)
(* x 2))
I can write another function which takes double as an argument:
(define (change_result f x)
(f (+ 3 x)))
; (change_result double 6) returns 18
I can also do this the same way, if I use a lambda (anonymous) function:
(change_result (lambda (x) (* 3 x)) 10)

Resources