I have a problem with Racket (Scheme) and the procedure "Eval".
To check "eval" in Dr.Racket, we can type in the interpreter, e.g.,
(eval '(+ 5 2))
If we work with lists, we can have,
(eval '(append '(a) '(b)))
That returns,
'(a b)
Until here all is fine,
but I want to do something like:
(define x_list '(append a))
(define y_list '(b c))
(eval (list (car x_list) (cdr x_list) (list (car y_list))))
That obviously doesn't work, because there are not quotes
in front of the lists, i.e. what is doing is,
(eval '(append (a) (b)))
My question is, there is any way to put the quotes in
front of the lists to make this working??
(eval (list (car x_list) (cdr x_list) (list (car y_list))))
Try this:
(eval (list (car x_list) `',(cdr x_list) `',(list (car y_list))))
=> '(a b)
The trick was using quasiquoting, check the documentation for more details.
Related
I'm fairly new to scheme and have been playing around with it and one of the problems I have placed upon myself is to remove all symbols from a single list of elements.
(define lst '(a 2 3 a 2 d 3))
(define removeSymbol
(lambda (lst)
(if (null? lst)
'()
(if (symbol? (car lst))
(removeSymbol (cdr lst))
(cons car lst) (removeSymbol (cdr lst))))))
(removeSymbol lst)
I feel like this should work, but it is not giving me what I am expecting.
My expectation: (list 2 3 2 3)
Any help or guidance would be appreciated.
You mentioned your unmet expectation, but not your result.
I'm guessing you're seeing a syntax error (in Racket, I get: if: bad syntax; has 4 parts after keyword) because the body of your nested if contains 3 s-expressions.
(if (symbol? (car lst))
(removeSymbol (cdr lst))
(cons car lst)
(removeSymbol (cdr lst)))
If you shuffle your parens so that they look like the following, your function should work as expected:
(define lst '(a 2 3 a 2 d 3))
(define (removeSymbol lst)
(if (null? lst)
'()
(if (symbol? (car lst))
(removeSymbol (cdr lst))
(cons (car lst) (removeSymbol (cdr lst))))))
(removeSymbol lst) ;; '(2 3 2 3)
I appreciate you're just working through this example as a learning exercise, but what you're attempting to do could also be achieved (arguably) a bit more idiomatically using the prelude functions filter, negate and symbol?:
(filter (negate symbol?) lst) ;; '(2 3 2 3)
Lets say I have a list containing arguments, how can I display it without the parentheses, example:
(define lst (list 1 2 3)) (display lst)
-> (1 2 3)
But I want it to appear as: 1 2 3
My attempt:
(define (clean-list lst)
(if
(null? lst) (display (null))
(display (car lst)))
(display #\space)
(clean-list (cdr lst)))
It returns the the list without parentheses, but with an error message... Anyone who could help me with this? Also note that im new to racket and racket is my first programming language. Appreciates all answers!
The error is caused by the fact that you always call recursively the function, after the if, even when the list is null.
Here is a correct version:
(define (clean-list lst)
(when (cons? lst)
(display (car lst))
(display #\space)
(clean-list (cdr lst))))
Note that this function prints only the elements on the first level of the list without parentheses, but if an element is a list it is printed with parentheses.
I'm having trouble understanding how Scheme forms and then detects lists. Hows does it determine the difference between a list and a dotted pair?
A list structure is formed from pairs. A proper list is a chain of pairs where the last pair has the empty list as its cdr.. We can make list? like this:
(define (list? lst)
(cond ((null? lst) #t)
((pair? lst) (list? (cdr lst)))
(else #f)))
Or you could use and/or:
(define (list? lst)
(or (null? lst)
(and (pair? lst)
(list? (cdr lst)))))
I have been working in DrRacket, trying to create a "prefix" function (#lang racket). It should take two lists as an input, and should output #t if pf is either null, or is equal to the beginning of ls.
My problem is that my code doesn't seem to return anything at all when pf is not a prefix of ls and ls isn't null. If I replace the #f in the if statement with something else, like '(), it will return that properly, but if I try to capture the '() and give an output based on that instead, it gives results that don't make sense (like saying that '() isn't null, or that '() doesn't equal '()). It seems to have something to do with having an if statement within a cond statement. Could anyone tell me what it's doing, or why? Is it possible to make this code work correctly, or am I going to need to rework it another way?
Thanks for the help!
(define prefix
(lambda (pf ls)
(cond
[(null? pf) #t]
[(null? ls) #f]
[(if (equal? (car pf) (car ls)) (prefix (cdr pf) (cdr ls)) #f)])
))
Having an if within a cond condition is usually a sign of doing something wrong. I think you meant to say this:
(define prefix
(lambda (pf ls)
(cond
[(null? pf) #t]
[(null? ls) #f]
[(equal? (car pf) (car ls)) (prefix (cdr pf) (cdr ls))]
[else #f])))
I would like to go through a list (which may have nested lists) and have it evaluate to one flattened list with all of the elements. I can't even get a recursive function to evaluate to anything other than nil
(defun pl(lst)
(if (atom lst)
lst
(progn
(pl (car lst))
(pl (cdr lst)))))
I'll then call with something like (pl '(1 (2 3) (4 5))), but it always evaluates to nil.
I changed
(if (atom lst) lst
to
(if (atom lst) (print lst)
and this doesn't even print any of the items of the list.
what concept I am missing here?
A function will normally only return one value, which is value of its body. If you look closely at pl you see that it is an if form, so pl either returns the value of lst or the value of progn.
The first thing I have to point out here is that the return value of a (progn ...) form is the value of its last expression, which in this case is the recursive call (pl (cdr lst)). As you do not do anything with the return value of (pl (car lst)) this call has no effect whatsoever. The value of the recursive call will at some point fall through the atom test. The second thing to point out here is that (atom nil) is also true. Remember that the last element of a list is nil, so when you give pl a list it will always return nil as you have observed.
If your print version shows nothing, it is probably because the print output is shown somewhere else, in another buffer for example.
As for the solution: you either want a pure recursive solution by using append instead of progn, because that's what in your homework assignment. In regular lisp you just use one of the iteration constructs.
My advice is to check any textbook on lisp or scheme to grasp the fundamentals of recursion and tail-recursion.
You might consider looking at an introductory text like "The Little Schemer". One of the first things it does is shows you how to take a consistent approach to problems just like this. The resulting function might look like:
(define (pl lst)
(cond ((null? lst) '())
((not (pair? lst)) (list lst))
(else (append (pl (car lst))
(pl (cdr lst))))))
Sure, this is Scheme, but the approach is the same for Lisp:
Check for the special case where the argument is nil
Check for the special case where the argument is an atom
Recursively apply the function to the car and cdr of the argument, appending the results
The same function in Lisp would look like:
(defun pl (lst)
(cond ((null lst) '())
((atom lst) (list lst))
(t (append (pl (car lst))
(pl (cdr lst))))))
Arguments can be made that this is not the most efficient code, but that isn't the point. This type of pattern occurs over and over again. It's a good idiom to learn.