TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: daron on October 27, 2004, 02:06:52 PM

Title: Better than mapcar???
Post by: daron on October 27, 2004, 02:06:52 PM
What would you guys say? I stumbled across this and it hit me. Mapcar REQUIRES that all lists be of equal length. Vl-every seems to do the same thing as mapcar, EXCEPT it will take the shortest list and run only that number of times while processing all lists.
Quote from: Acad Help File
Compare the results of the following expressions:

_$ (vl-every '= '(1 2) '(1 3))

nil
_$ (vl-every '= '(1 2) '(1 2 3))

T
The first expression returned nil because vl-every compared the second element in each list and they were not numerically equal. The second expression returned T because vl-every stopped comparing elements after it had processed all the elements in the shorter list (1 2), at which point the lists were numerically equal. If the end of a list is reached, vl-every returns a non-nil value.
Title: Better than mapcar???
Post by: David Bethel on October 27, 2004, 02:21:55 PM
I would say that is very dangerous.  I use equal to comapre lists ( with a fuzz )

Quote
_$ (vl-every '= '(1 2) '(1 2 3))

T


It is not good that an obiviously not true test returns T

-David
Title: Better than mapcar???
Post by: MP on October 27, 2004, 03:05:11 PM
[friendlies on]

(Opinion) ..

I agree with David, and to add, mapcar does not require lists of equal lengths. Also, there is not straight substition for mapcar w/vl-every given the contect you provided:

Code: [Select]
(apply 'and (mapcar 'eq '(1 2) '(1 3)))
nil

(apply 'and (mapcar 'eq '(1 2) '(1 2)))
T

(apply 'and (mapcar 'eq '(1 2) '(1 2 3)))
T
(dangerous implications)

Finally, the intent of vl-every is to terminate the evalution of list(s) as soon as one of the members of the list(s) returns a nil result of the predicate function. This way it doesn't superfluously evalute beyond that point. In that contect it blows mapcar away, as mapcar will evaluate every item.

Code: [Select]
;;  contrived example, determine if all members are 9

(vl-every
   '(lambda (x)
        (print x)
        (eq 9 x)
    )
   '(9 8 7 6 5 4 3 2 1)
)

;;  output

9
8 nil

(apply 'and
    (mapcar
       '(lambda (x)
            (print x)
            (eq 9 x)
        )
       '(9 8 7 6 5 4 3 2 1)
    )  
)

;;  output

9
8
7
6
5
4
3
2
1 nil
Title: Better than mapcar???
Post by: daron on October 27, 2004, 05:13:26 PM
I knew I'd get more information than was provided. That's why I posted it.
Title: Better than mapcar???
Post by: MP on October 27, 2004, 05:58:31 PM
In my haste to quickly respond to this topic I failed to note a very important thing (in my mind), and that's the distinction beween vl-every and mapcar. Vl-every is more closely related to foreach than mapcar (in my opinion). Foreach iterates thru each item in a list, whatever is returned at the end of that iteration depends upon the last evaluation performed inside the loop construct. Mapcar on the other hand is designed so the result is returned as a list (nil is also a list).

Anywho, you could replicate the functionality of vl-every with a abused version of foreach to illustrate how it works; a simple (not robust) implementation might be:

Code: [Select]
(defun my-every ( predicate lst / result )
    (vl-catch-all-apply
       '(lambda ()
            (foreach x (mapcar 'list lst)
                (if (null (apply predicate x))
                    (progn
                        (setq result t)
                        (exit)
                    )    
                )
            )
        )    
    )    
    (null result)
)

;;  using previous contrived example ...

(vl-every
   '(lambda (x)
        (print x)
        (eq 9 x)
    )
   '(9 8 7 6 5 4 3 2 1)
)

;;  output ..

9
8 nil

(my-every
   '(lambda (x)
        (print x)
        (eq 9 x)
    )
   '(9 8 7 6 5 4 3 2 1)
)

;;  output ..

9
8 nil

Cheers.
Title: Better than mapcar???
Post by: daron on October 28, 2004, 08:14:28 AM
Now that's pretty neat. Thanks MP.
Title: Better than mapcar???
Post by: whdjr on October 28, 2004, 08:41:57 AM
Quote from: Daron
Better than mapcar???

That's like asking  "Better than sex???" :twisted:
Title: Better than mapcar???
Post by: MP on October 28, 2004, 10:24:45 AM
Quote from: Daron
Now that's pretty neat. Thanks MP.

Hoped it would be illuminating for at least one bit head; thanks for the thanks. :)

Quote from: whdjr
That's like asking  "Better than sex???"

Like many questions it depends upon the context. Ask that question of a 5 year old boy, a teenager and a ninety five year old man. Whose answer is correct? :)
Title: Better than mapcar???
Post by: SMadsen on October 28, 2004, 10:36:41 AM
Would this do as a homebrewed VL-EVERY (though taking only one list argument)?

Code: [Select]
(defun myEvery (pred lst)
  (cond ((null lst))
        ((apply pred (list (car lst)))
         (myEvery pred (cdr lst))
        )
  )
)
Title: Better than mapcar???
Post by: whdjr on October 28, 2004, 10:40:07 AM
Quote from: MP
Quote from: whdjr

That's like asking "Better than sex???"


Like many questions it depends upon the context. Ask that question of a 5 year old boy, a teenager and a ninety five year old man. Whose answer is correct? Smile


I was wondering how long someone would leave that one hanging.
Title: Better than mapcar???
Post by: MP on October 28, 2004, 10:44:48 AM
Quote from: whdjr
I was wondering how long someone would leave that one hanging.

Ackkk, thanks for the visual.