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))
Related
i want to write a function that accepts 2 lists as argument and return multiplication of them in a list.
like this:
(3 4) (3 5 6) => (9 15 18 12 20 24)
this is the code that i've came up with but i receive an error which is telling me that i have too few arguments for map.
(defun multip (lst lst2)
;this is a function to flatten the result
(defun flatten (tree)
(let ((result '()))
(labels ((scan (item)
(if (listp item)
(map nil #'scan item)
(push item result))))
(scan tree))
(nreverse result)))
(flatten (map (lambda (i) (map (lambda (j) (* i j)) lst )) lst2))
)
(write (multip '(3 4 6) '(3 2) ))
i can not understand what am i doing wrong. i appreciate your comment.
You don't need to flatten the list, if you create a flat list.
Use MAPCAN:
CL-USER 4 > (flet ((mult (a b)
(mapcan #'(lambda (a1)
(mapcar (lambda (b1) (* a1 b1))
b))
a)))
(mult '(3 4) '(3 5 6)))
(9 15 18 12 20 24)
You should use mapcar instead of map:
(mapcar (lambda (i) (mapcar (lambda (j) (* i j)) lst )) lst2))
These are two different functions: mapcar maps a function on one or more lists, and requires at least two arguments, while map is the equivalent but for any kind of sequences (e.g. vectors), and requires an additional argument specifying the type of the result. See the reference for map here, and the reference for mapcar here.
Style
You are using a defun inside another defun: this is not good style, since every time multip is called it redefines globally the function flatten. You should either define flatten externally, only once, or use a local declaration of function with flet or labels (as for the internal function scan inside flatten.)
For alternative and more simple definitions of flatten, you can see this question in SO.
I am not very good in Lisp and I need to do a function which allows evaluating of infix expressions. For example: (+ 2 3) -> (infixFunc 2 + 3). I tried some variants, but none of them was successful.
One of them:
(defun calcPrefInf (a b c)
(funcall b a c))
OK, let's do it just for fun. First, let's define order of precedence for operations, since when one deals with infix notation, it's necessary.
(defvar *infix-precedence* '(* / - +))
Very good. Now imagine that we have a function to-prefix that will convert infix notation to polish prefix notation so Lisp can deal with it and calculate something after all.
Let's write simple reader-macro to wrap our calls of to-prefix, for aesthetic reasons:
(set-dispatch-macro-character
#\# #\i (lambda (stream subchar arg)
(declare (ignore sub-char arg))
(car (reduce #'to-prefix
*infix-precedence*
:initial-value (read stream t nil t)))))
Now, let's write a very simple function to-prefix that will convert infix notation to prefix notation in given list for given symbol.
(defun to-prefix (lst symb)
(let ((pos (position symb lst)))
(if pos
(let ((e (subseq lst (1- pos) (+ pos 2))))
(to-prefix (rsubseq `((,(cadr e) ,(car e) ,(caddr e)))
e
lst)
symb))
lst)))
Good, good. Function rsubseq may be defined as:
(defun rsubseq (new old where &key key (test #'eql))
(labels ((r-list (rest)
(let ((it (search old rest :key key :test test)))
(if it
(append (remove-if (constantly t)
rest
:start it)
new
(r-list (nthcdr (+ it (length old))
rest)))
rest))))
(r-list where)))
Now it's time to try it!
CL-USER> #i(2 + 3 * 5)
17
CL-USER> #i(15 * 3 / 5 + 10)
19
CL-USER> #i(2 * 4 + 7 / 3)
31/3
CL-USER> #i(#i(15 + 2) * #i(1 + 1))
34
etc.
If you want it to work for composite expressions like (2 + 3 * 5 / 2.4), it's better to convert it into proper prefix expression, then evaluate it. You can find some good example of code to do such convetion here: http://www.cs.berkeley.edu/~russell/code/logic/algorithms/infix.lisp or in Piter Norvigs "Paradigs of Artificial Intelligence Programming" book. Code examples here: http://www.norvig.com/paip/macsyma.lisp
It's reall too long, to be posted in the aswer.
A different approach for "evaluating infix expressions" would be to enable infix reading directly in the Common Lisp reader using the "readable" library, and then have users use the notation. Then implement a traditional Lisp evaluator (or just evaluate directly, if you trust the user).
Assuming you have QuickLisp enabled, use:
(ql:quickload "readable")
(readable:enable-basic-curly)
Now users can enter any infix expression as {a op b op c ...}, which readable automatically maps to "(op a b c ...)". For example, if users enter:
{2 + 3}
the reader will return (+ 2 3). Now you can use:
(eval (read))
Obviously, don't use "eval" if the user might be malicious. In that case, implement a function that evaluates the values the way you want them to.
Tutorial here:
https://sourceforge.net/p/readable/wiki/Common-lisp-tutorial/
Assuming that you're using a lisp2 dialect, you need to make sure you're looking up the function you want to use in the function namespace (by using #'f of (function f). Otherwise it's being looked up in the variable namespace and cannot be used in funcall.
So having the definition:
(defun calcPrefInf (a b c)
(funcall b a c))
You can use it as:
(calcPrefInf 2 #'+ 3)
You can try http://www.cliki.net/infix.
(nfx 1 + (- x 100)) ;it's valid!
(nfx 1 + (- x (3 * 3))) ;it's ALSO valid!
(nfx 1 + (- x 3 * 3)) ;err... this can give you unexpected behavior
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.
What's the equivalent of foldr, foldl in Emacs Lisp?
If you
(require 'cl)
then you can use the Common Lisp function reduce. Pass the keyword argument :from-end t for foldr.
ELISP> (reduce #'list '(1 2 3 4))
(((1 2) 3) 4)
ELISP> (reduce #'list '(1 2 3 4) :from-end t)
(1 (2 (3 4)))
Since Emacs-24.3 we recommend the use of cl-lib over cl (which is planned for removal in some distant future), so it would be:
(require 'cl-lib)
(cl-reduce #'+ '(1 2 3 4))
and since Emacs-25, you can also use the seq package for that:
(require 'seq)
(seq-reduce #'+ '(1 2 3 4) 0)
Common Lisp library provides plenty of sequence functions like mapping, filtering, folding, searching and even sorting. CL library is shipped with Emacs by default, so you should stick to it. I however really like dash.el library, because it provides enormous amounts of functions for list and tree manipulations. It also supports anaphoric macros and encourages functional programming, which makes code concise and elegant.
Haskell's folds correspond with dash.el folds:
foldl with -reduce-from
foldr with -reduce-r-from
foldl1 with -reduce
foldr1 with -reduce-r
Sum of a range 1 to 10 using folds might look like in this in Haskell and dash.el:
foldl (+) 0 [1..10] -- Haskell
(-reduce-from '+ 0 (number-sequence 1 10)) ; Elisp
You probably know, that folds are very general, and it is possible to implement maps and filters via folds. For example, to increment every element by 2, Haskell's currying and sections would allow for terse code, but in Elisp you would usually write verbose throwaway lambdas like that:
foldr ((:) . (+2)) [] [1..10] -- Haskell
(-reduce-r-from (lambda (x acc) (cons (+ x 2) acc)) '() (number-sequence 1 10)) ; Elisp
Guess what, it isn't necessary in dash.el with anaphoric macros, which allow special syntax by exposing variables of a lambda as shortcuts, like it and acc in folds. Anaphoric functions start with 2 dashes instead of 1:
(--reduce-r-from (cons (+ it 2) acc) '() (number-sequence 1 10))
There are plenty fold-like functions in dash.el:
;; Count elements matching a predicate
(-count 'evenp '(1 2 3 4 5)) ; 2
;; Add/multiply elements of a list together
(-sum '(1 2 3 4 5)) ; 15
(-product '(1 2 3 4 5)) ; 120
;; Find the smallest and largest element
(-min '(3 1 -1 2 4)) ; -1
(-max '(-10 0 10 5)) ; 10
;; Find smallest/largest with a custom rule (anaphoric versions)
(--min-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (6)
(--max-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (1 2 3)
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