Question regarding a mapcar lambda code

Question regarding a mapcar lambda code

Anonymous
Not applicable
2,292 Views
23 Replies
Message 1 of 24

Question regarding a mapcar lambda code

Anonymous
Not applicable

Hi all!

 

I have a list of a lists called in this example "list"

 

It looks like this:

((1.0 1.0 0.0) (3.0 5.0 0.0) (6.0 4.0 0.0))

 

I would like to add 5.0 to the car of each list, 4.0 to the cadr of each one, and nothing to the caadr of them. (i can even omit the third part)

 

So i would like to get this at the end in a variable called offs.

((6.0 5.0 0.0) (8.0 9.0 0.0) (11.0 8.0 0.0))

 

I am trying this line:

 

(setq offs (mapcar '(lambda (a) ((+ 5.0 (car a))(+ 4.0 (cadr a))(+ 0 (caadr a)))) list))

 

But of course it doesnt work, and i feel like its total wrong, because i dont know what will mapcar return in this case, but i dont think its even a list. I think i should include "list" and "append" too to somewhere.

 

Can someone help? 🙂

 

Thanks in advance!

0 Likes
Accepted solutions (4)
2,293 Views
23 Replies
Replies (23)
Message 2 of 24

Kent1Cooper
Consultant
Consultant
Accepted solution

Try this:

 

(setq offs (mapcar '(lambda (x) (mapcar '+ x '(5.0 4.0 0.0))) list))

Kent Cooper, AIA
0 Likes
Message 3 of 24

ВeekeeCZ
Consultant
Consultant
Accepted solution

(setq offs (mapcar '(lambda (a) (list (+ 5.0 (car a))(+ 4.0 (cadr a))(+ 0 (caddr a)))) lst))

you cannot name a variable list since that is a name of function - which, btw, is the one you need to use to fix your expresion.

 

or of course, you don't need to add 0:

(mapcar '(lambda (a) (list (+ 5.0 (car a)) (+ 4.0 (cadr a)) (caddr a))) lst)

0 Likes
Message 4 of 24

Kent1Cooper
Consultant
Consultant

@ВeekeeCZ wrote:

....

you cannot name a variable as list since that is a name function - which you need to use to fix your expresion.

....


True -- change that in Message 2 to go along with whatever other variable name you use.

Kent Cooper, AIA
0 Likes
Message 5 of 24

ronjonp
Advisor
Advisor
Accepted solution

Here's another for fun:

(defun _myoff (p) (mapcar '+ p '(5. 4. 0.)))
(setq l (mapcar '_myoff '((1. 1. 0.) (3. 5. 0.) (6. 4. 0.))))
Message 6 of 24

Anonymous
Not applicable

Both solutions are working perfectly! Thanks for the help, you are all awesome.

The first solution is a bit hard to understand 🙂

0 Likes
Message 7 of 24

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

The first solution is a bit hard to understand 🙂


Perhaps, but it's so concise!  I agree, those (mapcar) and (lambda) functions take some getting used to....

 

(setq offs (mapcar '(lambda (x) (mapcar '+ x '(5.0 4.0 0.0))) yourNewVariableName))

 

The inner (mapcar '+ ...) function adds the items in a list to the corresponding items in another list, in this case XYZ coordinate values.  The x is the stand-in within the (lambda) function for each item that the function is applied to by the outer (mapcar) function [each set of XYZ coordinates in your initial list].  Clear as mud?

Kent Cooper, AIA
Message 8 of 24

hak_vz
Advisor
Advisor
Accepted solution

Here is another one. Created just for testing, but it works.

 

 

(setq lst '((1. 1. 0.) (3. 5. 0.) (6. 4. 0.)))
(foreach e lst
	(setq lst 
		(append (cdr lst) (list(mapcar '+ e '(5 4 0))))
	)
)
;-> ((6.0 5.0 0.0) (8.0 9.0 0.0) (11.0 8.0 0.0))

 

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 9 of 24

Anonymous
Not applicable

Thanks! Nice idea! 🙂

 

I started to learn autolisp like two month ago, and I always have a lot of questions but there are some questions wich i cant answer even when i try to research for it. But i dont think it would be a good idea to flood this forum with different threads for all of my small questions. So I think i should rename this thread into random questions 😄

 

For example here is this code:

 

(defun c:hlines ( / *error* g1 g2 gr h l ms p p1 p2 v )
  ;; Lee Mac 2011
  (defun *error* ( m ) (redraw) (princ))
  (or *n (setq *n 3))
 
  (if (setq p1 (getpoint "\nSpecify First Corner: "))
    (progn
      (setq ms (princ "\nSpecify Opposite Corner [+/-]: "))
      (while
        (progn (setq gr (grread t 15 0) g1 (car gr) g2 (cadr gr))
          (cond
            ( (= 5 g1)(redraw)
              (setq h (- (car g2) (car p1))
                    v (/ (- (cadr g2) (cadr p1)) (1+ *n))
                    p p1
              )
              (repeat *n
                (setq p (list (car p) (+ v (cadr p)) (caddr p)))
                (grdraw p (list (+ (car p) h) (cadr p) (caddr p)) -1)
              )
              (setq l
                (list
                  p1 (list (+ (car p1) h) (cadr p1) (caddr p1))
                  g2 (list (car p) (+ v (cadr p)) (caddr p))
                )
              )
              (mapcar '(lambda ( a b ) (grdraw a b 1 -1)) l (append (cdr l) (list (car l))))
            )
            ( (= 2 g1)
              (cond
                ( (member g2 '(45 95))
                  (if (= 1 *n)
                    (princ (strcat "\n--> Minimum Number of Lines Reached." ms))
                    (setq *n (1- *n))
                  )
                )
                ( (member g2 '(43 61))
                  (setq *n (1+ *n))
                )
              )
            )
            ( (= 3 g1)
              (setq h (- (car g2) (car p1))
                    v (/ (- (cadr g2) (cadr p1)) (1+ *n))
              )
              (repeat *n (setq p1 (list (car p1) (+ v (cadr p1)) (caddr p1)))
                (entmakex
                  (list
                    (cons 0 "LINE")
                    (cons 10 (trans p1 1 0))
                    (cons 11 (trans (list (+ (car p1) h) (cadr p1) (caddr p1)) 1 0))
                  )
                )
              )
              nil
            )
          )
        )
      )
    )
  )
  (redraw) (princ)
)

 

What is the sense of encapsulating the whole program into an "if" statement?

I mean getpoint will wait for the point, and the program would continue only if the point is given anyway.

I dont understand this line neither: (or *n (setq *n 3)) 😞

0 Likes
Message 10 of 24

ronjonp
Advisor
Advisor

@Anonymous wrote:

What is the sense of encapsulating the whole program into an "if" statement?

I mean getpoint will wait for the point, and the program would continue only if the point is given anyway.

I dont understand this line neither: (or *n (setq *n 3)) 😞


Maybe this sheds some light:

 

 

;; Global variable, if it does not exist set it to 3
(or *n (setq *n 3))
;; Is the same logic as
(if (not *n)
  (setq *n 3)
)

;; Getpoint <enter>
(getpoint)
;; returns nil and the program needs a point to start that's why there is a check

;; If you want to have a default point set to the center of the screen and remove
;; the if statement, it could be written like the or statement above
(or (setq p1 (getpoint "\nSpecify First Corner: ")) (setq p1 (getvar 'viewctr)))

 

 

Message 11 of 24

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

What is the sense of encapsulating the whole program into an "if" statement?

I mean getpoint will wait for the point, and the program would continue only if the point is given anyway.

I dont understand this line neither: (or *n (setq *n 3))


The program would continue even if the point is not given [i.e. is nil, if the User hits Enter at the (getpoint) prompt], but would run into a problem when it first tried to use the p1 variable, and throw an error.  With the (if) test, it will not throw an error, but will just not proceed.  An (initget 1) preceding could forbid the User to hit Enter, if you'd rather go that direction.

 

About (or *n (setq *n 3)):  An (or) function returns True when it reaches the first argument that does not return nil, and stops looking at any further arguments.  If there's a *n variable value already, that will satisfy the (or) function, so it will not reach the (setq) function.  It's creating a starting value for *n only if there isn't a value already.  It's equivalent to:
(if (not *n) (setq *n 3))

Kent Cooper, AIA
Message 12 of 24

ronjonp
Advisor
Advisor

Similar to @hak_vz  but I prefer mapcar for this since it keeps the order of the elements without any futzing about 🙂

 

(foreach e (reverse '((1. 1. 0.) (3. 5. 0.) (6. 4. 0.)))
  (setq lst (cons (mapcar '+ e '(5. 4. 0.)) lst))
)

 

 Cool trick 

;; Change this
(mapcar '+ e '(5. 4. 0.))
;; To this and it will return a list of 2D points
(mapcar '+ e '(5. 4.))
Message 13 of 24

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

...

I dont understand this line neither: (or *n (setq *n 3)) 😞


(or
  *n 		; expression one
  (setq *n 3)	; expression two
  )

 

It might look weird, but these are two expressions. If I set any value to *n, it's True. Even an empty char "" is T. 

The OR function tests one expression after another until finds T, then it stops the testing and returns True. OR does not really care whether there are 1 or 2 or more T expressions. If one is T, that's enough, the result cannot be different than T. 

 

The opposite logic applies to the AND function - it tests one expression after another until finds nil, then it stops the testing and returns nil.

 

The COND function is even better and therefore very popular...

(cond ((test1) 
(result1 ...))
((test2)
(result2 ....))
((test3))
((test4)
(result4)))

 

It evaluates one test function after another until it finds True. Then it evaluates its result function and returns its value. BUT if there is NO result function - see test3 - then it returns the value of the test3 function itself! And not just True as OR/AND functions but a real value (possibly a value of *n).

Think of this:

(setq number (cond ((getreal "Enter number <pi>: "))

                                    (3.14)))

Message 14 of 24

hak_vz
Advisor
Advisor

@Anonymous  You have received explanation regarding how code works, so I want talk about this. Here is my only advice

Never create in your code construction like this.

(or *n (setq *n 3)

When naming variables don't use *-+/ at the beginning, or don't use it at all. One little space when editing can crush whole the code.

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 15 of 24

ВeekeeCZ
Consultant
Consultant

@hak_vz wrote:

@Anonymous  You have received explanation regarding how code works, so I want talk about this. Here is my only advice

Never create in your code construction like this.

(or *n (setq *n 3)

When naming variables don't use *-+/ at the beginning, or don't use it at all. One little space when editing can crush whole the code.

 


Agreed.

Although very often we can see something like this *hls-n* .

Double asterisks mark that it's a global variable. The name should be somehow unique to avoid possible unintentional conflicts with global variables of other routines. So this example is shortened routine name with the variable name.

*n - some users like things short, so use just one asterisk. 

 
Message 16 of 24

Anonymous
Not applicable

Awesome! Thank you! 🙂

0 Likes
Message 17 of 24

Kent1Cooper
Consultant
Consultant

@hak_vz wrote:

....

Never create in your code construction like this.

(or *n (setq *n 3)

When naming variables don't use *-+/ at the beginning, or don't use it at all. One little space when editing can crush whole the code.


I, on the other hand, don't agree.  There's nothing wrong with using allowed punctuation marks in variable names.  The "one little space" argument is spurious -- there are a myriad of places where one little space will ruin things, such as if one got into the middle of any function name, e.g.  (se tq *n 3) , but you don't need to be any more careful about that in variable names than you do in anything else.

 

As @ВeekeeCZ pointed out, many people use an asterisk at the beginning, or one at each end, to distinguish global variable names from local ones.  Such a thing is never required, just a visual cue.  Some people use _underscores_ or $dollar-signs$  or %percent-signs% in the same way.  All optional, and perfectly acceptable.  Just because some of them happen to be function names when used alone doesn't mean you shouldn't use them as part of something longer, with the same appropriate care as is needed for anything you do.

Kent Cooper, AIA
Message 18 of 24

ronjonp
Advisor
Advisor

@hak_vz wrote:

@Anonymous  You have received explanation regarding how code works, so I want talk about this. Here is my only advice

Never create in your code construction like this.

 

(or *n (setq *n 3)

 

When naming variables don't use *-+/ at the beginning, or don't use it at all. One little space when editing can crush whole the code.

 


I always prefix and suffix globals with * .. Consistency helps with finding pesky globals if problems arise.

 

(vl-remove-if-not '(lambda (x) (wcmatch x "`**`*")) (atoms-family 1))

 

 

Message 19 of 24

Anonymous
Not applicable

Alright nother question with the same lisp: why did Lee Mac use the "progn" functions the way he did in this code? The firtst progn is okayish because "if" needs it, (but why is it closed down only at the half of the while loop? And why did he used the second progn function for the while loop itself? While doesnt need progn to run and nothing changes if i left it out.

Possibly this is some kind of error handling function too?

0 Likes
Message 20 of 24

hak_vz
Advisor
Advisor

@Anonymous wrote:

Alright nother question with the same lisp: why did Lee Mac use the "progn" functions the way he did in this code? The firtst progn is okayish because "if" needs it, (but why is it closed down only at the half of the while loop? And why did he used the second progn function for the while loop itself? While doesnt need progn to run and nothing changes if i left it out.

Possibly this is some kind of error handling function too?


As it says in PROGN definition, it evaluates each expression sequentially and returns the value of the last expression.

For functions grread and grdraw to work, all possible cases must be evaluated, i.e. whole block inside progn.

Dending on case either new temporary representation is drawn after mouse move, or if space is not enough to create a line, warning message is shown....

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.