SBCL common lisp, using pmap within a loop - common-lisp

I've been recently dealing with a nested for loops in SBCL. I discovered, that operations, which can be reduced to map, can easily be made parallel using pmap (or any similar function). I decided to try and make my double for loop parallel in the following way:
Basic loops:
(loop for element in list_of_lists
do (loop for element2 in list_of_lists2
...(random_function element element2)))
And this works fine, yet I was wondering if something like:
(defun supplementary_function (single_list list_collection)
"This function iterates through list_collection and executes (random_function) on pairs obtained"
(loop for element in list_collection
do (random_function single_list element)))
(map 'nil (lambda (x) (supplementary_function x list_of_lists2)) list_of_lists1)
I would like to this for performance boost, as map in this case can easily be replaced with pmap in my case. So to clarify a bit more, the question is:
Can one replace the first loop with map, where in each map operation, second loop is executed within a special function of some sort using a single element from first loop and whole second loop. I see no conceptual mistake as to why this should not be possible, yet it throws me some memory errors (?)
Thank you very much!

Does this help?
(loop for e1 in '(1 2 3 4 5)
do (loop for e2 in '(a b c d e)
do (print (list e1 e2))))
is
(mapc (lambda (e1)
(mapc (lambda (e2)
(print (list e1 e2)))
'(a b c d e)))
'(1 2 3 4 5))
is
(defun f (e1 e2s)
(mapc (lambda (e2)
(print (list e1 e2)))
e2s))
(mapc (lambda (e1)
(f e1 '(a b c d e)))
'(1 2 3 4 5))

Related

How to shuffle list in lisp?

It's very simple program which just return the input as a list shuffled. I wrote this program in python. Now I want to convert this program to lisp code. but I couldn't. How do I write down this program in lisp?
def my_shuffle(a, b, c, d):
return [b, c, d, a]
I tried the following code but an error occur.
(defun my_shuffle (a b c d) (list b c d a))
Thee are several things here that I think that need to be pointing out. First the code that you presented is correct but do shuffle a list, present a new list of four algorithms that you pass, allways with the same order. First of all shuffle a sequence is:
generating a random permutation of a finite sequence
From wikipedia you can find several algorithms for that:
https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Also in the rosseta code there is an implementation of the knuth shuffle:
(defun nshuffle (sequence)
(loop for i from (length sequence) downto 2
do (rotatef (elt sequence (random i))
(elt sequence (1- i))))
sequence)
Then if you apply this in the repl:
CL-USER> (nshuffle (list 1 2 3 4))
(3 1 4 2)
CL-USER> (nshuffle (list 1 2 3 4))
(3 1 2 4)
Note Two different results on the same list!!! (also the same can happen, because is a random order)
In python there are build algorithms for that:
https://docs.python.org/3/library/random.html#random.shuffle
also in the Common lisp library Alexandria:
CL-USER> (ql:quickload :alexandria)
To load "alexandria":
Load 1 ASDF system:
alexandria
; Loading "alexandria"
(:ALEXANDRIA)
CL-USER> (alexandria:shuffle (list 1 2 3 4))
(3 2 4 1)
(defun my_shuffle (a b c d) (list b c d a))
The above code defines a function which will take 4 items and return a rearranged list of those 4 items. It can take input of 4 lists, 4 atoms, 4 numbers, 4 anything, but it cannot separate sublists present inside a single list.
What you can do is:
(defun my_shuffle (myList)
(list (second myList) (third myList) (fourth myList) (first myList)))
or
(defun my_shuffle (myList)
(list (cadr myList) (caddr myList) (cadddr myList) (car myList)))
or
(defun my_shuffle (myList)
(list (nth 1 myList) (nth 2 myList) (nth 3 myList) (nth 1 myList)))
car returns the first element of a list
cdr returns the tail of a list (part of the list following car of the list)
I have used combinations of car and cdr to extract the different elements of the list. Find that in your textbook.
first, second, third, fourth are relatively easy to use and do the same thing as car, cadr, caddr and cadddr
(nth x list) returns the (x+1)th item of the list, counting from zero.
So,
(nth 3 (list a b c d)) => d
(nth 0 (list a b c d)) => a
and so on.

Average using &rest in lisp

So i was asked to do a function i LISP that calculates the average of any given numbers. The way i was asked to do this was by using the &rest parameter. so i came up with this :
(defun average (a &rest b)
(cond ((null a) nil)
((null b) a)
(t (+ (car b) (average a (cdr b))))))
Now i know this is incorrect because the (cdr b) returns a list with a list inside so when i do (car b) it never returns an atom and so it never adds (+)
And that is my first question:
How can i call the CDR of a &rest parameter and get only one list instead of a list inside a list ?
Now there is other thing :
When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there.
My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
EDIT: I know the function only does the + operation, i know i have to divide by the length of the b list + 1, but since i got this error i'd like to solve it first.
(defun average (a &rest b)
; ...
)
When you call this with (average 1 2 3 4) then inside the function the symbol a will be bound to 1 and the symbol b to the proper list (2 3 4).
So, inside average, (car b) will give you the first of the rest parameters, and (cdr b) will give you the rest of the rest parameters.
But when you then recursively call (average a (cdr b)), then you call it with only two arguments, no matter how many parameters where given to the function in the first place. In our example, it's the same as (average 1 '(3 4)).
More importantly, the second argument is now a list. Thus, in the second call to average, the symbols will be bound as follows:
a = 1
b = ((3 4))
b is a list with only a single element: Another list. This is why you'll get an error when passing (car b) as argument to +.
Now there is other thing : When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there. My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
(null b) will only be truthy when b is the empty list. But when you call (average a '()), then b will be bound to (()), that is a list containing the empty list.
Solving the issue that you only pass exactly two arguments on the following calls can be done with apply: It takes the function as well as a list of parameters to call it with: (appply #'average (cons a (cdr b)))
Now tackling your original goal of writing an average function: Computing the average consists of two tasks:
Compute the sum of all elements.
Divide that with the number of all elements.
You could write your own function to recursively add all elements to solve the first part (do it!), but there's already such a function:
(+ 1 2) ; Sum of two elements
(+ 1 2 3) ; Sum of three elements
(apply #'+ '(1 2 3)) ; same as above
(apply #'+ some-list) ; Summing up all elements from some-list
Thus your average is simply
(defun average (&rest parameters)
(if parameters ; don't divide by 0 on empty list
(/ (apply #'+ parameters) (length parameters))
0))
As a final note: You shouldn't use car and cdr when working with lists. Better use the more descriptive names first and rest.
If performance is critical to you, it's probably best to fold the parameters (using reduce which might be optimized):
(defun average (&rest parameters)
(if parameters
(let ((accum
(reduce #'(lambda (state value)
(list (+ (first state) value) ;; using setf is probably even better, performance wise.
(1+ (second state))))
parameters
:initial-value (list 0 0))))
(/ (first accum) (second accum)))
0))
(Live demo)
#' is a reader macro, specifically one of the standard dispatching macro characters, and as such an abbreviation for (function ...)
Just define average*, which calls the usual average function.
(defun average* (&rest numbers)
(average numbers))
I think that Rainer Joswig's answer is pretty good advice: it's easier to first define a version that takes a simple list argument, and then define the &rest version in terms of it. This is a nice opportunity to mention spreadable arglists, though. They're a nice technique that can make your library code more convenient to use.
In most common form, the Common Lisp function apply takes a function designator and a list of arguments. You can do, for instance,
(apply 'cons '(1 2))
;;=> (1 . 2)
If you check the docs, though, apply actually accepts a spreadable arglist designator as an &rest argument. That's a list whose last element must be a list, and that represents a list of all the elements of the list except the last followed by all the elements in that final list. E.g.,
(apply 'cons 1 '(2))
;;=> (1 . 2)
because the spreadable arglist is (1 (2)), so the actual arguments (1 2). It's easy to write a utility to unspread a spreadable arglist designator:
(defun unspread-arglist (spread-arglist)
(reduce 'cons spread-arglist :from-end t))
(unspread-arglist '(1 2 3 (4 5 6)))
;;=> (1 2 3 4 5 6)
(unspread-arglist '((1 2 3)))
;;=> (1 2 3)
Now you can write an average* function that takes one of those (which, among other things, gets you the behavior, just like with apply, that you can pass a plain list):
(defun %average (args)
"Returns the average of a list of numbers."
(do ((sum 0 (+ sum (pop args)))
(length 0 (1+ length)))
((endp args) (/ sum length))))
(defun average* (&rest spreadable-arglist)
(%average (unspread-arglist spreadable-arglist)))
(float (average* 1 2 '(5 5)))
;;=> 3.25
(float (average* '(1 2 5)))
;;=> 2.66..
Now you can write average as a function that takes a &rest argument and just passes it to average*:
(defun average (&rest args)
(average* args))
(float (average 1 2 5 5))
;;=> 3.5
(float (average 1 2 5))
;;=> 2.66..

Why does the Common Lisp's apply function give a different result?

When I try this code on Emacs SLIME, the apply function gives a different result. Isn't it supposed to give the same result? Why does it give a different result? Thanks.
CL-USER> (apply #'(lambda (n)
(cons n '(b a))) '(c))
(C B A)
CL-USER> (cons '(c) '(b a))
((C) B A)
cons takes an element and a list as arguments. So (cons 'x '(a b c d)) will return (x a b c d).
apply takes a function and a list of arguments -- but the arguments will not be passed to the function as a list! They will be split and passed individually:
(apply #'+ '(1 2 3))
6
(actually, it takes one function, several arguments, of which the last must be a list -- this list will be split and treated as "the rest of the arguments to the function". try, for example, (apply #'+ 5 1 '(1 2 3)), which will return 12)
Now to your code:
The last argument you passed to the apply function is '(c), a list with one element, c. Apply will treat it as a list of arguments, so the first argument you passed to your lambda-form is c.
In the second call, you passed '(c) as first argument to cons. This is a list, which was correctly included in the first place of the resulting list: ( (c) b a).
The second call would be equivalent to the first if you did
(cons 'c '(b a))
(c b a)
And the first call would be equivalent to the second if you did
(apply #'(lambda (n) (cons n '(b a))) '((c)))
((c) b a)
CL-USER 51 > (cons '(c) '(b a))
((C) B A)
CL-USER 52 > (apply #'(lambda (n)
(cons n '(b a)))
'(c))
(C B A)
Let's use FUNCALL:
CL-USER 53 > (funcall #'(lambda (n)
(cons n '(b a)))
'(c))
((C) B A)
See also what happens when we apply a two element list:
CL-USER 54 > (apply #'(lambda (n)
(cons n '(b a)))
'(c d))
Error: #<anonymous interpreted function 40600008E4> got 2 args, wanted 1.
There is a symmetry between &rest arguments in functions and apply.
(defun function-with-rest (arg1 &rest argn)
(list arg1 argn))
(function-with-rest 1) ; ==> (1 ())
(function-with-rest 1 2) ; ==> (1 (2))
(function-with-rest 1 2 3 4 5) ; ==> (1 (2 3 4 5))
Imagine we want to take arg1 and argn and use it the same way with a function of our choice in the same manner as function-with-rest. We double the first argument and sum the rest.
(defun double-first-and-sum (arg1 &rest argn)
(apply #'+ (* arg1 2) argn))
(double-first-and-sum 1 1) ; ==> 3
(double-first-and-sum 4 5 6 7) ; ==> 26
The arguments between the function and the list of "rest" arguments are additional arguments that are always first:
(apply #'+ 1 '(2 3 4)) ; ==> (+ 1 2 3 4)
(apply #'+ 1 2 3 '(4)) ; ==> (+ 1 2 3 4)
This is very handy since often we want to add more arguments than we are passed (or else we could just have used the function apply is using in the first place. Here is something called zip:
(defun zip (&rest args)
(apply #'mapcar #'list args))
So what happens when you call it like this: (zip '(a b c) '(1 2 3))? Well args will be ((a b c) (1 2 3)) and the apply will make it become (mapcar #'list '(a b c) '(1 2 3)) which will result in ((a 1) (b 2) (c 3)). Do you see the symmetry?
Thus you could in your example you could have done this:
(apply #'(lambda (&rest n)
(cons n '(b a))) '(c))
;==> ((c) b a)
(apply #'(lambda (&rest n)
(cons n '(b a))) '(c d e))
;==> ((c d e) b a)

Common Lisp: Function that checks if element is member of list

I want to make a function that checks if an element is a member of a list. The list can contain other lists.
This is what I came with so far:
(defun subl(l)
(if (numberp l)
(if (= l 10)
(princ "Found"))
(mapcar 'subl l)))
Now the number I am searching for is hard-coded and it is 10. I would like to write it somehow so the function takes another parameter(the number I am searching for) and returns true or 1 when it finds it. The main problem is that I can't see a way to control mapcar. mapcar executes subl on each element of l, if l si a list. But how can I controll the returned values of each call?
I would like to check the return value of each subl call and if one of it is true or 1 to return true or 1 till the last recursive call. So in the end subl returns true or one if the element is contained in the list or nil otherwise.
Any idea?
This procedure below should process as you have described;
(defun member-nested (el l)"whether el is a member of l, el can be atom or cons,
l can be list of atoms or not"
(cond
((null l) nil)
((equal el (car l)) t)
((consp (car l)) (or (member-nested el (car l))
(member-nested el (cdr l))))
(t (member-nested el (cdr l)))))
mapcar is a very generic primitive to map a function over a list. You can use one of the built-in combinators which are much more closely suited with what you're trying to do. Look into the member function.
Your function seems to play the role of main function and helper at the same time. That makes your code a lot more difficult to understand than it has to be..
So imagine you split the two:
;; a predicate to check if an element is 10
(defun number10p (l)
(and (numberp l)
(= l 10)))
;; the utility function to search for 10 amongst elements
(defun sublistp (haystack)
(mapcar #'number10p haystack)))
But here when you do (sublistp '(5 10 15 20)) you'll get (nil t nil nil) back. Thats because mapcar makes a list of every result. For me it seems you are describing some since it stops at the first true value.
(defun sublistp (haystack)
(some #'number10p haystack)))
(sublistp '(5 10 15 20)) ; ==> t
Now to make it work for any data type we change the predicate and make it as a local function where we have the argument we are searching for:
(defun sublistp (needle haystack)
(flet ((needlep (x)
(equal x needle)))
(some #'needlep haystack)))
(sublistp '(a b) '(a b c (a b) d e f)) ; ==> t
You can also do this with an anonymous predicate like this:
(defun sublistp (needle haystack)
(some #'(lambda (x)
(equal x needle))
haystack))
An implementation of this is the member function, except it returns the match as truth value. That's ok since anything but nil is true in CL:
(member 10 '(5 10 15 20)) ; ==> (10 15 20)
EDIT
You commented on a different answer that you are required to use mapcar in that case use it together with append to get a list of all matches and check if the list has greater than 0 elements:
(defun sublistp (needle haystack)
(flet ((needle-check (x)
(if (equal x needle) '(t) nil)))
(< 0 (length
(apply #'append
(mapcar #'needle-check haystack))))))
How it works is that for each match you get a list of one element and for every non match you get an empty list. When appending the lists you'll get the empty list when there is not match. For all other results you have a match. This is not a very efficient implementation.

How would one interleave elements of 2 lists in LISP?

Given 2 lists, how can you produce an output of a 3rd list which has its elements as an interleaved set of L1 and L2? If they are uneven length, nil should be inserted for holes. On a second note, how can I reverse a list? I am super new to LISP and simply modifying existing code... I'd really love to have a good explanation, not just code.
First, I guess you use Common Lisp, as it is the one most used in Lisp courses. So, my examples will be in CL. If you use Scheme, you will get almost the same code. If modern Clojure, it will need some changes, through an idea will be the same.
Interleave
To interleave 2 lists you must go through both of them, collecting elements by turns. You can use loop statement or recursion for this. I'll use recursion since it has more functional style and may be used in any lisp, not only CL. Also note, that there's a feature called tail recursion, which lets you write recursive function that will be compiled to a loop.
So, base skeleton for our function will be:
(defun interleave (l1 l2)
??????
(interleave ?????))
To collect items in recursive functions you will need to return them from each call and then cons together (for a tail recursion you must have one more parameter, which will accumulate values). So, the end of the function will be (cons current-value (interleave ????)).
Also you must alternate lists to take elements from with each other. You may have additional parameter, but you also may just swap them in a recursive call. So, code becomes:
(defun interleave (l1 l2)
?????
(cons current-value (interleave l2 l1)))
Any recursion must stop somewhere. In this case, it must stop when both lists are empty (nil).
This is one condition (let give it number 1), and there are some more conditions:
2. if the list to take from is empty, and the other one is not, we must take nil instead.
3. if both lists are not empty, take first element as a current-value and proceed with it's tail.
There's only one more condition that 2 lists can be in: list to take from is not empty, and the second one is. But in fact we don't care about this and may go forward with a rule number 3.
So, the code (and this is the final one):
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
Reverse
I'll show two implementations of this function: one with cond and another with built-in reduce function which is extremely useful in practice.
First approach for cond version is to go through the all list with a recursive calls and then go back, collecting elements:
(defun reverse-1-1 (li)
(if (eql li nil)
nil
(append (reverse-1-1 (rest li))
(list (first li)))))
But this is extremely inefficient, since append is O(n), and you must pass n elements, so the final complexity is O(n^2).
To reduce it you may use one more argument to the function (and make it tail recursive, if compiler lets you):
(defun reverse-1-2 (li)
(reverse-aux li nil))
(defun reverse-aux (li accumulator)
(if (eql li nil)
accumulator
(reverse-aux (rest li) (cons (first li) accumulator))))
That's you use one more parameter to collect your elements in while passing through the list, and then just return this accumulator.
There's one more interesting option. Lisp has extremely powerful function reduce (in other functional languages it is sometimes called fold, foldr, foldl or something like that). You may find description for it here, and I'll just show an example:
(defun reverse-2 (li)
(reduce #'cons li :from-end t :initial-value nil))
:from-end tells function to go through the the list from the end, and :initial-value tells to use as the very first reduced argument nil.
Note: in some implementations reduce with option :from-end true may first reverse list by itself, so if you need to create it from scratch or use the most efficient version, use reverse-1-2 instead.
In Common Lisp:
(defun merge-lists (lst1 lst2)
(let ((m (max (length lst1) (length lst2))))
(flatten (mapcar (lambda (a b) (list a b))
(append-nulls lst1 m)
(append-nulls lst2 m)))))
Examples:
(merge-lists '(1 2 3 4) '(5 6 7 8)) ;; => (1 5 2 6 3 7 4 8)
(merge-lists '(1 2 3 4) '(5 6 7)) ;; => (1 5 2 6 3 7 4 NULL)
(merge-lists '(1 2) '(5 6 7 8)) ;; => (1 5 2 6 NULL 7 NULL 8)
The helper functions flatten and append-nulls:
(defun flatten (tree)
(let ((result '()))
(labels ((scan (item)
(if (listp item)
(map nil #'scan item)
(push item result))))
(scan tree))
(nreverse result)))
(defun append-nulls (lst n)
(if (< (length lst) n)
(dotimes (i (- n (length lst)))
(setq lst (append lst (list 'null)))))
lst)
The answer above:
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
If one of your lists is longer than the other, you will get something like (1 2 3 4 nil 5).
Replace:
((eql l1 nil) (cons nil (interleave l2 l1)))
with:
((null l1) l2)
:P
An example of a more idiomatic solution in Common Lisp:
(defun interleave (a b)
(flet ((nil-pad (list on-list)
(append list (make-list (max 0 (- (length on-list) (length list)))))))
(loop for x in (nil-pad a b)
for y in (nil-pad b a)
append (list x y))))

Resources