Author Topic: mapcar apply lambda  (Read 11472 times)

0 Members and 1 Guest are viewing this topic.

Bhull1985

  • Guest
Re: mapcar apply lambda
« Reply #15 on: January 07, 2014, 01:07:11 PM »
The two most recent posts in this thread contradict eachother, and my day is filled with client work again but i'm still reading best I can. Perhaps by the end of the day I can have more time to devote as the benchmarking has always interested me....nobody likes a routine that takes longer to run than someone doing the process manually :P

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: mapcar apply lambda
« Reply #16 on: January 07, 2014, 03:57:41 PM »
Excuse me if I'm wrong- just trying to gain understanding here... and I'm not, definitely not, thinking my methodology is the best here but at the moment the second example, "fixos example" seems a bit redundant with the multiple calls to mapcar and the single list. I suppose with the points being a list themselves, is this what's causing the second mapcar?

As jvillareal correctly points out, there are usually several ways to tackle a problem in AutoLISP (this is further demonstrated by the number of equivalent solutions offered in the many 'challenge' threads here at the Swamp).

As for the performance: it is true that the solution using mapcar is performing two redundant addition operations since the following mapcar expression:
Code - Auto/Visual Lisp: [Select]
  1. (mapcar '(lambda ( x ) (mapcar '+ x '(0 0 12))) '((1 2 3) (4 5 6) (7 8 9)))
Is performing the following operations on each item 'x' of the list:
Code - Auto/Visual Lisp: [Select]
  1. (
  2.     ((+ 1 0) (+ 2 0) (+ 3 12))
  3.     ((+ 4 0) (+ 5 0) (+ 6 12))
  4.     ((+ 7 0) (+ 8 0) (+ 9 12))
  5. )
Also, memory must be allocated for the second list argument supplied to mapcar for each iteration - therefore, although this solution is perhaps more concise and maybe more readable, the above reasons could make this inefficient.

However, consider that in the alternative solution:
Code - Auto/Visual Lisp: [Select]
  1. (mapcar '(lambda ( x ) (list (car x) (cadr x) (+ (caddr x) 12))) '((1 2 3) (4 5 6) (7 8 9)))
We have the overhead of evaluating the list function to construct a new list, followed by evaluation of the car, cadr & caddr functions independently of each other to access the first three items of the list, before the addition is performed and the new list returned.

