I have a list of functions, a list of elements, and I'd like to apply all the functions on all the elements then append all the resulting lists together. I did it as follow
(defun apply-functions(funcs elements)
(if (null funcs)
nil
(append (mapcar #'(lambda (x) (funcall (car funcs) x)) elements) (apply-functions (rest funcs) elements))))
It works as intended, but I don't like it. Is there a cleaner, more concise way of doing it?. I am new to lisp, and still getting used to the lispish style of doing things.
I don't know if you like loop macro (and I don't want to spoil anyone), but try this:
(defun apply-functions (fs es)
(loop for f in fs appending (mapcar f es)))
This is the same idea as yours, just shorter:
(defun apply-functions (functions elements)
(mapcan #'(lambda (x) (mapcar x elements)) functions))
I would define a function, call-each that returns a new function,
returning the list of calling each function on it's argument:
(defun call-each (fns)
(lambda (arg)
(mapcar (lambda (fn)
(funcall fn arg))
fns)))
(funcall (call-each (list #'third #'second #'first)) '(a b c))
;=> (C B A)
cl has the function mapcan which is basically nconc + mapcar :
(mapcan #'reverse '((a b c)
(e f g)
(h i j)))
;=> (C B A G F E J I H)
(mapcan (call-each (list #'identity #'1+)) '(1 3 5 7 9))
;=> (1 2 3 4 5 6 7 8 9 10)
unfortunately, nconc, which mapcan uses, is destructive:
(let ((data '((a b c)
(d e f)
(g h i))))
;;here be dragons
(list (mapcan #'identity data)
data))
;=> ((A B C D E F G H I) ((A B C D E F G H I) (D E F G H I) (G H I)))
alexandria to the rescue:
(let ((data '((a b c)
(d e f)
(g h i))))
;;safe version
(list (alexandria:mappend #'identity data)
data))
;=> ((A B C D E F G H I) ((A B C) (D E F) (G H I)))
note that using mapcan is more efficient, but unless you know exactly where
your data is coming from, and who owns it, mappend is the way to go.
so you could write:
(defun apply-functions (fs es)
(when fs
(alexandria:mappend (call-each fs) es))
(apply-functions (list #'identity #'1+) '(1 3 5 7 9))
;=> (1 2 3 4 5 6 7 8 9 10)
Related
How do i do in Racket a function that replaces the element of a list at the position n by e.
(repl-elem '(a b c d e) 2 d)
should return a d c d e
In order to replace the element with index 2 in a list with a new element 'A,
one can do the following:
#lang racket
(define xs (list 1 2 3 4 5))
(append (take xs 2)
(list 'A)
(drop xs (+ 2 1)))
I'll leave it as an exercise to turn this into a function.
To see "the mechanics behind this list-set" one can use 'named let' recursion:
(define (f L n c)
(let loop ((x 1)
(ol '()))
(cond
[(> x (length L))
(reverse ol)]
[(= x n)
(loop (add1 x) (cons c ol))]
[else
(loop (add1 x) (cons (list-ref L (sub1 x)) ol))])))
Testing:
(f '(a b c d e) 2 'd)
Output:
'(a d c d e)
OP can figure out how it is working.
I have a list defined as follows:
(defparameter testlist '(((a b) (c d)) ((e f) (g h ))) )
I also have a variable defined as :
(defparameter feature 'u)
I want to append a feature to (c d).
When I try:
(setf (nth 1 (nth 0 testlist)) (append (nth 1 (nth 0 testlist)) feature))
testlist becomes:
(((A B) (C D . U)) ((E F) (G H)))
However, I want a non dotted list.
I can't figure out why I have this result. Can you explain why or suggest a better method to append, that is comprehensible for a beginner level?
First off your feature is not a list. append allows the last argument to be anything but then the result would not be a proper list if the last element is itself not a proper list. Thus:
(append '(1 2) 3) ; ==> (1 2 . 3)
(append '(1 2) '(3 . 4)) ; ==> (1 2 3 . 4)
(append '(1 2) '(3 4)) ; ==> (1 2 3 4)
Thus you need to append (list feature) if you want feature to be one element in the list you are replacing and not the new dotted value.
You need to locate the list you are changing and everything before you need to recreate but everything after you can just share with the original source:
Looking at your structure you want to change the cadar while you need to recreate the caar while the result can share the cdr:
(let ((lst '(((a b) (c d)) ((e f) (g h )))) (feature 'x))
(list* (list (caar lst) (append (cadar lst) (list feature))) (cdr lst)))
; ==> (((a b) (c d x)) ((e f) (g h)))
Now how you choose to use that result is up to you. You can setf the binding and you will have the same behaviour as if you mutated except for the unwanted consequences.
How can I transform this list:
'((A B) (A C) (C D) (B D) (D E) (D F))
Into something like
'(A (B (nil)) (C (D ((F (nil)) (E (nil))))))
Or whatever list best represent the tree:
A
/ \
B C
|
D
/ \
E F
Note that as C was the first to claim D as its child, the (B D) didn't add the D as the child of B.
first of all i would clean up the data, removing all the unnecessary pairs (in your case '(B D)), and build the adjacency map:
user> (def data '((A B) (A C) (C D) (B D) (D E) (D F)))
#'user/data
user> (def nodes-map (group-by first
(apply sorted-set-by
#(compare (second %1) (second %2))
data)))
#'user/nodes-map
user> nodes-map
{A [(A B) (A C)], C [(C D)], D [(D E) (D F)]}
i removed the garbage using sorted-set, using the fact that it treats items to be equal using comparator, and keep only the first of them (in this case it considers (C D) and(B D) to be equal)
then i would construct the tree, using recursive function:
user> (defn to-tree [start nodes]
(list start
(if-let [connections (seq (nodes start))]
(map #(to-tree (second %) nodes) connections)
'(nil))))
#'user/to-tree
user> (to-tree 'A nodes-map)
(A ((B (nil)) (C ((D ((E (nil)) (F (nil))))))))
I want to fix my own function that gives the same result with the default intersection function. I've been trying to write a lisp code which prints same elements in the two lists. My code works for it. But it doesn't work for nested lists. How can I fix this?
(defun printelems (L1 L2)
(cond
((null L1) nil) ((member (first L1) L2) (cons (first L1) (printelems (rest L1) L2)))
(t (printelems (rest L1) L2))))
Expected inputs and outputs
(printelems '(2 3 5 7) '( 2 3)) => It works
=> (2 3)
(printelems '(a b '(c f)) '(a d '(c f) e)) => It doesn't work.
=> (a (c f))
Edit
Using the default intersection function works as intended. How can I use the equal function in my recursive function?
For default intersection,
(intersection '(a b (c f)) '(a d (c f) e) :test 'equal)
((C F) A)
(intersection '(a b (c f)) '(a d c f e) :test 'equal)
(A)
My intersection,
(printelems '(a b (c f)) '(a d c f e))
(A C F)
(printelems '(a b (c f)) '(a d (c f) e) )
(A C F)
My edited code:
(defun flatten (l)
(cond ((null l) nil)
((atom (car l)) (cons (car l) (flatten (cdr l))))
(t (append (flatten (car l)) (flatten (cdr l))))))
(defun printelemsv1(list1 list2)
(cond
((null list1) nil)
(((member (first list1) list2) (cons (first list1) (printelemsv1 (rest list1) list2)))
(t (printelemsv1 (rest list1) list2)))))
(defun printelems (L1 L2)
(printelemsv1 (flatten L1) (flatten L2)))
Common Lisp already has an intersection function. If you want to compare sublists like (C F), you'll want to use equal or equalp as the test argument.
(intersection '(a b '(c f)) '(a d '(c f) e) :test 'equal)
;=> ('(C F) A)
While it doesn't change how intersection works, you probably don't really want quote inside your list. Quote isn't a list creation operator; it's a "return whatever the reader read" operator. The reader can read (a b (c f)) as a list of two symbols and a sublist, so (quote (a b (c f))), usually abbreviated as '(a b (c f)) is fine. E.g.:
(intersection '(a b (c f)) '(a d (c f) e) :test 'equal)
;=> ((C F) A)
It's always helpful when you provide an example of input and the expected output. I assume you mean you have two lists like '(1 (2 3) 4) and '((1) 2 5 6) that the function should produce '(1 2). In this case you can just flatten the two lists before giving them to printelems.
Since I'm not familiar with Common-Lisp itself I will leave you with one example and a link.
(defun flatten (structure)
(cond ((null structure) nil)
((atom structure) (list structure))
(t (mapcan #'flatten structure))))
Flatten a list - Rosetta Code
flatten takes an arbitrary s-expression like a nested list '(1 (2 3) 4) and returns '(1 2 3 4).
So now you just have to write a new function in which you use your printelems as a helper function and give it flattened lists.
(defun printelems.v2 (L1 L2)
(printelems (flatten L1) (flatten L2)))
Take this with a grain of salt, since as said before I'm not familiar with Common-Lisp, so appologies in advance for any potential syntax errors.
I'll explain in math, here's the transformation I'm struggling to write Scheme code for:
(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)
Where two letters together like ad means (* a d).
I'm trying to write it in a purely functional manner, but I'm struggling to see how. Any suggestions would be greatly appreciated.
Here are some examples:
(1mul '(0 1) '(0 1)) = '(0 0 1)
(1mul '(1 2 3) '(1 1)) = '(1 3 5 3)
(1mul '(1 2 3) '(1 2)) = '(1 4 7 6)
(1mul '(1 2 3) '(2 1)) = '(2 5 8 3)
(1mul '(1 2 3) '(2 2)) = '(2 6 10 6)
(1mul '(5 5 5) '(1 1)) = '(5 10 10 5)
(1mul '(0 0 1) '(2 5)) = '(0 0 2 5)
(1mul '(1 1 2 3) '(2 5)) = '(2 7 9 16 15)
So, the pattern is like what I posted at the beginning:
Multiply the first number in the list by every number in the second list (ad, ae, af) and then continue along, (bd, be, bf, cd, ce, cf) and arrange the numbers "somehow" to add the corresponding values. The reason I call it overlapping is because you can sort of visualize it like this:
(list
aa'
(+ ba' ab')
(+ ca' bb' ac')
(+ cb' bc')
cc')
Again,
(f '(a b c) '(d e f)) = '(ad (+ bd ae) (+ cd be af) (+ ce bf) cf)
However, not just for 3x3 lists, for any sized lists.
Here's my code. It's in racket
#lang racket
(define (drop n xs)
(cond [(<= n 0) xs]
[(empty? xs) '()]
[else (drop (sub1 n) (rest xs))]))
(define (take n xs)
(cond [(<= n 0) '()]
[(empty? xs) '()]
[else (cons (first xs) (take (sub1 n) (rest xs)))]))
(define (mult as bs)
(define (*- a b)
(list '* a b))
(define degree (length as))
(append
(for/list ([i (in-range 1 (+ 1 degree))])
(cons '+ (map *- (take i as) (reverse (take i bs)))))
(for/list ([i (in-range 1 degree)])
(cons '+ (map *- (drop i as) (reverse (drop i bs)))))))
The for/lists are just ways of mapping over a list of numbers and collecting the result in a list. If you need, I can reformulate it just maps.
Is this a good candidate for recursion? Not sure, but here's a
a direct translation of what you asked for.
(define (f abc def)
(let ((a (car abc)) (b (cadr abc)) (c (caddr abc))
(d (car def)) (e (cadr def)) (f (caddr def)))
(list (* a d)
(+ (* b d) (* a e))
(+ (* c d) (* b e) (* a f))
(+ (* c e) (* b f))
(* c f))))
Is it correct to assume, that you want to do this computation?
(a+b+c)*(d+e+f) = a(d+e+f) + b(d+e+f) + c(d+e+f)
= ad+ae+af + bd+be+bf + cd+ce+cf
If so, this is simple:
(define (f xs ys)
(* (apply + xs) (apply + ys))
If you are interested in the symbolic version:
#lang racket
(define (f xs ys)
(define (fx x)
(define (fxy y)
(list '* x y))
(cons '+ (map fxy ys)))
(cons '+ (map fx xs)))
And here is a test:
> (f '(a b c) '(d e f))
'(+ (+ (* a d) (* a e) (* a f))
(+ (* b d) (* b e) (* b f))
(+ (* c d) (* c e) (* c f)))