(princ '(setq d (cons (car c) h))) unexpected results. Thanks.

(princ '(setq d (cons (car c) h))) unexpected results. Thanks.

Anonymous
Not applicable
844 Views
11 Replies
Message 1 of 12

(princ '(setq d (cons (car c) h))) unexpected results. Thanks.

Anonymous
Not applicable

 

 

Hi!

 

I have the following code and I get unexpected result.

(defun C:MyTemp()



  
  (setq c '(40.0 5))
	(setq h '(20.0 10)

  (princ '(setq d (cons (car c) h)))

  )

I expect to get (40 20.0),

but I get (40 . 20.0)

 

All ideas are appreciated.

 

Thank you!

 

0 Likes
845 Views
11 Replies
Replies (11)
Message 2 of 12

ВeekeeCZ
Consultant
Consultant

Missing parthesis.

 

(defun C:MyTemp()
  (setq c '(40.0 5))
  (setq h '(20.0 10))
  (princ (setq d (cons (car c) h))) ;erased '
)

And reslut is: (40.0 20.0 10)

first of c added to whole h.

Message 3 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

I expect to get (40 20.0),

but I get (40 . 20.0)

 

.... 

If you really want just the 20.0 out of the h variable, and not in a dotted-pair list with what comes from the c variable:

 

(defun C:MyTemp()
  (setq c '(40.0 5))
(setq h '(20.0 10)); as corrected by BeekeeCZ (princ (setq d (list (car c) (car h)))) )

 That returns (40.0 20.0), so if you really want just the 40, either change it in the setting of the c variable, or do something like this:

 

....
(princ (setq d (list (fix (car c)) (car h))))
....

 

Kent Cooper, AIA
Message 4 of 12

Anonymous
Not applicable

Sorry, I didn't get the idea.

 

Here is the code of @ВeekeeCZ

 

 

(defun C:MyTemp()
  (setq c '(40.0 5))
  (setq h '(20.0 10))
  (princ (setq d (cons (car c)   h))) ;erased '
)

 

 

If I modify it and instead h I use (cadr h)

 

 

(defun C:MyTemp()
  (setq c '(40.0 5))
  (setq h '(20.0 10))
  (princ (setq d (cons (car c)   (cadr h)))) ;erased '
)

I get the same result with the space    (40.0 . 10)

+++++++++++++++++

 

Please also explain me where I should use '  and  where should not.

 

Thank you!

 

 

0 Likes
Message 5 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....

I get the same result with the space    (40.0 . 10)

....

Please also explain me where I should use '  and  where should not.

 

....

If you mean that you do not want the period between the 40.0 and the 10, use the (list) function instead of (cons), as I suggested in Post 3.  Read about both in Help to understand why (cons) is making a dotted-pair list.

 

For the apostrophe [ ' ] issue, read about the (quote) function, for which ' is shorthand, to learn what it does, and also about the (list) function and its usage in relation to (quote) or '.

Kent Cooper, AIA
Message 6 of 12

Anonymous
Not applicable

OK.

 

Thank you!

 

One more question:

 

What is the use of dotted-pair list?

 

Thanks!

0 Likes
Message 7 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... 

What is the use of dotted-pair list?

 

....

There may be other reasons for them to exist, but here's one thing that I'm aware of:

 

The AutoLisp (cdr) function applied to a list normally returns the list with the first item removed from it, but still as a list.  But if it's a dotted-pair list, (cdr) returns simply the second item in it, not as a shortened one-item list but as whatever kind of thing it is [number, text string, entity name].  So what good is that?  Take, for example, the entity data list from a Line:

 

((-1 . <Entity name: 7ef71dc8>) (0 . "LINE") (330 . <Entity name: 7ef6ecf8>) (5 . "2F1") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbLine") (10 4.625 1.1875 0.0) (11 5.4375 2.125 0.0) (210 0.0 0.0 1.0))

 

An entity data list is a list of lists [or of sub-lists, if you like].  Some of the lists in it are "ordinary" lists, and some [most] of them are dotted pairs.  This structure allows you to use the same function (cdr) to extract pieces entity data in appropriately usable form from any of those sub-lists.  You find data entries with the (assoc) function, using the first number in a sub-list as the first argument and the entity data list as the second argument.  Where the difference kicks in is in extracting the information from a sub-list that (assoc) locates.

 

For instance, the start and end points of the Line are in the 10- and 11-code entries, in this case  (10 4.625 1.1875 0.0)  and  (11 5.4375 2.125 0.0).  These are "ordinary" lists of four items each.  When you apply (cdr) to them, you get the points themselves [which are three-item lists of XYZ coordinates], with the 10 or 11 removed, namely (4.625 1.1875 0.0) and (5.4375 2.125 0.0).  And that's how you need them -- in list form -- if you want to use them as points in whatever your routine is doing.

 

But the Layer that the Line is drawn on is stored in the 8-code entry, in this case (8 . "0").  That's a dotted-pair list, so when you apply (cdr) to that, it returns just the "0" as a text string, which is, again, how you will need it -- as a string rather than a list -- if you want to [for example] set that Layer current, or unlock it, or something.  If that were stored as an "ordinary" list without the dot, namely (8 "0"), then when you applied (cdr) to it, it would return ("0") [in parentheses] as a one-item list, rather than as a text string, and you can't set the current Layer name to a list.  You would need to use a different function -- (cadr) -- on it to get the "0" string itself.

 

Because you can use the same (cdr) function to get any piece of information in appropriately usable form, in a routine that needs to get lots of these pieces of information from entity data, you can shortcut the code required to do that with a sub-routine, which here assumes you have stored that entity data list in a variable called 'edata':

 

(defun data (num)

  (cdr (assoc num edata))

); defun

 

Then, when you want the start point of a Line, instead of:

 

(cdr (assoc 10 edata))

 

you can use:

 

(data 10)

 

and if you want its Layer, instead of:

 

(cdr (assoc 8 edata))

 

you can use:

 

(data 8)

 

Even though one of those requests wants a list returned and the other wants a text string, the same sub-routine will get what is needed from the appropriate entry, in the appropriate form.  You don't need a separate sub-routine to get point- or vector-type data entries from the one you use to get other kinds.

 

 

Kent Cooper, AIA
Message 8 of 12

Anonymous
Not applicable

 Hi!

Please help me to understand the following issue

 

I have a text from the tutorial

 

++++++++++++

What we have is a list of angles that we want to convert to Radians.

	(setq c '(23.0 47.8 52.1 35.6))

Firstly we would write a function to convert degrees to radians :

(defun dtr (a)
	(* pi (/ a 180.0))
)

Our function to convert our list would look like this :

	(setq d (mapcar 'dtr c))

This function will run the (dtr) function against each element of list c. In other words, the value of each element is passed to the (dtr) function.

The function could also be written like this :

	(setq d (mapcar (quote dtr) c))

++++++++++++++

 

From other tutorials I have learned that  quote command is used for list that should not be evaluated by list function.

 

But here I see :

(setq d (mapcar (quote dtr) c))

I don't understand why the quote function is used here.

Thank you!

 

0 Likes
Message 9 of 12

ВeekeeCZ
Consultant
Consultant

 

It's not used for list but for function name drt.

c variable is a list

 

"quote command is used for list that should not be evaluated by list function."

 

You can use '(1 2 3) - here is nothing to evaluate

But not '(1 (+ 1 2) 3) - here is + function to evaluate, so you need to use (list 1 (+ 1 2) 3)

 

Here is somthing to understand:

(mapcar '+ '(1 2))    + is a function name similar to your drt

 

 

Message 10 of 12

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

....Our function to convert our list would look like this :

	(setq d (mapcar 'dtr c))

....

The function could also be written like this :

	(setq d (mapcar (quote dtr) c))

.... quote command is used for list that should not be evaluated by list function.

 

But here I see :

(setq d (mapcar (quote dtr) c))

I don't understand why the quote function is used here.
....

I'm not quite sure, either, and it doesn't seem to be explained in Help anywhere that I can find, but I think, at least in part, it has to do with distinguishing a function name from the possibility of a variable that could have the same name.  Without the ' before it, AutoLisp will try to evaluate the term as if it's a variable.  For example, I have a (defun)'d command called ZL which Zooms to the drawing Limits, and which gets loaded in every drawing.  If I use the (type) function to find out what ZL is:

 

Command: (type ZL)
nil

 

That's apparently the result of AutoLisp's thinking it's a variable that needs to be evaluated.  But if I put the apostrophe before it, it tells AutoLisp not to evaluate it for content as a variable, in which case it can tell that it's a SYMbol:

Command: (type 'ZL)
SYM

 

If I set some value into ZL as a variable name:

 

Command: (setq ZL 23.45)
23.45

 

then when I ask what type it is without the apostrophe, it evaluates it as a variable, and knows what kind of content it holds:

 

Command: (type ZL)
REAL

 

But I don't fully understand some aspects of this whole subject, for example the difference between SYM and SUBR in what (type) returns, especially in relation to native AutoLisp function names, such as:

 

Command: (type car)
SUBR

 

It knows that one's not a variable name to be evaluated, even without the apostrophe, and it calls it something else if you include that:

 

Command: (type 'car)
SYM

 

I also don't understand the fact that it also "knows" [or "thinks"?] something that has not been defined is a SYMbol when I put an apostrophe before it:

 

Command: (type 'whatever)
SYM

 

which throws into question the return from (type 'ZL) earlier -- apparently it doesn't really know that ZL is a defined command, but at least it knows from the apostrophe that it's not to be evaluated like a variable.

 

I could study more about (quote), (type), symbols vs. variables vs. subroutines, and functions that use the difference -- (mapcar), (apply), etc. -- but I'm accustomed enough to the apostrophe prefix in those situations that I don't think much about it any more.

 

Another use of the apostrophe as a prefix is in working with System Variable names.  Both the (getvar) and (setvar) can take a System Variable name in either of two forms: with double-quotes at both ends, or with an apostrophe only at the beginning [which is what I always use -- it's shorter!].  These are both valid and equivalent:

 

(setvar "osmode" 0)

or

(setvar 'osmode 0)

 

Help for (setvar) uses the former in its example, but Help for (getvar) uses the latter [even though it describes the argument as a string].  But I haven't seen any description of why either a STRing or a SYMbol can be used in these functions.

Kent Cooper, AIA
Message 11 of 12

martti.halminen
Collaborator
Collaborator

 

You are approaching this from an empirical viewpoint. It is easier if you know the actual rules, for that Autodesk documents are not necessarily the best source. Finding some books about programming would be better.

 

The nearest relative to AutoLISP in this regard is the Scheme language. Reading books about Common Lisp wouldn't be bad either, but in this regard there are a few additional complications in CL that may confuse the reader.

 

The rules in Scheme-like languages are really simple: evaluate everything. The QUOTE function protects whatever it surrounds from (one level of) evaluation.

 

- numbers and strings are self-evaluating: (eval 5) -> 5, (eval "foo") -> "foo". (eval (quote "foo")) -> "foo", so here adding a quote won't change anything.

 

- Evaluating a symbol produces whatever was bound to it (or NIL in AutoLISP if there wasn't anything. In most other Lisps you'd get an unbound-variable error.) So, evaluating PI produces 3.14159, but evaluating 'PI produces the symbol PI. (eval +) -> #<SUBR @0000000030e72ba8 +>, that is a function object.

 

As an aside, your ZL command doesn't follow these rules, because its actual name on the Lisp side is C:ZL, not bare ZL. A symbol has at any time only one value bound to it, which may be either an ordinary value, or a function:

_$ (setq a 5)
5
_$ a
5
_$ (defun a () (print 'b))
A
_$ a
#<USUBR @00000000315bd0e8 A>

 

so defining the function A overwrote the previous value A had.

[This is one of the complications with CL: it has separate namespaces for values and functions]

 

- So if you do (setq C:ZL 6), you just broke your ZL command.

 

 

 

And the final evaluation rule: what to do with lists: evaluate all the contents, and call the value of the first one as the function, and the rest as its arguments.

 

So, (quote ...) is not in any way specialized for lists, it protects anything from evaluation.

 

 

Of course this isn't quite so simple: there are some special constructs that don't entirely follow these rules: COND or IF would work rather oddly, if every choice got evaluated. Likewise DEFUN, OR, AND, SETQ and a few others. MAPCAR is also slightly odd: in AutoLISP it doesn't accept a function object as its argument, it wants the name of the function, so it has to be quoted if given as a symbol (instead of calculated by another function).

 

-- 

 

Message 12 of 12

Anonymous
Not applicable

Guys!

Thanks for your replies.

 

It is a bit comlicated, but I will try to comprehend line by line.

 

Thanks!

0 Likes