I am confused as to how car and cdr work on lists. Here is an example of what I have tried:
(define sample (read))
(display sample)
(display (car sample))
(display (cdr sample))
(display (car (cadr sample)))
(display (cdr (cdr sample)))
On entering the value '(A B C D E F), here is what I get:
'(a b c d e f)
quote
((a b c d e f))
a
()
I am not able to understand that how quote can be the car of sample. Also, why does (cdr sample) output ((a b c d e f))?
Language: DrScheme - R5RS - Scheme
If you wanted to simply type the list (a b c d e f), you should just type (a b c d e f). What you typed, instead, was (quote (a b c d e f)) because the ' operator is short for (quote ...).
Your list literally has the first element quote and the second element (a b c d e f). Of course, when you're writing source code, you need the quote to prevent the S-expressions from being executed.
Related
Isn't it supposed to be (a b c d) ??
When I try it on Racket it gives me () .
'((a b c d)) is a list, containing only one element, that is the four-element list (a b c d). So if you get the car of it, you obtain as result (a b c d), while the cdr produces correctly the empty list ().
How would you create such a list using cons?
(cons (cons 'a (cons 'b (cons 'c (cons 'd '()))))
'())
or
(cons '(a b c d) '())
cdr returns the second element of the given pair, so it returns '().
I'm new to coding in racket, but I wanted to define a procedure that checks to see if a given list is a sublist (or part of) another list.
This is my code so far:
(define prefix?
(lambda (lst1 lst2)
(cond
((equal? lst1 lst2) #t)
((null? lst2) #f)
(else (prefix? lst1 (reverse (rest (reverse lst2))))))))
(define sublist?
(lambda (lst1 lst2)
(cond
((prefix? lst1 lst2) #t)
((null? lst2) #f)
(else (prefix? lst1 (rest lst2))))))
I've tried most cases and it works the way it's supposed to but when I tried this test case:
(sublist? '(a b d) '(a b c a b d e))
It returns #f when it's supposed to return #t
I tried tracing the sublist? procedure but it isn't returning me any useful information.
Is there a logic error in my code?
There is a logic error. The default case of sublist? should call sublist?, but instead calls prefix? so your prefix? will only be true if the match is either in index 0 or 1.
Also you have created a rather complex prefix?. Instead of comparing one by one element until any of them are empty you do a O(n) removal of the last element until you have a empty list before returning #f even if the two first elements are different. I would have compared the first elements and then recurred with rest in both args until either list is empty. Which one depends on the result and eg. (prefix '(a b) '(w a d f s)) will stop computing after the very first check between a and w.
try this:
(define sub?
(lambda (l sub)
(define test (lambda (x) (equal? x sub)))
((lambda (s) (s s l test))
(lambda (s l k)
(or (k '())
(and (pair? l)
(s s (cdr l)
(lambda (r)
(or (test r)
(k (cons (car l) r)))))))))))
(sub? '(a b c a b d e) '(b d e) )
(sub? '(a b c a b d e) '(c a b) )
(sub? '(a b c a b d e) '(a b c) )
(sub? '(a b c a b x e) '(a b d) )
From this question we can construct an interleaved list out of two lists with a different length (according to Sylwester answer making use of circular-list). My question is how can we do the same but taking the elements of the second list randomly.
That is, I want to assign to the elements of a list a random value out of a list. For example: given the assigning list '(0 1) and whatever list '(a b c d) I want as the output a list such as '((a 0) (b 0) (c 1) (d 0)) or '((a 1) (b 0) (c 0) (d 1)) for example.
My attempts are:
(map cons '(a b c d) (circular-list (random '(0 1))))
which gives '((a . 0) (b . 0) (c . 0) (d . 0)) or '((a . 1) (b . 1) (c . 1) (d . 1)) and nothing different and
(map cons '(a b c d) (list (random '(0 1))))
which gives '((a . 0)) or '((a . 1)) and nothing different.
PS: I am making use of a function called random and defined as
(define (random lst) (list-ref lst (random (length lst))))
which in my example would take randomly 0 or 1 out of a list '(0 1).
To avoid confusion, you should rename your new "random" function on lists to random-element or something similar. That way both people reading your code, and Racket, will know the difference.
random : PositiveNaturalNumber -> NaturalNumber
random-element : [NonEmptyListof X] -> X
These two different functions need to have two different names so that when you want to refer to the first one random from Racket, you can do so. Otherwise Racket (as well as other people reading your code) will think you mean random-element when you really want random.
This confusion matters in the body of your definition of "random":
; /--------------<< This should be renamed to `random-element`
; \/
(define (random lst)
(list-ref lst (random (length lst))))
; /\
; \------<< This is meant to be the original Racket `random`
; but it ends up referring to "random-element" because
; of the naming conflict
Because of this name conflict, when this definition of random is put in a File, and I run a Repl for that File, I get an error like this:
> (random '(A B C D E F G))
length: contract violation
expected: list?
given: 7
When this is renamed, the definition should look like this:
;; random-element : [NonEmptyListof X] -> X
(define (random-element lst)
(list-ref lst (random (length lst))))
; /\
; \-------<< This is the `random` from Racket, not the "new" one
Using it:
> (random-element '(A B C D E F G))
'E
> (random-element '(A B C D E F G))
'B
> (random-element '(A B C D E F G))
'D
> (random-element '(A B C D E F G))
'F
> (random-element '(A B C D E F G))
'C
The comments can't contain code fragments, so ...
What does this program give?
#lang racket
(require srfi/1)
(random '(0) '(1))
On my computer with Racket 7.0 I get:
random: contract violation
expected: exact-integer?
given: '(0)
argument position: 1st
other arguments...:
I'm working on a program that takes a list of elements and each individual element is duplicated based on an integer contained in a 2nd list of integers. for example if I had a list of
(A B C D)
being duplicated by:
(1 5 4 2)
I would have
(A B B B B B C C C C D D)
So far I have
(defun COPY (X Y)
(if (zerop Y)
nil
(cons S (COPY X (1 - Y)))))
Of course this is only duplicating a single element a single number of times. Does anybody have a good idea how to go about this?
Use mapcan and
make-list (which is the library version of your copy):
(mapcan (lambda (letter num)
(make-list num :initial-element letter))
'(A B C D) '(1 5 4 2))
==> (A B B B B B C C C C D D)
or just
(mapcan #'copy '(A B C D) '(1 5 4 2))
If you are required to use simple recursion, you can also write
(defun copy-list-elements (elements counts)
(and elements counts
(let ((count (pop counts)))
(if (plusp count)
(cons (car elements)
(copy-list-elements elements
(cons (1- count) counts)))
(copy-list-elements (cdr elements)
counts)))))
(copy-list-elements '(A B C D E) '(1 5 4 0 2))
==> (A B B B B B C C C C E E)
Note that the recursive version is longer and probably slower.
Loop over the two lists, call copy, and append the results.
(loop for letter in letters
for count in counts
nconcing (copy letter count))
;How to get the value of 'a' in 'b'?
;Not want to assign the letter 'a' in 'b' want the value contained in 'a'
(define a 5)
(define c '(a c))
(define b (car c))
(display b)
(define a 5)
(define c (list a 'c))
(define b (car c))
(display b)
' is equivalent to the quote procedure. So '(a c) => (list 'a 'c)
See: http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Quoting.html#Quoting
Or, using your original code, are you asking how you would (eval b (the-environment))?