Author Topic: mapcar help  (Read 6137 times)

0 Members and 1 Guest are viewing this topic.

rhino

  • Guest
mapcar help
« on: January 02, 2014, 05:44:27 AM »
Hi All,

This snippet:
Code - Text: [Select]
  1. (mapcar '+ '(0.0 200.0 0.0) p1)
will add 200 to a point list p1.

How do I apply this to each item in a list with multiple points.

I tried:
Code - Text: [Select]
  1. (foreach n dplist (mapcar '+ '(0.0 200.0 0.0) n))
but that will return a list with the last point only by applying mapcar

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: mapcar help
« Reply #1 on: January 02, 2014, 06:21:11 AM »
Code - Auto/Visual Lisp: [Select]
  1.   '(lambda (dp)
  2.     (mapcar '+ '(0.0 200.0 0.0) dp)
  3.   )
  4.   dplist
  5. )

rhino

  • Guest
Re: mapcar help
« Reply #2 on: January 02, 2014, 07:10:10 AM »
Thanks Roy! I was trying lambda but not by doubling the mapcar - this makes sense though hehe  ^-^

Bhull1985

  • Guest
Re: mapcar help
« Reply #3 on: January 02, 2014, 08:20:29 AM »
Roy would you mind to comment each line out there in what's happening, for newbies like me who wish to further their understanding of mapcar
(and eventually be able to use it constructively within code!)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: mapcar help
« Reply #5 on: January 02, 2014, 09:10:35 AM »
While you are studying you may find this useful as well.
-------------  LISP  Logic  -----------------
http://www.theswamp.org/index.php?topic=13046.msg158557#msg158557  by CAB
http://www.cadtutor.net/forum/showthread.php?52365-localizing-variables

I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: mapcar help
« Reply #6 on: January 02, 2014, 09:26:39 AM »
Thank you CAB!

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: mapcar help
« Reply #7 on: January 02, 2014, 09:41:17 AM »
You're quite welcome.  8)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Bhull1985

  • Guest
Re: mapcar help
« Reply #8 on: January 02, 2014, 01:03:42 PM »
I have read most of the longer mapcar and lambda references that reside on this board indeed :)
The ones that come to mind just from memory are irneb and lee mac, they established a good basis in understanding the functions but I still have yet to learn how to properly apply them, and as thus I hassle more experienced lispers to explain what they're doing in hopes of gaining that knowledge.
However, instead of perusing the boards I'll spend some time with what you've linked, maybe there's something I haven't seen :D
Thank you both, regardless!!

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: mapcar help
« Reply #9 on: January 02, 2014, 01:56:45 PM »
IMO, the key way to think about how to apply mapcar/lambda is to think about exactly what you want to do with each list item - when you know the function that is to be applied to each item, you can simply pass this function to mapcar to evaluate it on all items in the list.

In this particular case, we already know the operation that is to be applied to each item:
Code: [Select]
(mapcar '+ '(0.0 200.0 0.0) <list-item>)
And so we can construct a function to perform this operation either using defun or lambda:
Code: [Select]
(defun myfunction ( x )
    (mapcar '+ '(0.0 200.0 0.0) x)
)
Code: [Select]
(lambda ( x ) (mapcar '+ '(0.0 200.0 0.0) x))Think of the lambda function simply as a function defined without a function name - an anonymous function.

Each of the above functions require a single argument 'x' (the list item) and will perform the required operation on this item and return the result of the operation.

Now to apply this function on all list items (and return the results), it becomes a simple case of supplying the function to mapcar:
Code: [Select]
(mapcar 'myfunction <list>)
Code: [Select]
(mapcar '(lambda ( x ) (mapcar '+ '(0.0 200.0 0.0) x)) <list>)
To understand why the function has been quoted, see this tutorial.

Lee

rhino

  • Guest
Re: mapcar help
« Reply #10 on: January 02, 2014, 02:04:05 PM »
Hi Bhull1985,

The really great thing with AutoLISP is that you can test out the functions and methods directly in VLIDE using the visual lisp console.

I couldn't wrap my head around mapcar or lambda too - in spite of reading through those tutorial; I would just go huh! :ugly:

But here's how I came up with the first function:
Code - Text: [Select]
  1. (mapcar '+ '(0.0 200.0 0.0) p1)
I got this by reapplying the logic in the below example from http://www.lee-mac.com/mapcarlambda.html:
Quote
Code - Text: [Select]
  1. (mapcar '+ '(1 2 3 4 5) '(3 4 5 6 7))
  2. (4 6 8 10 12)
Here mapcar is supplied with the + function, which takes any number of numerical arguments and adds them together. Hence in the above example, mapcar will evaluate the + function on each member of each list and return a list of the results:
Code - Text: [Select]
  1. (4 6 8 10 12) = ((+ 1 3) (+ 2 4) (+ 3 5) (+ 4 6) (+ 5 7))

so effectively the first mapcar line is a function to add to a supplied list. edit: list with one point

just before roy could post the solution I was reading and trying to apply this logic as per CAB's explainationhttp://www.theswamp.org/index.php?topic=340.0:

Quote
mapcar is a specialized foreach function
defined as
(mapcar function list1... listn)
Quote
Lambda: defined as
(lambda arguments expr...)
Code - Auto/Visual Lisp: [Select]
  1. (setq counter 0)
  2. (mapcar '(lambda (x)  
  3.           (setq counter (1+ counter))  
  4.           (* x 5)  
  5.         )  
  6.         '(2 4 -6 10.2)  
  7. )
mapcar feeds each value from the list (2 4 -6 10.2) to x then collects the return values in a list
the (setq counter (1+ counter)) counts the number of times the lambda was executed which will be 4
  this also illustrates that more than one line of code may be used within the lambda function
the ' symbol could be replaced with (function and would perform better (faster).
the (* x 5) process the x variable as follows
  (* 2 5)  10
  (* 4 5)  20
  (* -6 5) -30
  (* 10.2 5) 51
so it return
   (10 20 -30 51.0)

which is what is happening with the code roy posted:
Code - Auto/Visual Lisp: [Select]
  1. ;apply function on multiple entities in a list
  2.      '(lambda (dp) ;;dp is the each item in the list
  3.        (mapcar '+ '(0.0 200.0 0.0) dp) ;;function
  4.      )
  5.      dplist ;;main list to apply the function
  6.     )

