I am attempting to write a program that checks whether or not a list of lists has a certain property (unimportant to the question). Along the way I found it necessary to produce the list of "non-diagonal pairs" of a single given list, so I wrote a macro that takes a list and defines both the list of pairs (a list-version of the Cartesian product of sets) and what I'll call the "diagonal" of that list (pairs of the form '(x x)). The code I've written to accomplish this is below:
;;;These first two definitions are 'extended' car and cdr
;;;I only did this because the (prod a b) code below threw errors otherwise
(define (xcar a) (cond ((null? a) '()) ((car a))))
(define (xcdr a) (cond ((null? a) '()) ((cdr a))))
;;;This defines a pre-product, i.e. all pairs with the first element of the first list
(define (pre-prod a b)
(cond ((or (null? a) (null? b)) '())
((append (list (list (xcar a) (xcar b))) (pre-prod a (xcdr b))))))
;;;This defines the full product of the list
(define (prod a b)
(cond ((null? a) '())
((append (pre-prod a b) (prod (xcdr a) b)))))
;;;This defines the diagonal of the list
(define (diagonal a)
(cond ((null? a) '())
((append
(list (list (car a) (car a)))
(diagonal (cdr a))))))
Great, that code all seems to work just like I want it to. I next needed to take a list-version of the set-minus. I found the following code to do exactly this in an answer here:
;;;Returns #t if x is an element of lst and #f otherwise
(define (element? x lst)
(cond ((null? lst) #f)
((eq? x (car lst)) #t)
(#t (element? x (cdr lst)))))
;;;Takes list a and removes all elements of list b from it
(define (list-minus a b)
(cond ((null? a) '())
((element? (car a) b)
(list-minus (cdr a) b))
(#t (cons (car a) (list-minus (cdr a) b)))))
Cool, that seems to work just fine for what it needs to do. Now all I have to do is get DrRacket to return the list of proper pairs (removing the diagonal). I figure that the following code ought to do it:
(define (proper-pairs a) (list-minus (prod a a) (diagonal a)))
Now I test this new function on something easy, where it should return '():
> (proper-pairs '(1))
=> '((1 1))
WHAT? I've tried a lot of examples, reworked the code several times, tried it on various lists of lists. I always come up with the following problem: list-minus will not remove a list from a list of lists.
Question 1: Why does list-minus exhibit this anomalous behavior on lists of lists while working exactly as expected on things like the following example:
> (list-minus '(1 2 3 4 5) '(x 2 4 m))
=> '(1 3 5)
Question 2: How do I repair the list-minus code, or is it necessary to start from scratch?
Question 3: In the very first lines of code above I had to "extend" the car and cdr to ensure that the prod function would not throw an error. Is what I did a standard trick? I'm not sure I understand why it makes a difference (I just tried it in because I had a hunch it might work).
Disclaimer: I am not a programmer. I'm trying to learn functional programming as a means of testing various (mathematical) conjectures and compiling some examples. I have absolutely no experience writing code other than some very silly little bits that I've done in DrRacket and on an old TI-83 calculator. This being said, it will probably be necessary to "dumb-down" your answers for me.
Sorry for the long-windedness, and thank you for your time!
The problem is due to the fact that equality in Racket, like in other languages, is represented with different operators, that must be chosen according to:
the type of data that must be compared,
the semantics of the comparison.
The general hint is that you should use the operator which is logically more simple for the task and that can be used for a certain comparison.
For instance, you should use = to compare numbers; eq? to compare objects for identity i.e. two values are equal if the are the same object in memory; eqv? if you want to check that two values are the same object in memory or are equal numbers or equal characters; equal? if you want to check if two values are eqv? or if they are equal strings, or if they, being structured data like lists, are structurally equivalent (see the manual), i.e. recursively equivalent.
For instance:
(equal? '(a (b)) '(a (b))) ; => true, two different objects with the same structure
(eqv? '(a (b)) '(a (b))) ; => false, two different objects
(eq? '(a (b)) '(a (b))) ; => false, as for eqv?
(let ((x '(a (b))))
(eq? x x)) ; true, they are the same object
Related
The following Scheme code works fine:
(define (same-parity x . numbers-input)
(define (check-parity a) (= (remainder x 2) (remainder a 2)))
(define (iter numbers-left)
(cond ((null? numbers-left) nil)
((check-parity (car numbers-left)) (cons (car numbers-left) (iter (cdr numbers-left))))
(else (iter (cdr numbers-left)))))
(cons x (iter numbers-input)))
It is supposed to output a list with the first element being an integer x and the subsequent elements being all the integers from numbers-input which have the same parity as x.
If anyone is interested, this is my attempt at solving the exercise 2.20 from the book Structure and Interpretation of Computer Programs.
Now, I wanted to replace (car numbers-left) and (cdr numbers-left) with the variables "first" and "rest".
(define (same-parity x . numbers-input)
(define (check-parity a) (= (remainder x 2) (remainder a 2)))
(define (iter numbers-left)
(let ((first (car numbers-left))
(rest (cdr numbers-left)))
(cond ((null? numbers-left) nil)
((check-parity first) (cons first (iter rest)))
(else (iter rest)))))
(cons x (iter numbers-input)))
Trying to call this function now gives me an error:
> (same-parity 1 2 3 4 5)
. . mcar: contract violation
expected: mpair?
given: ()
Racket is highlighting the (car numbers-left) inside of the let-statement. Even when I never actually call "first" or "rest" in the body of the function and just leave it the way it was before, I get the same error.
However, in the following code I tried to copy the structure of the above procedure in a simple test definition and surprisingly, this works as you would expect.
(define (test x . testlist)
(define (test2 test2list)
(let ((first (car test2list)))
first))
(test2 testlist))
> (test 1 2 3 4 5)
2
It turns out that if I replace my (cond ...) in my original program with a simple call it works fine as well, so somehow the (cond ...) statement prohibits me from using the variables.
I know this is a very specific thing and I don't know if this ever really matters (except maybe if you want to make the code more readable) but I would really like to know why exactly it behaves this way.
Any insight would be appreciated!
Variables' values are evaluated as soon as you define them, whether you use them or not. Therefore you are calling (car '()) at the end of your recursion, once the list has become empty. You never make it to the part of your cond that attempts to exit.
Hi i am learning Scheme new.I have question.Lets think I have defined a function which it adds element to list if it is empty.If there is an element in list and new element is added as second to list and goes like this.For example
>(add a) ; here list is empty
'(a)
>(add b) ; here a is in the list
'(a b)
>(add c) ; here a and b is in the list
(a b c)
List is updated like this.How can I write a function like this.I add elements to empty list each time with my code.I mean it is like that with mine.
>(add a)
'(a)
>(add b)
'(b)
>(add c)
'(c)
How can I write the proper code for this purpose ?
here is my code
#lang racket
(define addToList
(lambda (a b)
(cond ((null? a) b)
((null? b) a)
((cons (car a) (addToList (cdr a) b))))))
(addToList '(1 2 3) '())
You can't "add" to an empty list in any Lisp dialect, because in all Lisp dialects, the empty list is a special, immutable value.
In Racket, not only is the empty list immutable, but so are all lists. Code that manipulates lists needs to be written in "functional" style to work properly.
"Adding" to a list in the sense of your add function would mean creating a whole new list with one more element and then binding it to the same variable as before:
;;; This implementation of add would behave just like
;;; the examples at the top of your question.
(define add
(let ((the-list '()))
(lambda (new-item)
(set! the-list
(append the-list (list new-item)))
the-list)))
The above function runs slower the longer the-list is because it has to
copy every element before adding the new one. It is much faster to add to the beginning of a list instead of the end:
(define add
(let ((the-list '()))
(lambda (new-item)
(set! the-list
(cons new-item the-list))
the-list)))
For this reason, most Racket programs build their lists backwards, and then
use reverse as late as possible to create a forward version of the list.
Just like any other language there are two ways to mutate a value. You can mutate what a variable points to (binding) or you can mutate the targeted object by altering parts of the object. The last one requires that the object is not a primitive.
Using variable binding:
#!r6rs
(import (rnrs))
(define lst '())
(define (add element)
(set! lst (append lst (list element))) ; adding to front is much cheaper
lst)
Using mutation:
#!r6rs
(import (rnrs)
(rnrs mutable-pairs))
(define lst (list 'head))
(define tail lst) ; keep the last cons so we can add O(1)
(define (add element)
(set-cdr! tail (list element))
(set! tail (cdr tail))
(cdr lst))
Your procedure looks more like the functional kind since it's not actually mutating anything, but it would work if you kept the result you got back and fixed the fact that it's not extending the list but adding the element to the tail as a dotted list.
(define addToList
(lambda (a b)
(cond ((null? a) (list b)) ; result needs to be a list
((null? b) a)
((cons (car a) (addToList (cdr a) b))))))
(define lst '())
(set! lst (addToList lst 1))
(set! lst (addToList lst 2))
(set! lst (addToList lst 3))
lst ; ==> (1 2 3)
I would have written it like this to make it look more like scheme:
(define (add-to-end lst e)
(if (null? lst)
(list e)
(cons (car lst)
(add-to-end (cdr lst) e)))))
Of course adding to front is much cheaper and is done with plain old cons. If you add some elements and actually wanted to add it to end you get the same effect by reversing the list after adding your elements.
I have been trying to transform a linear list into a set but with no avail. Everytime I run this, I get some weird compilation errors like "badly formed lambda" which points to the way I use append. Here is my code:
(defun mem(e l)
(cond
((null l) nil)
((equal e (car l)) t)
((listp (car l)) (mem e (car l)))
(t(mem e (cdr l)))
)
)
(defun st(l k)
(cond
((null l) nil)
(( mem '(car l) 'k) (st (cdr l) k))
((listp (car l)) (st (car l) k))
( t (st (cdr l) (append((car l) k)) ))
(t(mem e (cdr l)))
)
)
EDIT: frankly I just want to remove the duplicates from list l
Prefer Standard Library Functions
EDIT: frankly I just want to remove the duplicates from list l
Common Lisp has a remove-duplicates function. The documentation inclues examples:
Examples:
(remove-duplicates "aBcDAbCd" :test #'char-equal :from-end t) => "aBcD"
(remove-duplicates '(a b c b d d e)) => (A C B D E)
(remove-duplicates '(a b c b d d e) :from-end t) => (A B C D E)
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr) => ((BAR #\%) (BAZ #\A))
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr :from-end t) => ((FOO #\a) (BAR #\%))
Are you trying to flatten the list too?
From your code for mem, where you do:
((listp (car l)) (mem e (car l)))
it looks like you want your member function to also recurse into sublists. That's a bit questionable, even when working with sets, since sets can traditionally include other sets. E.g., {{3},{4},5} is a set containing 5, the set {3}, and the set {4}. It's not the same as the set {3,4,5}. Your st function also looks like it's trying to recurse into lists, which makes it seem like you want to flatten you lists, too. Again, that's a bit questionable, but if you want to do that, then your conversion to a set would be easier as a "flatten, then remove duplicates" process:
(defun flatten (list)
"Returns a fresh list containing the leaf elements of LIST."
(if (listp list)
(mapcan 'flatten list)
(list list)))
;; CL-USER> (flatten '(1 2 (3 4) 5 ((6))))
;; (1 2 3 4 5 6)
(defun to-set (list)
"Returns a set based on the elements of LIST. The result
is a flat list containing the leaf elements of LIST, but
with any duplicate elements removed."
(delete-duplicates (flatten list)))
;; CL-USER> (to-set '(1 3 (3 4) ((4) 5)))
;; (1 3 4 5)
Notes
I get some weird compilation errors like "badly formed lambda" which points to the way I use append.
Yes, you're trying to call append like: (append((car l) k)). That's actually not a problem for append. Remember, the syntax for a function call in Lisp is (function argument…). That means that you've got:
(append ((car l) k))
<function> <argument1>
But your argument1 is also a function call:
((car l) k )
<function> <argument1>
In Common Lisp, you can't use (car l) as a function. The only thing that can appear for a function is a symbol (e.g., car, append) or a lambda expression (e.g., (lambda (x) (+ x 1)).
You want to call (append (car l) k) instead.
First, CL does not have a set data type.
Lists, however, can be used as sets, you do not need to write any special code for that.
Second, I don't understand what your st function is supposed to do, but I bet that in the second cond clause you should not quote (car l) and k. You should use meaningful names for your functions and avoid abbreviations. As per your explanation in the comment, you should use pushnew instead.
Third, your mem function is quite weird, I am pretty sure you do not mean what you wrote: e is searched along a path in the tree l, not in the list l. As per your explanation in the comment, you should check both car and cdr:
(defun tree-member (tree element &key (test #'eql))
(if (consp tree)
(or (tree-member (car tree) element :test test)
(tree-member (cdr tree) element :test test))
(funcall test element tree)))
So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.
For my programming languages class I'm supposed to write a function in Scheme to reverse a list without using the pre-made reverse function. So far what I got was
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (CONS (reverseList(CDR lst)) (CAR lst)))
))
The problem I'm having is that if I input a list, lets say (a b c) it gives me (((() . c) . b) . a).
How am I supposed to get a clean list without multiple sets of parenthesis and the .'s?
The problem with your implementation is that cons isn't receiving a list as its second parameter, so the answer you're building isn't a proper list, remember: a proper list is constructed by consing an element with a list, and the last list is empty.
One possible workaround for this is to use a helper function that builds the answer in an accumulator parameter, consing the elements in reverse - incidentally, this solution is tail recursive:
(define (reverse lst)
(reverse-helper lst '()))
(define (reverse-helper lst acc)
(if (null? lst)
acc
(reverse-helper (cdr lst) (cons (car lst) acc))))
(reverse '(1 2 3 4 5))
=> '(5 4 3 2 1)
You are half way there. The order of the elements in your result is correct, only the structure needs fixing.
What you want is to perform this transformation:
(((() . c) . b) . a) ; input
--------------------
(((() . c) . b) . a) () ; trans-
((() . c) . b) (a) ; for-
(() . c) (b a) ; mation
() (c b a) ; steps
--------------------
(c b a) ; result
This is easy to code. The car and cdr of the interim value are immediately available to us. At each step, the next interim-result is constructed by (cons (cdr interim-value) interim-result), and interim-result starts up as an empty list, because this is what we construct here - a list:
(define (transform-rev input)
(let step ( (interim-value input) ; initial set-up of
(interim-result '() ) ) ; the two loop variables
(if (null? interim-value)
interim-result ; return it in the end, or else
(step (car interim-value) ; go on with the next interim value
(cons ; and the next interim result
(... what goes here? ...)
interim-result )))))
interim-result serves as an accumulator. This is what's known as "accumulator technique". step represents a loop's step coded with "named-let" syntax.
So overall reverse is
(define (my-reverse lst)
(transform-rev
(reverseList lst)))
Can you tweak transform-rev so that it is able to accept the original list as an input, and thus skip the reverseList call? You only need to change the data-access parts, i.e. how you get the next interim value, and what you add into the interim result.
(define (my-reverse L)
(fold cons '() L)) ;;left fold
Step through the list and keep appending the car of the list to the recursive call.
(define (reverseList lst)
(COND
((NULL? lst) '())
(ELSE (APPEND (reverseList(CDR lst)) (LIST (CAR lst))))
))
Instead of using cons, try append
(define (reverseList lst)
(if (null? lst)
'()
(append (reverseList (cdr lst)) (list (car lst)) )
)
)
a sample run would be:
1]=> (reverseList '(a b c 1 2 + -))
>>> (- + 2 1 c b a)
car will give you just one symbol but cdr a list
Always make sure that you provide append with two lists.
If you don't give two lists to the cons it will give you dotted pair (a . b) rather than a list.
See Pairs and Lists for more information.