DrRacket - Intermediate Student With Lambda - List ordering - scheme

I have an assignment question that asks me to write a function, using lambda, that consumes a list of numbers and removes all but the first occurrence of each number. My function is I think quite nice, with the exception that it produces the wrong result! It produces a list that contains the last occurrence of each number. It produces a list with the same values as the proper list, just in different order. Here's my code:
(define (remove-duplicates numlist)
(foldr (lambda (a b)
(cond
[(not (member? a b)) (cons a b)]
[else b])) empty numlist))
I've tried using foldl instead of foldr but, not surprisingly, it produces the correct list, but in reverse. Is there a way of producing the correct list without resorting to reversing the list created by foldl with another lambda expression?
Please keep in mind, this is homework so no explicit answers please.
Thanks everyone!

Think about how foldr behaves, semantically. It starts at the rightmost element of the list, and performs the fold, moving leftwards. That means that in your lambda function, a represents the element directly to the left of the thus-far-folded list, and b represents the result of folding everything to the right of the list element a. With this in mind, consider:
[(not (member? a b)) (cons a b)]
[else b]
You check whether the list b already contains a. If it does, then you discard a, keeping b as it is. This explains why your code keeps the last (rightmost) occurrence, and not the first. If you wish to perform a right fold, then, you must change your logic. You need to somehow "purge" b of the offending element a that it contains.
[(not (member? a b)) (cons a b)]
[else (cons a (purge a b))]
This way, you will eventually keep only the leftmost, rather than the rightmost, occurrence of each unique element. It may be wise to perform member? and purge simultaneously, since they both must traverse the list; this would require additional refactoring.
Note that, since the function takes O(n2) time anyways, it really doesn't hurt the time complexity to add a O(n) reverse to the foldl version.

Related

Is the cdr of a list always eqv?

