I just began to play with Lisp and I'm trying to use funcall inside cons.
This is what I'm trying to do:
(cons '(1 2 3) '(1 (funcall #'rest '(a b)) ))
The result should be:
((1 2 3) 1 (b))
I know this works:
(cons '(1 2 3) (funcall #'rest '(a b)))
And I tried this already and it didn't work
(cons '(1 2 3) `,'(1 (funcall #'rest '(a b)) ))
(cons '(1 2 3) '(1 (apply 'rest '(a b))))
(cons '(1 2 3) '(1 `,(apply 'rest '(a b))))
Thanks in advance.
(cons '(1 2 3) `(1 ,(funcall #'rest '(a b))))
When you quote a list, everything is quoted inside the list, so there is no function call. You can achieve what you want like this:
[1]> (cons '(1 2 3) (list 1 (funcall #'rest '(a b)) ))
((1 2 3) 1 (B))
[2]>
Related
I'm not been able to make this working on. I'm defining a predicate using deftype SameType(x y) method, which evaluates whether the elements of list x and list y are of the same type, and in the same position. The problem comes when I try to call the predicate for testing. I receive an error ERROR: SameType is undefined This is my code:
(deftype SameType (x y)
`(cond
((and (null x) (null y) T))
(
(and (numberp (car x)) (numberp (car y)))
(SameType (cdr x) (cdr y) )
)
(
(and (stringp (car x)) (stringp (car y)))
(SameType (cdr x) (cdr y) )
)
(
(and (atom (car x)) (atom (car y)))
(SameType (cdr x) (cdr y) )
)
(T nil)
)
)
And this is how I'm calling it
(SameType '(A B C 1 2 4 A) '('() G 2 5 6 A B))
I already checked on various onine resources, even related questions on this site.
deftype can be used to define a type, not a predicate. For instance, to define the type of the lists with only integers, you could write something like:
(defun intlistp (l)
"predicate to check if l is a list consisting only of integers"
(and (listp l) ; l is a list and
(every #'integerp l))) ; every element of l is an integer
(deftype integer-list ()
"the type of list of integers"
`(satisfies intlistp))
and then you can check if a value satisfies this type:
CL-USER> (typep '(1 2 3) 'integer-list)
T
CL-USER> (typep '(1 2.5 3) 'integer-list)
NIL
If you want to check if two lists have the same type according to your definition, then you could define a regular function:
(defun same-type (l1 l2)
"check if lists l1 and l2 have the same length and corresponding
elements of the same CL type"
(cond ((null l1) ; if l1 is null
(null l2)) ; returns true only if also l2 is null
((and (consp l1) ; if l1 is a cons
(consp l2) ; and l2 is a cons too,
(typep (car l1) (type-of (car l2)))) ; and their cars have the same CL type
(same-type (cdr l1) (cdr l2))))) ; go recursively on their cdrs
CL-USER> (same-type '(1 a 3) '(2 b 4))
T
CL-USER> (same-type '(1 "a" 3) '(2 "b" 3))
T
CL-USER> (same-type '(1 a 3) '(2 b 4.5))
NIL
CL-USER> (same-type '(1 a 3) '(2 b 4 3))
NIL
CL-USER> (same-type '(1 2 (3 4)) '(1 6 (4 5)))
T
CL-USER> (same-type '(1 2 (3 4)) '(1 6 (4 5 6)))
T
Note that, as you can see from the last example, the type is checked only for the first level of the list.
My question is how can i print the elements of a list two times, the code i have tried is given below
(define duplicate-list
(lambda (mylist n)
(cond ((null? mylist) '())
((< n 2) (cons (car mylist)
(duplicate-list mylist (+ n 1))))
(else
(duplicate-list (cdr mylist) 0)))))
(define duplicate
(lambda (mylist)
(duplicate-list mylist 0)))
The problem in this code is that, it works fine only when i give it a list as input, this fails to work when i give it an input of a nested list.
>(duplicate '(a 1 b 2 c 3 r x)) -> a a 1 1 b b 2 2 c c 3 3 r r x x
>(duplicate '( (a 1) b ((c)) 2)) ->((a 1) (a 1) b b ((c)) ((c)) 2 2)
Whereas, the expected outcome needed should be
(duplicate '( (a 1) b ((c)) 2 z 3) = ( (a a 1 1) b b ((c c)) 2 2 z z 3 3)
You're using the wrong approach to build the output list, you have to recur over the car and cdr parts, given that this is a list of lists. Try this:
(define (duplicate lst)
(cond ((null? lst)
'())
((not (pair? (car lst)))
(cons (car lst)
(cons (car lst) ; here we duplicate each element
(duplicate (cdr lst)))))
(else
(cons (duplicate (car lst))
(duplicate (cdr lst))))))
It works as expected:
(duplicate '((a 1) b ((c)) 2 z 3))
=> '((a a 1 1) b b ((c c)) 2 2 z z 3 3)
Here's another solution using pattern matching via match -
(define (duplicate l)
(match l
((list (list a ...) b ...) ; nested list
(cons (duplicate a)
(duplicate b)))
((list a b ...) ; flat list
(cons a
(cons a
(duplicate b))))
(_ ; otherwise
null)))
It works as expected -
(duplicate '((a 1) b ((c)) 2 z 3))
; '((a a 1 1) b b ((c c)) 2 2 z z 3 3)
(duplicate '())
; '()
i have a function in scheme, this function calls another function many times, and every time this function appends return value of another function to result value.
but finally i want to get a result such that '(a b c), however i get a result such that '((a) (b) (c)) how can i fix this problem? i have searched but i couldn't find good solution.
my little code like that not all of them.
(append res (func x))
(append res (func y))
(append res (func z))
my code like this
(define (check a )
'(1)
)
(define bos '())
(define (func a)
(let loop1([a a] [res '()])
(cond
[(eq? a '()) res]
[else (let ([ x (check (car a))])
(loop1 (cdr a) (append res (list x)))
)]
)
))
Try this:
(define (func a)
(let loop1 ([a a] [res '()])
(cond
[(eq? a '()) res]
[else
(let ([ x (check (car a))])
(loop1 (cdr a) (append res x)))])))
Notice that the only change I made (besides improving the formatting) was substituting (list x) with x. That will do the trick! Alternatively, but less portable - you can use append* instead of append:
(append* res (list x))
As a side comment, you should use (null? a) for testing if the list is empty. Now if we test the procedure using the sample code in the question, we'll get:
(func '(a b c))
=> '(1 1 1)
It seems that instead of
(loop1 (cdr a) (cdr b) c (append res (list x)))
you want
(loop1 (cdr a) (cdr b) c (append res x))
Basically the trick is to use cons instead of list. Imagine (list 1 2 3 4) which is the same as (cons 1 (cons 2 (cons 3 (cons 4 '())))). Do you see how each part is (cons this-iteration-element (recurse-further)) like this:
(define (make-list n)
(if (zero? n)
'()
(cons n (make-list (sub1 n)))))
(make-list 10) ; ==> (10 9 8 7 6 5 4 3 2 1)
Usually when you can choose direction you can always make it tail recursive with an accumulator:
(define (make-list n)
(let loop ((x 1) (acc '()))
(if (> x n)
acc
(loop (add1 x) (cons x acc))))) ; build up in reverse!
(make-list 10) ; ==> (10 9 8 7 6 5 4 3 2 1)
Now this is a generic answer. Applied to your working code:
(define (func a)
(let loop1 ([a a] [res '()])
(cond
[(eq? a '()) (reverse res)]
[else
(let ([x (check (car a))])
(loop1 (cdr a) (cons (car x) res)))])))
(func '(a b c)) ; ==> (1 1 1)
append replaces the cons so why not put the car og your result to the rest of the list. Since you want the result in order I reverse the result in the base case. (can't really tell from the result, but I guessed since you ise append)
(defun filter-numbers-rec (inlist)
"This function filters out non-numbers from its input list and returns
the result, a list of numbers"
(cond
((not (listp inlist))
(princ "Argument must be a list")
(terpri)
())
((null inlist)
())
((not (numberp (car inlist)))
(filter-numbers-rec (cdr inlist)))
(t
(cons (car inlist)
(filter-numbers-rec (cdr inlist))))))
Well, the description of what the function does is that you want to remove each thing from the the list if it is not a number, so a good candidate here is remove-if-not, which you would use as follows:
(remove-if-not 'numberp '(1 a 2 b 3 c #\x (y 4)))
;=> (1 2 3)
If, for some reason, you want to write this in a way that (might) not use recursion, you could use do:
(do ((list '(1 a 2 b 3 c #\x (y 4)) (rest list))
(result '()))
((endp list) (nreverse result))
(when (numberp (car list))
(push (car list) result)))
;=> (1 2 3)
If you don't like the wordiness of do, you can use loop:
(loop :for x :in '(1 a 2 b 3 c #\x (y 4))
:when (numberp x)
:collect x)
;=> (1 2 3)
Input1:
(decompose '(* 1 2 3 4))
Output1:
'(* 1 (* 2 (* 3 4)))
Input2
(decompose '(+ 1 2 3 (* 5 6 7)))
Output2
'(+ 1 (+ 2 (+ 3 (* 5 (* 6 7)))))
Does anyone have ideas about this?
Same way as you would evaluate it, but instead of outputting the result, you simply output the expression that would be used.
Here's my implementation, tested on Racket:
(define (decompose expr)
(define (expand x)
(if (list? x)
(decompose x)
x))
(define oper (car expr))
(let next ((args (map expand (cdr expr))))
(if (<= (length args) 2)
(cons oper args)
(list oper (car args) (next (cdr args))))))
I see you posted your own solution, so I guess it's ok to show my complete answer. Here's another possible implementation, as a mutually-recursive pair of procedures. I like the fact that this solution doesn't require using length or list? (which might entail unnecessary traversals over the list), and uses only elementary functions (no foldr, reverse, map or any other higher-order procedures are needed.)
(define (decompose lst)
(if (or (null? lst) ; if the list is empty
(null? (cdr lst)) ; or has only one element
(null? (cddr lst))) ; or has only two elements
lst ; then just return the list
(process (car lst) ; else process car of list (operator)
(cdr lst)))) ; together with cdr of list (operands)
(define (process op lst)
(cond ((null? (cdr lst)) ; if there's only one element left
(if (not (pair? (car lst))) ; if the element is not a list
(car lst) ; then return that element
(decompose (car lst)))) ; else decompose that element
((not (pair? (car lst))) ; if current element is not a list
(list op ; build a list with operator,
(car lst) ; current element,
(process op (cdr lst)))) ; process rest of list
(else ; else current element is a list
(list op ; build a list with operator,
(decompose (car lst)) ; decompose current element,
(process op (cdr lst)))))) ; process rest of list
It works for your examples, and then some:
(decompose '(* 1 2 3 4))
=> '(* 1 (* 2 (* 3 4)))
(decompose '(+ 1 2 3 (* 5 6 7)))
=> '(+ 1 (+ 2 (+ 3 (* 5 (* 6 7)))))
(decompose '(+ 1 (* 4 5 6) 2 3))
=> '(+ 1 (+ (* 4 (* 5 6)) (+ 2 3)))
(decompose '(+ 1 2 3 (* 5 6 7) 8))
=> '(+ 1 (+ 2 (+ 3 (+ (* 5 (* 6 7)) 8))))
(decompose '(+ 1 2 3 (* 5 6 7) (* 8 9 10) (* 11 12 (- 1))))
=> '(+ 1 (+ 2 (+ 3 (+ (* 5 (* 6 7)) (+ (* 8 (* 9 10)) (* 11 (* 12 (- 1))))))))
Modified from Chris Jester-Young's solution:
(define (decompose x)
(if (pair? x)
(let ((operator (car x))
(expanded-x (map decompose x)))
(let decompose-helper ((operands (cdr expanded-x)))
(if (<= (length operands) 2)
(cons operator operands)
(list operator (car operands) (decompose-helper (cdr operands))))))
x))