In fact, they do quite the same, but mapcar (that is a specialized form of lisp's map) seems a bit more flexible because it can deal with many lists at once (perl's map can't, at least by default).
First we start with a usual applicative programming case:
For example, generating a list with the square of each element in another list.
perl version looks like this:
my @squares = map { $_ * $_ } @mylist;
#or
map { $_ * $_ } (1..10);
lisp version. As lisp does not have the equivalent to (1..10), we can build a list builder by range :
(defun range (a b)That's the full interaction we have to do with lisp. define range function, test it, and then use mapcar. Notice that common lisp (unlike scheme) is a lisp-2, so has a namespace for variables and another for functions, so we have to provide the sharp quote, that refers to the function.
(loop for i from a to b collect i))
(range 1 10) => (1 2 3 4 5 6 7 8 9 10)
(mapcar #'(lambda (x) (* x x)) (range 1 10)) => (1 4 9 16 25 36 49 64 81 100)
So far so good.
But when things get trickier is when you want to evaluate a function that takes two parameters and you want to get the parameters from two lists.
lisp mapcar can do it by default. (nice, eh?)
(mapcar #'+ '(1 2) '(2 1)) => (3 3)Doing this in perl is not that straight, but it is possible, and you know, TIMTOWTDI:
A nice trick is doing a little mind change , and shift the point of view. You can take the index as the iterator, and get something like:
Btw, remember that if you feed 2 or more lists to map, it will append them and treat as if only one list was entered.
map { $a[$_] + $b[$_] } 0..$#a ;
There are other ways to get the map functionality, using some List::MoreUtils functions.
For example, if you only want to operate on two lists, you can use pairwise:
pairwise {$a + $b} @a , @b ;There's also each_array, that builds an iterator , and with it, you can browse N arrays step by step.
As a last hacky resort, you could use zip (or mesh, they are the same) to build a new list like (11,21,31,12,22,32....) (I hope you get what I mean) , and then use natatime.
Want more perl ways to do it? Check that stackoverflow thread.
Plenty of options, yes, I know. For me, I stick with good old map {..} 0...$#a ;
As always, thanks to #emacs-es'ers for patiently answering my Offtopic lisp questions.
And thanks to Larry for the language that makes programming -Ofun.
And remember, comments allowed, even encouraged. :-)
No hay comentarios:
Publicar un comentario