A newcomer to Lisp. I know that
(mapcar #'list '(1 2) '(3 4))
will give
'((1 3) (2 4))
and based on my understanding of how apply works, I expect
(apply #'(lambda (&rest x) (mapcar #'list x)) '((1 2) (3 4)))
to return the same result. Instead, I am getting
'(((1 2)) ((3 4)))
I am confused because
(apply #'append '((1 2) (3 4)))
gives me
'(1 2 3 4)
as expected. What is going on?
Simplify it. Suppose you used A instead of (1 2), and B instead of (3 4):
(apply #'(lambda (&rest x) (mapcar #'list x)) '(A B))
Because &rest x takes all the arguments and packs them up as a list, so x has the value
(A B).
Then mapcar iterates twice, passing A to list, producing (A), then it does the same with B. Then mapcar makes a list of those, producing ( (A) (B) )
It's useful to put print statements in there to see what's going on.
Related
I have something like this
(map (lambda (l) (apply + l)) '('(1 2) '(3 4)))
I expect '(3 7), however I get an error saying that the applied function gets applied to a quote.
Why does this happen?
The list I had was equivalent to
(list (quote (list 1 2)) (quote (list 3 4)))
and not
(list (list 1 2) (list 3 4))
The list was malformed. For the difference between list and quote see this post: What is the difference between quote and list?.
A proper way to do nested loop is like '((1 2) (3 4)).
How to convert a flat list into an arbitrarily complex tree-like structure? First, a simple example, convert '(1 2 3 4) into '(1 (2 (3 (4)))). I know how to do it with classical recursion:
(defun nestify (xs)
(if (null xs)
(list)
(list (car xs) (nestify (cdr xs)))))
Now, what if the nested structure is arbitrarily complex? For example, I want to convert '(1 2 3 4 5 6 7 8) into '(1 (2 3) (4 (5 6) 7) 8). How can I write a general function that is able to convert a flat list in any such nested structure? I can think of giving a template with dummy values. For example:
* (nestify '(1 2 3 4 5 6 7 8) '(t (t t) (t (t t) t) t))
'(1 (2 3) (4 (5 6) 7) 8)
My first attempt using recursion and custom tree size finding function:
(defun length* (tr)
"Count number of elements in a tree."
(cond ((null tr) 0)
((atom tr) 1)
(t (+ (length* (car tr))
(length* (cdr tr))))))
(defun tree-substitute (xs tpl)
"(tree-substitute '(1 2 3) '(t (t) t)) -> '(1 (2) 3)"
(cond ((null tpl) nil)
((atom (car tpl))
(cons (car xs) (tree (cdr xs) (cdr tpl))))
(t (cons (tree xs (car tpl))
(tree (nthcdr (length* (car tpl)) xs) (cdr tpl))))))
Is there any way to do this better, in a more elegant and concise way? For example, the function converting a list into a tree might not use the template, although I can't think of the method. Can I abstract away recursion and other details and have a neat reduce or some other high-level function?
Turning (1 2 3 4) into (1 (2 (3 (4)))) actually isn't quite as simple as you might hope, if you're using reduce. You need to specify :from-end t if you want to process 4 first, and the reduction function is either called with 3 and 4, if no :initial-value is specified, or with 4 and the initial value, if one is. That means you can use something like this, where the function checks for the special initial case:
(reduce (lambda (x y)
(if y
(list x y)
(list x)))
'(1 2 3 4)
:from-end t
:initial-value nil)
;=> (1 (2 (3 (4))))
A solution that involves a template is much more interesting, in my opinion. It's easy enough to define a maptree function that maps a function over a tree and returns a new tree with the function results:
(defun maptree (function tree)
"Return a tree with the same structure as TREE, but
whose elements are the result of calling FUNCTION with
the element from TREE. Because TREE is treated as an
arbitrarily nested structure, any occurrence of NIL is
treated as an empty tree."
(cond
((null tree) tree)
((atom tree) (funcall function tree))
((cons (maptree function (car tree))
(maptree function (cdr tree))))))
(maptree '1+ '(1 2 (3 (4 5)) (6 7)))
;=> (2 3 (4 (5 6)) (7 8))
Given the maptree function, it's not hard to call it with a function that provides an element from a list of elements, until that list of element is exhausted. This provides a definition of substitute-into:
(defun substitute-into (items tree)
"Return a tree like TREE, but in which the elements
of TREE are replaced with elements drawn from ITEMS.
If there are more elements in TREE than there are in
ITEMS, the original elements of TREE remain in the result,
but a new tree structure is still constructed."
(maptree #'(lambda (x)
(if (endp items) x
(pop items)))
tree))
(substitute-into '(1 2 3 4 5) '(t (u (v)) (w x)))
;=> (1 (2 (3)) (4 5))
(substitute-into '(1 2 3 4 5) '(t u (v w x) y z))
;=> (1 2 (3 4 5) Y Z)
See Also
The maptree above is actually just a special case of a more general reduce, or fold, function for trees. Have a look at Using reduce over a tree in Lisp for some more information about how you can fold over trees. In this case, you could use my tree-reduce function from my answer to that question:
(defun tree-reduce (node-fn leaf-fn tree)
(if (consp tree)
(funcall node-fn
(tree-reduce node-fn leaf-fn (car tree))
(tree-reduce node-fn leaf-fn (cdr tree)))
(funcall leaf-fn
tree)))
and define maptree in terms of it:
(defun maptree (function tree)
(tree-reduce 'cons function tree))
My attempt:
(defun mimicry (source pattern)
(labels ((rec (pattern)
(mapcar (lambda (x)
(if (atom x)
(pop source)
(rec x)))
pattern)))
(rec pattern)))
Test:
CL-USER> (mimicry '(1 2 3 4 5) '(t (u (v)) (w x)))
(1 (2 (3)) (4 5))
I'm using R5RS (in racket). Here is my example
(map (lambda (x) (list (apply + x) (apply * x))) '((1 2 3) (4 5 6)))
-> ((6 6) (15 120))
I was just wondering that if there's a built-in function like this
(map-apply '(+ *) '((1 2 3) (4 5 6)))
which could produce the same result.
Nothing built-in, but you can write your own:
(define (map-apply funcs items)
(map (lambda (item)
(map (lambda (func)
(apply func item))
funcs))
items))
You'd have to pass in (list + *), not '(+ *), however.
If you are doing these kinds of things often you can abstract the production of the map-function. Thus the rest will be unchanged:
;; Makes a function that applies all functions to an argument
(define (make-map-fun . funs)
(lambda (lis)
(map (lambda (fun) (apply fun lis)) funs)))
(map (make-map-fun + *) '((1 2 3) (4 5 6)))
; ==> ((6 6) (15 120))
;; And you can zip with it too
(apply map
(lambda l ((make-map-fun + *) l))
'((1 2 3) (4 5 6) (7 8 9)))
; ==> ((12 28) (15 80) (18 162))
Are you still there +firegun? If you really, really need to pass the function arguments as '(+ *) then your solution would be:
(define (map-apply function-names items)
(let ((funcs (map (lambda (name) (eval name (interaction-environment))) function-names)))
(map (lambda (item)
(map (lambda (func)
(apply func item))
funcs))
items)))
In common lisp I can do this:
(mapcar #'cons '(1 2 3) '(a b c))
=> ((1 . A) (2 . B) (3 . C))
How do I do the same thing in elisp? When I try, I get an error:
(wrong-number-of-arguments mapcar 3)
If elisp's mapcar can only work on one list at a time, what is the idomatic way to combine two lists into an alist?
You want mapcar*, which accepts one or more sequences (not just lists as in Common Lisp), and for one sequence argument works just like the regular mapcar.
(mapcar* #'cons '(1 2 3) '(a b c))
((1 . A) (2 . B) (3 . C))
And even if it weren’t defined, you could easily roll your own:
(defun mapcar* (f &rest xs)
"MAPCAR for multiple sequences"
(if (not (memq nil xs))
(cons (apply f (mapcar 'car xs))
(apply 'mapcar* f (mapcar 'cdr xs)))))
Emacs has built-in Common Lisp library, which introduces plenty of Common Lisp functions and macros, but with the cl- prefix. There is no reason to avoid this library. cl-mapcar is what you want:
(cl-mapcar '+ '(1 2 3) '(10 20 30)) ; (11 22 33)
With dash list manipulation library (see the installation instructions), you can use -zip-with (remember: -zip-with is the same as cl-mapcar applied to 2 lists):
(-zip-with '+ '(1 2 3) '(10 20 30)) ; (11 22 33)
I don't know an elegant way to implement a -zip-with equivalent for 3 arguments. But you may use -partial from dash-functional package, which comes with dash (functions from dash-functional require Emacs 24). -partial partially applies the function, so these 2 function invocations below are equivalent:
(-zip-with '+ '(1 2) '(10 20)) ; (11 22)
(funcall (-partial '-zip-with '+) '(1 2) '(10 20)) ; (11 22)
Then, you can use it with a -reduce function:
(-reduce (-partial '-zip-with '+) '((1 2 3) (10 20 30) (100 200 300)))
; (111 222 333)
You can wrap it into a function with &rest keyword, so this function would accept varying amount of arguments instead of a list:
(defun -map* (&rest lists)
(-reduce (-partial 'zip-with '+) lists))
The following Emacs Lisp function takes a list of lists and returns a list in which the items of the inner lists have been concatenated to one big list. It is pretty straight-forward and I am convinced something like this must already be part of the standard function library.
(defun flatten (LIST)
(if LIST
(append (car LIST) (flatten (cdr LIST)))
nil))
I am looking for a function that will take a single list of lists as its argument and then append all the inner lists.
(flatten '((a b) (c d)))
will give
(a b c d)
Does anyone know whether this function is already built in, and if so, under which name?
Thanks!
You're either looking for append:
(defun flatten (list-of-lists)
(apply #'append list-of-lists))
If (and only if) you know that you'll always have a list of lists.
Otherwise:
(defun flatten (list)
(mapcan (lambda (x) (if (listp x) x nil)) list))
Emacs 27.1 has flatten-tree:
(flatten-tree '((a b) (c d)))
(a b c d)
See: https://www.gnu.org/software/emacs/manual/html_node/elisp/Building-Lists.html
I stepped into this only recently whilst looking for something different; there is something that might not have been put into evidence by the test data utilized to check the function, depending on whether the original question was meant to refer to generic lists (i.e.: list of list of list of list of...) or just to two-level lists (as in the example).
The solution based on append works fine only with two-level lists, and there is a further issue with the solution based on mapcan.
Basically, the general solution has to be recursive both on car and cdr, as in the flatten defun below.
(setq l '((((1 2) 3) 4) (5 6 7)))
(defun flatten(x)
(cond ((null x) nil)
((listp x) (append (flatten (car x)) (flatten (cdr x))))
(t (list x))))
(defun flatten2(l)
(if l (append (car l) (flatten2 (cdr l))) nil))
(defun flatten3(l)
(mapcan (lambda(x) (if (listp x) x nil)) l))
(flatten l)
(1 2 3 4 5 6 7)
(apply #'append l)
(((1 2) 3) 4 5 6 7)
(flatten2 l)
(((1 2) 3) 4 5 6 7)
The further issue is with the usage of mapcan in flatten3: as mapcan hides an nconc inside, the user must remember that it alters its argument.
l
((((1 2) 3) 4) (5 6 7))
(flatten3 l)
(((1 2) 3) 4 5 6 7)
l
((((1 2) 3) 4 5 6 7) (5 6 7))
Dash is a modern list library for Emacs, and has flatten. It's the second most downloaded package on Melpa, after magit. From the readme:
-flatten (l): Takes a nested list l and returns its contents as a single, flat list.
(-flatten '((1))) ;; => '(1)
(-flatten '((1 (2 3) (((4 (5))))))) ;; => '(1 2 3 4 5)
(-flatten '(1 2 (3 . 4))) ;; => '(1 2 (3 . 4))
-flatten-n (num list): Flatten num levels of a nested list.
(-flatten-n 1 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 (3 4) ((5 6)))
(-flatten-n 2 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 (5 6))
(-flatten-n 3 '((1 2) ((3 4) ((5 6))))) ;; => '(1 2 3 4 5 6)
This package was started 2012-09.
I realize that the original question was "what is the built in function". It appears that there is none. The other solutions do not actually flatten all lists that I tested. This function appears to work. I'm posting it here because this was the first place Google hit when I did my search.
(defun flatten (LIST)
"flattens LIST"
(cond
((atom LIST) (list LIST))
((null (cdr LIST)) (flatten (car LIST)))
(t (append (flatten (car LIST)) (flatten (cdr LIST))))))
e.g.
(flatten (list "a" (list "b" "c" nil) (list (list "d" "e") "f")))
("a" "b" "c" nil "d" "e" "f")
Have a look at nconc