declaring variable

declaring variable

vishshreevT578L
Advocate Advocate
1,703 Views
22 Replies
Message 1 of 23

declaring variable

vishshreevT578L
Advocate
Advocate

(defun CopyLayerColor2 (ent1 ent2 / elist1 elist2 lay1 col1)
(setq elist1 (entget ent1)
elist2 (entget ent2)
lay1 (cdr (assoc 8 elist1))
)
(setq elist2 (subst (cons 8 lay1) (assoc 8 elist2) elist2))
(if (assoc 62 elist1)
(progn
(setq col1 (cdr (assoc 62 elist1)))
(if (assoc 62 elist2)
(setq elist2 (cons (cons 62 col1) elist2))
(setq elist2 (subst (cons 62 col1) (assoc 62 elist2) elist2))
)
)
)
(entmod elist2)
)

 

Is this code correct.

my question is about declaring variable which i am making bold. (defun CopyLayerColor2 (ent1 ent2 / elist1 elist2 lay1 col1) 

Shreev
0 Likes
Accepted solutions (1)
1,704 Views
22 Replies
Replies (22)
Message 2 of 23

ВeekeeCZ
Consultant
Consultant

Read about arguments HERE

0 Likes
Message 3 of 23

vishshreevT578L
Advocate
Advocate

Thank you sir,

 

but i did not understand this part.

 

(defun ARGTEST (arg1 arg2 / ccc retVal)
(setq ccc "Constant string")

(if (= (type arg1) 'STR)
(if (= (type arg2) 'STR)
(setq retVal (strcat ccc ", " arg1 ", " arg2))
(prompt "bad argument: arg2 not a string\n")
)
(prompt "bad argument: arg1 not a string\n")
)
(if retVal
retVal
(princ)
)
)

 

sorry i am new here (I hope you understand), can you make me understand this subject (like teaching a,b,c,d...to a child) as i am unable to move ahead

 

Shreev
0 Likes
Message 4 of 23

ВeekeeCZ
Consultant
Consultant

What do you don't understand. You've found the code somewhere and don't know how to use it? You don't need to "declare" arguments.

 

Usage of sub-function is something like this:

 

(defun C:CopyLayerColor2 ( / en1 en2)
  (if (and (setq en1 (car (entsel "\nSelect the object to copy layer from: ")))
	   (setq en2 (car (entsel "\nSelect the object to copy layer to: ")))
	   )
    (CopyLayerColor2 en1 en2))
  (princ)
  )

Or you can modify the original subfunction... 

 

Spoiler
(defun c:CopyLayerColor2 ( / elist1 elist2 lay1 col1)
  (setq elist1 (entget (car (entsel "\nSelect the object to copy layer from: "))
	elist2 (entget (car (entsel "\nSelect the object to copy layer to: ")))
	lay1 (cdr (assoc 8 elist1))
	)
  (setq elist2 (subst (cons 8 lay1) (assoc 8 elist2) elist2))
  (if (assoc 62 elist1)
    (progn
      (setq col1 (cdr (assoc 62 elist1)))
      (if (assoc 62 elist2)
	(setq elist2 (cons (cons 62 col1) elist2))
	(setq elist2 (subst (cons 62 col1) (assoc 62 elist2) elist2))
	)
      )
    )
  (entmod elist2)
  )
0 Likes
Message 5 of 23

martti.halminen
Collaborator
Collaborator

That might be a little easier to understand if you indent it according to its structure.

(defun ARGTEST (arg1 arg2 / ccc retVal)
  (setq ccc "Constant string")
  (if (= (type arg1) 'STR)
      (if (= (type arg2) 'STR)
          (setq retVal (strcat ccc ", " arg1 ", " arg2))
          (prompt "bad argument: arg2 not a string\n"))
      (prompt "bad argument: arg1 not a string\n"))
  (if retVal
      retVal
      (princ)))

--

 

0 Likes
Message 6 of 23

vishshreevT578L
Advocate
Advocate
(defun ARGTEST (arg1 arg2 / ccc retVal)
  (setq ccc "Constant string")
  (if (= (type arg1) 'STR)
      (if (= (type arg2) 'STR)
          (setq retVal (strcat ccc ", " arg1 ", " arg2))
          (prompt "bad argument: arg2 not a string\n"))
      (prompt "bad argument: arg1 not a string\n"))
  (if retVal
      retVal
      (princ)))

IF I WILL SET A NEWSTR IN SUCH A WAY

 

(SETQ NEWSTR (ARGTEST "STR1" 2.0)) THEN IT HAS TO PROMPT FOR  

"bad argument: arg2 not a string

 

Shreev
0 Likes
Message 7 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:

(defun CopyLayerColor2 (ent1 ent2 / elist1 elist2 lay1 col1)

....

my question is about declaring variable which i am making bold. (defun CopyLayerColor2 (ent1 ent2 / elist1 elist2 lay1 col1) 


The trick is in the use of a function like that, with arguments.  Since it does not have a C: before the function name, it is a function, and not a command, which means it must be called inside parentheses, just as with any other AutoLisp function, and not by entering the name at the Command prompt.

 

The things in the parentheses following the function name are distinguished by whether they are before or after the slash character.  Those that are before it are arguments, and you must supply them [I assume that's what you mean by "declaring" them] when you use the function, inside the parentheses calling the function, after the function name, and in the order in the arguments list.  They must be the kind of thing that the function will be looking for, in this case entity names.  This is how you would use that function:

 

(CopyLayerColor2 anEntityName anotherEntityName)

 

Those entity names can be supplied from variables, which you would set by some other means external to this function definition, such as @ВeekeeCZ's first code in Post 4.  Or one of them could be (entlast), or either or both could be taken from a list of them with something like (nth) or (car)/(cadr)/(etc.) or (last), or from a selection set with (ssname), or by (entnext), or any other means of conveying an entity name.

 

Note that the second code in Post 4 doesn't merely redefine the function, but defines it instead as a Command name [with the C: prefixed], without arguments but with selection of entities built into it.  That one you would use by just typing in the command name, without surrounding parentheses.

 

Kent Cooper, AIA
Message 8 of 23

ВeekeeCZ
Consultant
Consultant

@vishshreevT578L wrote:
(defun ARGTEST (arg1 arg2 / ccc retVal)
  (setq ccc "Constant string")
  (if (= (type arg1) 'STR)
      (if (= (type arg2) 'STR)
          (setq retVal (strcat ccc ", " arg1 ", " arg2))
          (prompt "bad argument: arg2 not a string\n"))
      (prompt "bad argument: arg1 not a string\n"))
  (if retVal
      retVal
      (princ)))

IF I WILL SET A NEWSTR IN SUCH A WAY

 

(SETQ NEWSTR (ARGTEST "STR1" 2.0)) THEN IT HAS TO PROMPT FOR  

"bad argument: arg2 not a string

 


That's because 2.0 (as value for 2nd argument) is not a string! You need to use quote marks to make this string "2.0".

 

@Kent1Cooper thanks for putting the code into words.

0 Likes
Message 9 of 23

vishshreevT578L
Advocate
Advocate

sir can you give a effective example on this

Shreev
0 Likes
Message 10 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:
....I WILL SET A NEWSTR IN SUCH A WAY

(SETQ NEWSTR (ARGTEST "STR1" 2.0)) THEN IT HAS TO PROMPT FOR  

"bad argument: arg2 not a string

Exactly.  That's what it's designed to do.  The arg1 and arg2 are supposed to be text strings.  Try:

 

(SETQ NEWSTR (ARGTEST "STR1" "2.0"))

Kent Cooper, AIA
0 Likes
Message 11 of 23

vishshreevT578L
Advocate
Advocate

 

TEST.jpg

 

Shreev
0 Likes
Message 12 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:

sir can you give a effective example on this


The first code in Post 4 is one [I expect, though I haven't loaded and tried it].  It defines a CopyLayerColor2 Command [with the C: prefixed].  When you type in that command name, it asks you to select things [in which I would add "and color" in the prompts], and it puts their entity names into the en1 and en2 variables.  It then uses those variables as the ent1 and ent2 arguments in the CopyLayerColor2 function.

 

In the Command's use of the function:
(CopyLayerColor2 en1 en2)

the 'en1' is that variable set earlier in the Command.  Since it is the first argument supplied in calling the function, it will be used in the operation of the function wherever the first argument in its argument list ['ent1'] appears in its code.  And the second supplied argument [in this case 'en2'] will be used wherever the second argument listed in the function definition line ['ent2'] occurs in its code.

Kent Cooper, AIA
0 Likes
Message 13 of 23

vishshreevT578L
Advocate
Advocate

NO PROMPT HERE SIR....THATS WHAT IS CONFUSING ME ....PLEASE EXPLAIN ME THIS AND ALSO GIVE A NICE EXAMPLE FOR ARGUMENTS

Shreev
0 Likes
Message 14 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:

NO PROMPT HERE SIR....THATS WHAT IS CONFUSING ME ....


I get the prompts from @ВeekeeCZ's first code in Post 4.  Are you loading it correctly?  After loading it, does AutoCAD recognize the CopyLayerColor2 command name?  If so, does it not prompt you to select the objects?

 

In trying it out, I discovered something:  If the first object's color is ByLayer, but the second one has an override color, the routine will change the second one's Layer, but it will not change its Color to ByLayer to match the first object -- it leaves the Color override on the second object.  See below for one that imposes ByLayer Color on the second one if that is the Color of the first one.

 

But in addition to that, there's a cute trick that can simplify this.  If an entity data list has more than one entry for a property for which there can be only one [such as Layer and Color], the entry that comes later in the list "wins" and overrules any earlier one(s).  That means it's not necessary to (subst)itute entries taking properties from one list into the other.  You can simply add entries onto the end, and the earlier ones will be overruled by the later ones.  This eliminates the need for some variables, and for the extraction of Layer and Color properties.  Try this [lightly tested]:

(defun CopyLayerColor2 (ent1 ent2 / elist1 elist2); the function
  (setq
    elist1 (entget ent1); entity data lists
    elist2 (entget ent2)
  ); setq
  (setq elist2 (append elist2 (list (assoc 8 elist1)))); assign ent1's Layer to ent2
  (setq elist2
    (append elist2 ; Color adjustment
      (if (assoc 62 elist1); ent1 has override [non-Bylayer] Color
        (list (assoc 62 elist1)); then [give that to ent2]
        '((62 . 256)); else [make ent2's Color ByLayer]
      ); if
    ); append
  ); setq
  (entmod elist2); update properties of ent2
); defun

(defun C:CLC2 (/ en1 en2); = Copy Layer & Color 2 [whatever the 2 means]; the command
  (if
    (and
      (setq en1 (car (entsel "\nObject to copy Layer and Color FROM: ")))
      (setq en2 (car (entsel "\nObject to copy Layer and Color TO: ")))
    ); and
    (CopyLayerColor2 en1 en2); apply those entities as arguments to the function
  ); if
  (princ)
); defun

[I shortened the command name from BeekeeCZ's version for ease of use.]

 

And then, of course, there's the option to just use MATCHPROP -- I assume this must be for situations where there might be other override properties that you don't want copied from the first object to the second.  However, MATCHPROP has Settings with which it can be limited to match only Layer and Color -- setting it that way would eliminate the need for any of this, as well as letting you do the matching to more than one other object within one running of the command.

Kent Cooper, AIA
Message 15 of 23

vishshreevT578L
Advocate
Advocate

Thank you Sir!

 

that means whatever we are declaring here (DEFUN C:TEST (ARG1 ARG2 .... / TEST1 TEST2) HAS TO BE DEFINED IN A VARIABLE.

 

i understood this now....

Shreev
0 Likes
Message 16 of 23

vishshreevT578L
Advocate
Advocate

now i want to inspect this code line by line, so how will i?

 

Shreev
0 Likes
Message 17 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:

.... 

that means whatever we are declaring here (DEFUN C:TEST (ARG1 ARG2 .... / TEST1 TEST2) HAS TO BE DEFINED IN A VARIABLE.

.....


Not necessarily always in a variable, though that is probably how arguments are supplied in most cases.  But you could supply the arguments not in variables.  A very trivial example:

 

(defun Add3 (Num1 Num2 Num3); = Add 3 numbers and only 3 numbers

  (+ Num1 Num2 Num3)

)

 

To use that, you could ask for numbers and put them into variables to feed to it, but you can also feed in numbers directly, and/or symbols and/or the results of other functions:

 

Command: (Add3 1.234 pi (sqrt 10))

7.53787

 

[That is trivial because you could just do:

 

(+ 1.234 pi (sqrt 10))

 

but one might have a reason to require 3 and only 3 numbers.  The (+) function can't restrict how many numbers you add in it, but the (Add3) function would tell you if you supplied the wrong number of arguments.]

Kent Cooper, AIA
0 Likes
Message 18 of 23

Kent1Cooper
Consultant
Consultant

@vishshreevT578L wrote:

now i want to inspect this code line by line, so how will i?

 


I suggest you just read about each function involved in Help.  The function names are what immediately follows each left parenthesis -- defun, setq, append, if, and so on.

Kent Cooper, AIA
0 Likes
Message 19 of 23

ВeekeeCZ
Consultant
Consultant
Accepted solution

@vishshreevT578L wrote:

now i want to inspect this code line by line, so how will i?

 


Tracing the code step by step, see the SCREENCAST

 

Edit: I wanted to show you how the cursor blinks when it match the parenthesis, but the video did not record this behaviour... so try yourselve.

Message 20 of 23

john.uhden
Mentor
Mentor
(defun ARGTEST (arg1 arg2 / ccc retVal)
  ;; Note that the input arguments, arg1 and arg1, are local as well as ccc and retval,
  ;; meaning that they will have no value outside the function.
  ;;
  ;; The use of "and" was taught by Stephan Koster.
  ;; It stops evaluating on the first statement that returns nil.
  ;; Here, prompt returns nil (as it always does).
  (and
    (setq ccc "Constant string")
    (or
      (= (type arg1) 'STR)
      (prompt "\nbad argument: arg1 is not a string.")
    )
    (or
      (= (type arg2) 'STR)
      (prompt "\nbad argument: arg2 not a string.")
    )
    (setq retVal (strcat "\n" ccc ", " arg1 ", " arg2))
  )
  ;; A function returns the last evaluation.
  ;; So if the "and" never got to the (setq retval...) line,
  ;; then retval would be nil, and the function would return nil.
  retVal
)

Command: (argtest "thing" "bling") [Enter]
"Constant string, thing, bling"

Command: (argtest "thing" 1)  [Enter]
bad argument: arg2 not a string. nil

John F. Uhden

0 Likes