Hope that helps you out and happy coding!
« Last Edit: January 02, 2014, 02:07:12 PM by rhino »

Bhull1985

  • Guest
Re: mapcar help
« Reply #11 on: January 02, 2014, 03:36:09 PM »
Alright thanks guys, really delved into this one this afternoon.
Even reached a gem from MIT :
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.6
Exercice 1.3, therin, was fun to do.
Simply
Quote
Exercise 1.3.  Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
MIT so, no answers, this is what I came up with
Code: [Select]
(defun summed ( x1 x2 x3 / n1 n2 data)
(setq n1 (if (> x1 x2)
                 (* x1 x1)
                 (* x2 x2)
             );if
);setq
(setq n2 (if (> x1 x3)
                 (* x1 x1)
                 (* x3 x3)
             );if
);setq
(setq data (+ n1 n2))
)
Quick paste into cad and i'm pleasantly being returned these:
Quote
(_> (setq data (+ n1 n2)))
SUMMED
Command: (summed 1 2 3)
13
Command: (summed 2 4 3)
25

But alas, that's not mapcar, nor lambda. However, I did learn a crucial fact in understanding these that is often not touched on, I suppose it's one of those "taken for granted" or "should be fundamentally understood". That said, and being self-taught, I missed out until now on the fact that the original list is always within the mapcar statement, in fact it's the second argument so it has to be. Function to be applied to the list being the first. If the list is given in '(L I T E R A L) form or given as a variable1 has no affect on the function that is being applied to the list.
This is where I have to force myself to be careful. It won't be simple addition that a mapcar is accomplishing, as per 95% of the examples given with it. I understand the need for simplicity but it's confusing in it's own right :P
I'll have to take them symbolically in order to interchange the arithmetic with useful programming skills, for instance
Code: [Select]
(setq pt1 '(1.5 2.5 3.5))
(setq pt2 '(2.0 3.0 4.0))
(setq pt3 '(3.5 4.5 5.5))
(setq lst '(pt1 pt2 pt3) )

(defun getx ( pt /)
(if pt
(princ (car pt))
)
(princ)
)

(mapcar
'(lambda ( pt ) (if pt (princ (car pt)))
lst
)
Fails. Miserably. I thought that would work, when substituting lambda for the function that works if I do it (getx pt1) with those points defined.
Bah, need a short break, few hrs of this and an error. Try more soon..

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: mapcar help
« Reply #12 on: January 02, 2014, 04:01:52 PM »
Quote
Exercise 1.3.  Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
MIT so, no answers, this is what I came up with
Code: [Select]
(defun summed ( x1 x2 x3 / n1 n2 data)
(setq n1 (if (> x1 x2)
                 (* x1 x1)
                 (* x2 x2)
             );if
);setq
(setq n2 (if (> x1 x3)
                 (* x1 x1)
                 (* x3 x3)
             );if
);setq
(setq data (+ n1 n2))
)

Careful... observe:
Code: [Select]
_$ (summed 1 2 3)
13
_$ (summed 3 2 1)
18

Here's one possible way to tackle it (using mapcar):
Code: [Select]
(defun sumsqr ( x y z / l )
    (setq l (list x y z)
          l (mapcar '* l l)
    )
    (apply 'max (mapcar '+ (cons (last l) l) l))
)

I'll have to take them symbolically in order to interchange the arithmetic with useful programming skills, for instance
Code: [Select]
(setq pt1 '(1.5 2.5 3.5))
(setq pt2 '(2.0 3.0 4.0))
(setq pt3 '(3.5 4.5 5.5))
(setq lst '(pt1 pt2 pt3) )

(defun getx ( pt /)
(if pt
(princ (car pt))
)
(princ)
)

(mapcar
'(lambda ( pt ) (if pt (princ (car pt)))
lst
)
Fails. Miserably. I thought that would work, when substituting lambda for the function that works if I do it (getx pt1) with those points defined.

Here's your problem:
Code: [Select]
(setq lst '(pt1 pt2 pt3))
See this section of my tutorial.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: mapcar help
« Reply #13 on: January 02, 2014, 04:02:03 PM »
How about a picture  :)
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: mapcar help
« Reply #14 on: January 02, 2014, 04:09:28 PM »
Excellent diagram CAB  :-)