Here is a quick benchmark:
Code - Auto/Visual Lisp: [Select]
  1. _$ (setq l '((0 1 2) (3 4 5)))
  2. ((0 1 2) (3 4 5))
  3. _$ (repeat 8 (setq l (append l l)))
  4. ((0 1 2) (3 4 5) ...  (3 4 5))
  5. _$ (length l)
  6. 512
  7. _$ (defun f1 ( l ) (mapcar '(lambda ( x ) (mapcar '+ x '(0 0 12))) l))
  8. F1
  9. _$ (defun f2 ( l ) (mapcar '(lambda ( x ) (list (car x) (cadr x) (+ (caddr x) 12))) l))
  10. F2
  11. _$ (defun f3 ( l ) (mapcar '(lambda ( x ) (reverse (cons (+ (caddr x) 12) (cdr (reverse x))))) l))
  12. F3
  13. _$ (equal (f1 l) (f2 l))
  14. T
  15. _$ (equal (f1 l) (f3 l))
  16. T
  17. _$ (benchmark '((f1 l) (f2 l) (f3 l)))
  18. Benchmarking .............Elapsed milliseconds / relative speed for 1024 iteration(s):
  19.  
  20.     (F2 L).....1108 / 2.84 <fastest>
  21.     (F3 L).....1326 / 2.38
  22.     (F1 L).....3151 / 1.00 <slowest>

adalea03

  • Guest
Re: mapcar apply lambda
« Reply #17 on: January 07, 2014, 08:48:58 PM »
Fixo
Your first post was an inspiration.

Bhull1985

  • Guest
Re: mapcar apply lambda
« Reply #18 on: January 08, 2014, 07:43:54 AM »
Very interesting.
So, taking away from this....
construct a mapcar statement logically based on which functions needed to operate on which list, but all elements of that list.
Function can be a primitive such as '+ '- '* '/ a subfunction defined elsewhere or an anonymous function calling lambda (typically when the only call to that function is within the mapcar statement itself).
Lambda accomplishes any task in a very similar manner as (defun) except it's usually a helper function, being as such it does not have it's own command to call nor does it require any additional memory usage once the task has been completed.
Lambda will be used typically when a list or an item must be processed in an unstandard manner, when there is no autolisp function or call that would in one step accomplish the same task.
Examples are given above, well, one in specific but it bears repeating just for clarity's sake....
For instance, adding 12 inches elevation to a set of points. There's no autocad function or command that operates on the z coordinates only of points, unless we're in the properties window. Well, that's why a lambda was used.



So both of these functions are used in necessity, typically only when the conditions for firing them off aren't met elsewhere. Mapcar expects a function and a list every time, and as such hopefully some others without a full understanding are starting to gain one- powerful stuff , here. Lists are one of the most extensively used data types that I see from day to day and it's no surprise that a programmer would want to construct a list and then perform operations on it. Something as simple as
Code: [Select]

(setq nameslist (list "Brandon" "carrie" "john" "frank" "tod" "bill"
"Shannon"))
("Brandon" "carrie" "john" "frank" "tod" "bill" "Shannon")

Command: (mapcar
(_> 'strcase
(_> nameslist
(_> )
("BRANDON" "CARRIE" "JOHN" "FRANK" "TOD" "BILL" "SHANNON")

Is an effective way to showcase the more basic capabilities of mapcar, although indeed on a very rudimentary level.
This function, along with all of your posts and assistance (and fixos curveball, totally worth the discussion) have really made mapcar appear as a tame animal, not so difficult once your head is wrapped around the basics...... the real wild thing is lambda, and i'm fine with that. Constructing on-the-fly functions that have no real use outside of the defun itself are pretty advanced programming, imo, and I look forward to a day where I can use them as fluently as pbejse and/or leemac. No offense others but I frequently see these two using and abusing lambda to spread joy to nerds in need everywhere. 
I won't press too hard right now to fully understand the most apt uses of lambda but even a few easier functions that at least allow some comprehension and when/where a lambda might be useful seem the most correct steps to take at the moment, much in the same way that mapcar was approached in this thread.
Another time, as client work beckons

Fixo, Lee, Rhino, mailmaverick, Gile, jvillareal---much obliged. This was a big step.
« Last Edit: January 08, 2014, 07:50:38 AM by Bhull1985 »

Bhull1985

  • Guest
Re: mapcar apply lambda
« Reply #19 on: January 08, 2014, 07:59:22 AM »
Two more quick things:

Fixo
Your first post was an inspiration.

Thanks for joining the discussion....


And as far as the benchmarking results, if I'm reading those correctly then the most direct method is the quickest. I say most direct because I don't believe it's mere chance that has me understanding car, caddr, list, and the primitives in order to construct this statement. Much more experience must be known in order to approach such a task, and have the foresight to realize that there are multiple ways to accomplish the task.....no, see, me as a fledgling, there was just one way, and I was directly going about it. It's just interesting that it would be the most direct in relation to speed (efficiency) as well. On that note, whenever I see (reverse) and (cons) in the same statement, my eyes glaze over. Although, even that i'm beginning to get a feel for. If an item is appended to a list or if two items are made into a list typically the most recent item added would be placed at the bottom of the list, a call to (reverse) gives this the order of newest-to-oldest. Simple enough, maybe i'll need to spend some time with those too.

Ah the neverending world of lisp, limitless and useful knowledge with a company of designers and drafters to be my guinea pigs, but oh did I mention the joy that a steady stream of learning can give to someone who seeks to challenge themselves, typically bored crazy with what others would find "challenging". It's nice to be able to speak with like minded individuals, with no pretenses other than the code itself that we all wrap around us, making ourselves important, lining our bank accounts (hopefully!)
I appreciate each and every post and discussion I can read or take a part of, just saying....it all culminates into something quite nice, and i'm finding these skills are highly desirable and incredibly rare! And I thank you for allowing me to spread my wings and learn more, each and every day.
« Last Edit: January 08, 2014, 08:02:43 AM by Bhull1985 »

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: mapcar apply lambda
« Reply #20 on: January 09, 2014, 06:28:46 PM »
It's nice to be able to speak with like minded individuals, with no pretenses other than the code itself that we all wrap around us

It's what the Swamp is all about and what makes this such a great place to visit  :-)