I am writing an interpreter for R7RS Scheme to gain a more complete understanding of the Scheme programming language.
From my understanding, eqv? must return #t if both list arguments denote the same location in memory. However, I am not sure if the cdr of a list must always be eqv:
(define l '(a b c))
(eqv? (cdr l) (cdr l)) ; #t of #f?
The missing part of my knowledge is whether or not the cdr of a particular list must always point to a particular location. For a particular list, must cdr always return an identical sublist every time it is called on the list, or can it return a completely new sublist?
(I understand that I can test this empirically using existing Scheme interpreters, but I am mainly interested in what the standard mandates).
eq? is pointer equality (symbol, boolean, empty list)
eqv? is #t for everything that is eq? and the same primitive value (number, char)
equal? is #t for everything that is eqv? and values that look the same
cdr is an accessor. (cdr l) will return the same pointer and thus (eq? (cdr l) (cdr l)) ; ==> #t and so will eqv? and equal? since they are guaranteed #t when a lower level equality predicate is.
Note that is is not the other way around. eg. (equal? "test" "test"); ==> #t but (eqv? "test" "test") can be either #f or #t. The cause of the different behavior is if you reuse constant data when you read the code rather then create new.
It's common to store primitive values in the pointer. Eg. on a 64 bit machine the last 3 bits is always 0 since we access the words aligned. Scheme implementation usually then code 0-7 to indicate type and often when it's 0 the rest of the bits isn't a location at all rather than a number embedded in the pointer. This way you can have a list (1 2 3) that uses 6 words. 3 pairs of 2 words each but no memory used for the numbers when they fit the 61bit size. This is why numbers and char are often eq? while not guaranteed in the report.

Scheme what does #= as output mean?

Hi I'm trying to learn Scheme and I was working on an example from a university website:
https://courses.cs.washington.edu/courses/cse341/05au/lectures/scheme-side-effects.html
The example is something along these lines:
(define circ '(a b))
(set-cdr! (cdr circ) circ)
and this is the output:
=> #0=(a b . #0#)
I don't understand what this means. The code defines a variable called circ as a list with 2 elements (a b).
set-cdr! mutates the cdr of this list [which is (b '())] and changes it to circ (which is (a b)).
So the output I expected here was (a (a b)) but I got this weird hashtag thing instead.
I'm using DrRacket IDE with R5RS scheme set as the language.
What does this hashtag stuff mean? Is it maybe creating a pointer to itself like (a [pointer to circ]) in which case it would be like some kind of infinite loop or something?
I mean if I do this:
(define x '(a b))
(set-cdr! x 'c)
x
=>(a . c) ; is the output
this is easy to understand as set-cdr! replaces the (b '()) with 'c and getting rid of the '() at the end is why I get a dotted pair back instead of a list. But this isn't in-line with the earlier example.
anyway if anybody cares to fill me in, let me know. Thanks in advance.
You are correct in thinking that the operation is the creation of a circular list.
Drawing a list through its cons cells, this is the situation after the define:
and this is the situation after the set-cdr!:
Note that the modification is on the cdr of the cdr of circ (so on the cdr of the second cell). The notation #0=(a b . #0#) in lisp languages describes an improper list where the last cdr is equal to the list itself, producing a circular data structure (i.e. a data structure with a “loop”).

Why closure use seems so "chicken or egg"

I've read and somewhat understand Use of lambda for cons/car/cdr definition in SICP. My problem is understanding the why behind it. My first problem was staring and staring at
(define (cons x y)
(lambda (m) (m x y)))
and not understanding how this function actually did any sort of consing. Consing as I learned it from various Lisp/Scheme books is putting stuff in lists, i.e.,
(cons 1 ()) => (1)
how does
(define (cons x y)
(lambda (m) (m x y)))
do anything like consing? But as the light went on in my head: cons was only sort of a placeholder for the eventual definitions of car and cdr. So car is
(define (car z)
(z (lambda (p q) p)))
and it anticipates an incoming z. But what is this z? When I saw this use:
(car (cons 1 2))
it finally dawned on me that, yes, the cons function in its entirety is z, i.e., we're passing cons to car! How weird!
((lambda (m) (m 1 2)) (lambda (p q) p)) ; and then
((lambda (p q) p) 1 2)
which results in grabbing the first expression since the basic car operation can be thought of as an if statement where the boolean is true, thus, grab the first one.
Yes, all lists can be thought of as cons-ed together expressions, but what have we won by this strangely backward definition? It's as if any initial, stand-alone definition of cons is not germane. It's as if uses of something define that something, as if there's no something until its uses circumscribe it. Is this the primary use of closures? Can someone give me some other examples?
but what have we won by this strangely backward definition?
The point of the exercise is to demonstrate that data structures can be defined completely in terms of functions; that data structures are not necessary as a primitive construct in a language -- if you have functions (that are closures), that's sufficient. This shows the power of functions, and is probably mind-boggling to someone from outside of functional programming.
It's not that in a real project we would actually define data structures this way. It would be more efficient to use language-provided data structure constructs. But it's important to know that we can do it this way. In computer science, it's useful to be able to "reduce" one construct (data structures) into another construct (functions) so that if we prove something about the second construct, it applies to the first one too.

How to write a scheme procedure for mean and median of a list?

I need to write a basic scheme procedure that can find the median of a list and another for the mean.
This is what I've come up with so far:
Mean:
(define (mean lst)
(if (null? lst) ()
(+ 1 (car lst) (mean (cdr lst))))
I know I need to divide my the length somewhere but not sure how to do so. My thought process for this is to add each element to the stack of the list and then divide my the length of the list?
Median:
I'm not sure where to start for median.I know I need to determine if the list has an odd number of elements or even, so to do that I've come up with
(define (median lst)
(if (integer? (/ (length lst) 2) ;which is the one for even
I don't know if I need another procedure to get me to the middle of the list?
The median procedure was already discussed here.
Calculating the mean is simple, just add all the elements and divide by the length of the list, the only special case to take care of is when the list is empty (because that will lead to a division by zero: the length is zero!), return an appropriate value indicating this.
By now you should definitely know how to add all the elements in a list, check with your instructor in case of doubts, but it's a basic operation, it shouldn't be a problem.

How to declare a variable inside a Scheme function?

Is it possible to do so? Let's say I want to get the last element of a list, I would create a variable i = 0, and increment it until it equals to length. Any idea? An example would be greatly appreciated.
Thanks,
There are several ways to declare a variable; the cleanest one is let:
(let ((x some-expr))
; code block that uses x
But you don't need this to get the last element of a list. Just use recursion:
(define (last xs)
(if (null? (cdr xs))
(car xs)
(last (cdr xs))))
Note: if you want, you can use a variable to cache cdr's result:
(define (last xs)
(let ((tail (cdr xs)))
(if (null? tail)
(car xs)
(last tail))))
Yes, it's possible to define local variables in scheme, either using let or define inside a function. Using set!, it's also possible to reassign a variable like you imagine.
That being said, you should probably not solve your problem this way. In Scheme it's generally good practice to avoid set! when you don't need to (and in this case you definitely don't need to). Further iterating over a list using indices is usually a bad idea as scheme's lists are linked lists and as such random access O(n) (making the last function as you want to implement it O(n^2)).
So a simple recursive implementation without indices would be more idiomatic and faster than what you're planning to do and as such preferable.

Resources