Author Topic: Apply  (Read 3610 times)

0 Members and 1 Guest are viewing this topic.

daron

  • Guest
Apply
« on: February 05, 2004, 05:08:09 PM »
I'm wondering if you guys would expound on the apply function a bit for me. I've seen it used, but not too often and it seems that the functions it's applying itself to is just a redundancy. The help file shows this:
(apply '+ '(1 2 3))
6

and

(apply 'strcat '("a" "b" "c"))
"abc"

Why would you even use apply, when (+ 1 2 3) will return 6 all the same and (strcat "a" "b" "c") will return "abc" equally? There has to be more to this function than meets the eye.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Apply
« Reply #1 on: February 05, 2004, 07:12:30 PM »
If you want to add a list of numbers and don't know how many will
be in the list.

Code: [Select]
 (setq lst (list 1 2 3 4 5 6))
  (apply '+ lst)


This way the lst could contain any  number of items
and the sum will result.

You can not do (+ lst)
You could do
Code: [Select]
(foreach num lst
  (setq total (+ num total))
)


Did I get close? :)
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.

Matt Stachoni

  • Guest
Apply
« Reply #2 on: February 05, 2004, 07:33:55 PM »
Daron,

(apply) is actually a really neat core function of AutoLISP. To really get the hang of it you need to make extensive use of lists in your programing, and think in those terms when creating your code and data structures. The more flexible you are with lists, the more you can find ways of using them in all sorts of ways.

The first thing to understand about a function like apply is that it works on a list as an argument, doing something with each element - this is really handy. Functions like (append) and (mapcar) work on and return a list. Combined together and especially with (lambda), you have a powerful way of crunching through complex lists with ease. The Customization manual give the lame (apply '+ '(1 2 3 4)) because it's easy to understand, but doesn't give you a feel for how to tap into the power of the function.

For example, take the code I posted for removing an element from a list:
Code: [Select]
(defun list:Remove (e l)
  (apply 'append (subst nil (list e) (mapcar 'list l)))
)
You feed the function an element (e) and a list. Using longhand programing you could do a (foreach....) type deal, but is that the most elegant solution? If you have a list to start with, and you want a list to end up with, chances are the best thing is to see how mapcar and apply can work together.

So, looking into how this works, let's say you do (list:Remove 3 '(1 2 3 4 5)), which returns '(1 2 4 5). Examining what happens inside the routine, start at the inner expressions and work outward:
(mapcar 'list l) returns '((1) (2) (3) (4) (5)). A simple (subst nil (list e) (mapcar 'list l)) returns '((1) (2) nil (4) (5)).

Remember that the apply function supplies another function with a list of arguments; the append function can take any number of separate lists as arguments and string them together into a single list, such that these two expressions are logically equivalent:

(append '(1) '(2) nil '(4) '(5)) <==>  (apply 'append '((1) (2) nil (4) (5))).
-Both return '(1 2 4 5).

However, the left hand version is a lot tougher to deal with normally because we would have to supply each tiny list argument in turn; in the (apply) case, we just need a single list. When you are automatically generating lists through various means, this is not a trivial consideration.

Remember that nil is considered a list type, so the (apply) function works especially well here to reassemble a single list without the nil part.

daron

  • Guest
Apply
« Reply #3 on: February 06, 2004, 12:16:38 AM »
Thank you both. Matt, I had that function in mind when I was thinking about it.