Author Topic: Storing variables  (Read 14889 times)

0 Members and 1 Guest are viewing this topic.

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Storing variables
« on: March 28, 2011, 02:16:07 PM »
I have 2 questions

1.  What is the simplist way to store a variable for future use, so after AutoCAD has been shut down and re-started I can call this variable?


2.  Why does USERS1 not store a variable in the drawing after saving and shutting down?  What use is this system variable?
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

CAB

  • Global Moderator
  • Seagull
  • Posts: 10395
Re: Storing variables
« Reply #1 on: March 28, 2011, 02:24:59 PM »
If you want something saved int the drawing use xdata.

If you want a global save use a text file or the registry.
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.

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #2 on: March 28, 2011, 02:48:46 PM »
Doesn't xdata just append to the entities dotted pair?  (can't remember the other name for dotted pair)
so I would use a filter to look for the xdata now associated to this element so now my xdata works as the handle?  (in my logic this would make the handle useless)  I know I am missing a bigger picture


Was USERS1-5 not developed for such a task?

USERR1-5
USERI1-5  save to the drawing but USERS1-5 does not, what is USSERS1-5 good for?
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

CAB

  • Global Moderator
  • Seagull
  • Posts: 10395
Re: Storing variables
« Reply #3 on: March 28, 2011, 03:26:53 PM »
xData can be attached to dictionaries. 8-)
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.

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #4 on: March 28, 2011, 03:41:53 PM »
I would echo what CAB suggests -

I mostly use text files for storing program settings that I wish to persist between drawing sessions (such as dialog settings), as these are safer and easier for the average user to remove than deleting registry keys.

As for storing data in drawings, if the data pertains to an entity in the drawing (for example, when using an Object Reactor perhaps) I would use the XData (eXtended data) for that entity, otherwise you can create your own dictionaries and add xRecords to those dictionaries (example here), and there is also LData.

Lee

CAB

  • Global Moderator
  • Seagull
  • Posts: 10395
Re: Storing variables
« Reply #5 on: March 28, 2011, 04:52:41 PM »
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.

Andrea

  • Water Moccasin
  • Posts: 2372
Re: Storing variables
« Reply #6 on: March 28, 2011, 05:57:44 PM »
Xdata and Ldata there are not only per drawings ?

maybe (setenv "myenvironnement") ??

or another suggestion...
a config file ? like cfg or ini ?
Keep smile...

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #7 on: March 28, 2011, 07:17:34 PM »
Xdata and Ldata there are not only per drawings ?

I don't follow?

maybe (setenv "myenvironnement") ??

SetEnv is convenient, but one must still remember that the function is writing data to the registry, under the following location:

Code: [Select]
(strcat "HKEY_CURRENT_USER\\" (vlax-product-key) "\\FixedProfile\\General")
And hence I would be careful not to bloat the registry unnecessarily.

a config file ? like cfg or ini ?

I suppose these would fall under the umbrella 'text file' method...

Aerdvark

  • Guest
Re: Storing variables
« Reply #8 on: March 29, 2011, 01:42:11 AM »
If you want something saved int the drawing use xdata.
If you want a global save use a text file or the registry.

For what I do with lisp, the textfile method suits me best

My reasons:
1. they can be viewed from outside autocad by notepad (handy in case of trouble)
2. also this will give you the ability to check or modify settings
3. you can create any extension like MyTextFile.mtf just rename your *.txt file

My 2 cents.

I see what you mean, the USERI1-5 are stored in the drawing just as the USERR1-5 are.
The USERS1-5 however are NOT. (http://docs.autodesk.com/ACD/2011/ENU/filesACR/WS1a9193826455f5ffa23ce210c4a30acaf-4e0d.htm)
Mind this: I = integer / R = Real / S = string.
Anyway... I assume you need to save a string in a specific drawing so I'd use a textfile or investigate some Xdata options.
« Last Edit: March 29, 2011, 01:48:44 AM by Aerdvark »

Stefan

  • Bull Frog
  • Posts: 255
Re: Storing variables
« Reply #9 on: March 29, 2011, 04:35:04 AM »
2.  Why does USERS1 not store a variable in the drawing after saving and shutting down?

Just a thought ...
Imagine that someone inexperienced download a lisp file that contains something like:

Code: [Select]
(eval (read (getvar "USERS1")))

Imagine now what could be saved in a DWG in USERS1-5 and you have a "perfect bomb" ...

Code: [Select]
(setvar "USERS1" "(vl-registry-delete HKEY_CURRENT_USER\\...  ... )")

... or other "goodies"

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #10 on: March 29, 2011, 07:26:47 AM »
Hmmm... but that 'danger' would exist should a string be stored in the registry, text file, or even if the string was disguised and present in the LISP code itself...

On this topic, I posted some tips on how to spot malicious code in programs here, might be useful to some.

Andrea

  • Water Moccasin
  • Posts: 2372
Re: Storing variables
« Reply #11 on: March 29, 2011, 08:11:22 AM »
I strongly suggest to not use the "USERS*" variables..
for the simple reason that to many program use it.

we had several problem with that on our offices..
and cause conflictual uncompatible problem between thirdparty software.

LDATA = saved by drawing
Xdata = saved by Entity
Vl-Registry-write = saved by PC
setenv = save data on registry without having administrative right.
(open "x:\\config\\yourfile.txt" "w") = allow you to store anything and share those info with your collegue over a network if you want. sure you can use any king of extension file and eaven...no extension.

so it is depend what the objective is.

Regards.

Keep smile...

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Storing variables
« Reply #12 on: March 29, 2011, 08:54:22 AM »

Personally I'd use XRecords ... the data sounds like it should stay with the document.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #13 on: March 29, 2011, 09:56:27 AM »
Quote
LDATA = saved by drawing
Xdata = saved by Entity
Vl-Registry-write = saved by PC
setenv = save data on registry without having administrative right.
(open "x:\\config\\yourfile.txt" "w") = allow you to store anything and share those info with your collegue over a network if you want. sure you can use any king of extension file and eaven...no extension.
This is a great breakdown for my feeble mind, thanks

I am reading AfraLisp Dictionary
What is an example I could use a dictionary for?  (not code, just an idea)

From what I understand:
  - Xdata appends to an existing entity assoiciation list
  - Dictionary is a container of entities or objects
  - Xrecord is the assoiciated list (dotted pair) of an entity or object inside of a dictionary
  - ENTMAKEX is act of creating an object without an owner.  Meaning it is a man made dictionary and a man made entity (inside this dictionary)...  The meaning of "no owner" is that this container (dictionary) did not exist until I created it, so it is not associated to any existing dictionary?
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

laidbacklarry

  • Guest
Re: Storing variables
« Reply #14 on: March 29, 2011, 01:18:37 PM »
Just another thought... XData can also be attached to Layers (and other Table objects). Attach your data to Layer "0" and it's pretty secure since you can't delete layer 0.

We started using this technique as soon as XData was introduced, before Dictionaries, LData, etc., and as long as you don't exceed the XData limit of 16K (I think), it works well. We store over 200 of our application specific "system" variables with this method.

Text files (.ini files) are used to store the initial settings, but if the variables need to change value from drawing to drawing, this system works.

We also use XData attached to entities and blocks. If XData had existed in the mid-80s, there would have no need for us to use attributes.

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #15 on: March 31, 2011, 10:33:54 AM »

Why does the 'P' remaine for a return?  If I put double space vs a single space the 'P' disapears


Quote
(defun c:exdata ( / )

(setq lastent (entget (car (entsel))))

(regapp "SHEETDATA")
                                           
(setq
  exdata '((-3 ("SHEETDATA" (1000 . "SheetTitle"))))
)
 
(setq newent
  (append lastent exdata)
)

(entmod newent)

(princ)
)


(defun c:test ( / )

  (vl-load-com)

  (setq
    acadObject         (vlax-get-acad-object)
    acadActiveDocument      (vla-get-ActiveDocument acadObject)
    acadPaperSpace      (vla-get-PaperSpace acadActiveDocument)
    acadLayout         (vla-get-Layout acadPaperSpace)

  )

  (setq ss (ssget "_x" '((0 . "MTEXT" ) (-3 ("SHEETDATA")))))

  (setq
    ssEnt   (ssname ss 0)
    sheetTitle   (cdr (assoc 1 (entget ssEnt)))
  )

  (setq sheetTitle (vl-string-translate "\\P" " " sheetTitle))     <---  If I put a double space here the 'P' disapears 
  (setq sheetTitle (vl-string-translate "\\pxqc;" ""  sheetTitle))

    (print sheetTitle)

    (princ)
)
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #16 on: March 31, 2011, 10:40:14 AM »
Because vl-string-translate switches individual characters, look into the vl-string-subst function.
« Last Edit: March 31, 2011, 11:57:06 AM by Lee Mac »

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #17 on: March 31, 2011, 11:12:52 AM »
If it is individual then why does it work on

Code: [Select]
(setq sheetTitle (vl-string-translate "\\pxqc;" ""  sheetTitle))  the entire "\\pxqc;" is removed

and why does it remove both \\ but leave the P?

Yes, I am starting to look in to the function   (vl-string-subst)  trying to learn how to loop thru a string right now.


  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #18 on: March 31, 2011, 11:24:34 AM »
If it is individual then why does it work on

Code: [Select]
(setq sheetTitle (vl-string-translate "\\pxqc;" ""  sheetTitle))  the entire "\\pxqc;" is removed

I'm guessing because it doesn't determine which character to translate to which, since there is no destination character set, hence it just translates them all to empty strings.

EDIT: On testing, it doesn't translate any characters for me:

Code: [Select]
_$ (vl-string-translate "\\pxqc;" "" "CAD\\pxqc;Man")
"CAD\\pxqc;Man"

Which is more likely what I would've expected.

and why does it remove both \\ but leave the P?

"\\" is one character in LISP ( \ )

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #19 on: March 31, 2011, 11:34:05 AM »
Yes, I am starting to look in to the function   (vl-string-subst)  trying to learn how to loop thru a string right now.

As a nudge in the right direction, this is what I use for string substitution in Visual LISP:

Code: [Select]
(defun LM:StringSubst ( new old string / l i ) (setq l (strlen new) i 0)
  (while (setq i (vl-string-search old string i))
    (setq string (vl-string-subst new old string i) i (+ i l))
  )
  string
)

For complex substitutions I use RegularExpressions (RegExp)

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #20 on: March 31, 2011, 11:37:38 AM »
el-Crap-o

I have to first center the text for it to not remove the //pxqc;   :ugly:


Ok, well at least I learned the // is one character, which makes no sense to me but I guess it is what it is, I'll accept it and move on.

Sorry for wasting your time.
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #21 on: March 31, 2011, 11:39:42 AM »
Code: [Select]
(defun LM:StringSubst ( new old string / l i ) (setq l (strlen new) i 0)
  (while (setq i (vl-string-search old string i))
    (setq string (vl-string-subst new old string i) i (+ i l))
  )
  string
)
Thanks
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #22 on: March 31, 2011, 11:42:23 AM »
Ok, well at least I learned the // is one character, which makes no sense to me but I guess it is what it is, I'll accept it and move on.

Note that it is the "\\" string which is interpreted as a single backslash. This is because the usual use of a backslash is within a escape character, such as "\n" for newline or "\t" for tab etc. Hence when we want to use a backslash on its own, we must double it up so that any following characters aren't interpreted as escape characters.

Sorry for wasting your time.

Not at all - I like questions I can answer  :evil:
« Last Edit: March 31, 2011, 11:54:12 AM by Lee Mac »

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #23 on: April 01, 2011, 11:46:30 AM »
Lee

I am strugaling to understand, I think I am close but not sure.  I am not sure if I am even passing the right info to the right variables...

Code: [Select]
  (defun c:test ( / ent entString pattern string)

    (setq ent (car (entsel)))
    (setq entString (cdr (assoc 1 (entget ent))))

    (setq pattern "\\P")
    (setq string " ")

    (setq l (strlen entString) i 0)    [color=red]<-----  I am not sure how this works[/color]
   
    (while
      (setq i (vl-string-search pattern string i))
      (setq entString (vl-string-subst string pattern entString i) i (+ i l))  [color=red]<----- nor this[/color]
    )


(print entString)
   
(princ)
)
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #24 on: April 01, 2011, 04:14:13 PM »
Ah - you broke the sub! :-P

You could call it like this:

Code: [Select]
(defun c:test ( / ent str )
  (if
    (and
      (setq ent (car (entsel)))
      (setq str (cdr (assoc 1 (entget ent))))
    )
    (setq str (LM:StringSubst " " "\\P" str))
  )
)

(defun LM:StringSubst ( new old string / l i ) (setq l (strlen new) i 0)
  (while (setq i (vl-string-search old string i))
    (setq string (vl-string-subst new old string i) i (+ i l))
  )
  string
)

To understand how the sub works, read all the documentation on the vl-string-search and vl-string-subst functions and all the arguments those functions can take.



cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #25 on: April 04, 2011, 09:08:15 AM »
Lee
I have stared at your code all weekend (well for a few hours anyway)

Code: [Select]
(setq str (LM:StringSubst " " "\\P" str))    [color=red]<----  What are you doing here?[/color]
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #26 on: April 04, 2011, 10:05:38 AM »
Hi CADMan,

On the line to which you referred, I am passing the necessary arguments (or parameters) to the subfunction called 'LM:StringSubst'. My subfunction takes three arguments: 'new', 'old' and 'string' which represent respectively the new string to be substituted, the pattern string to be matched and replaced, and the string in which to do the replacing. When the subfunction is called, the symbols 'new', 'old' and 'string' will hold the argument data passed to the subfunction.

Think of the subfunction as just another LISP function. For example, I'm sure you are familiar with the LISP function '+'. This function takes one or more numerical arguments and proceeds to add them together and return the sum:

Code: [Select]
(+ arg1 arg2 ... argN)
Returns:   arg1 + arg2 + ... + argN

But, say we wish to have a function that will return the supplied argument plus 2, we could define such a function in the following way:

Code: [Select]
(defun Add2 ( x ) (+ x 2))
Now, the above function takes a single numerical argument, denoted by the symbol 'x', and returns that supplied number incremented by 2. Just as we called the '+' function, we would call our subfunction in the following way:

Code: [Select]
(Add2 5)
Returns: 7

Hence in my example, I call the function 'LM:StringSubst' with the required arguments:

Code: [Select]
(LM:StringSubst " " "\\P" str)
Returns: the value of the variable 'str' with "\\P" substituted for " "

Lee


cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #27 on: April 04, 2011, 11:27:18 AM »
Hi Lee

I have the idea of what you are doing, the examples you give me make sense but they are basic examples using defun
and
your code uses setq

I ;|greyed out the subfunction|; ran it and it is looking for a function, this is interesting.  I am not sure how this is happening and I don't know enough to ask a logical question to pinpoint the answer I am looking for.  If I could see some more documentation or examples of this concept this would be great.

Is there a specific topic in the help menu, is there a good "key word" I can look for or any websites that discuss this concept.

Thanks
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

GDF

  • Water Moccasin
  • Posts: 2059
Re: Storing variables
« Reply #28 on: April 04, 2011, 11:35:43 AM »
Hmmm... but that 'danger' would exist should a string be stored in the registry, text file, or even if the string was disguised and present in the LISP code itself...

On this topic, I posted some tips on how to spot malicious code in programs here, might be useful to some.

Thanks for the info. Well written.
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #29 on: April 04, 2011, 11:38:15 AM »
I have the idea of what you are doing, the examples you give me make sense but they are basic examples using defun and your code uses setq

My use of setq just sets the return of the subfunction to a symbol in the calling function, just as we might do this:

Code: [Select]
(setq x (+ 1 2 3))
Where 'x' now holds the return of the '+' function (i.e. 'x' has the value 6)

In a similar way I could do this:

Code: [Select]
(setq x (LM:StringSubst " " "\\P" str))
And 'x' would hold the string returned by my function.

I ;|greyed out the subfunction|; ran it and it is looking for a function, this is interesting.  I am not sure how this is happening and I don't know enough to ask a logical question to pinpoint the answer I am looking for.  If I could see some more documentation or examples of this concept this would be great.

Correct - the function needs to be defined before it can be called, hence we define the function using the defun expression.

Perhaps have a read of these topics:

Using Defun

Functions with Arguments
« Last Edit: April 04, 2011, 11:57:47 AM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #30 on: April 04, 2011, 11:40:12 AM »
Hmmm... but that 'danger' would exist should a string be stored in the registry, text file, or even if the string was disguised and present in the LISP code itself...

On this topic, I posted some tips on how to spot malicious code in programs here, might be useful to some.

Thanks for the info. Well written.

Thanks Gary  :-)

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #31 on: April 04, 2011, 01:59:16 PM »
I have not read the links you posted yet, so if my question is covered there I appologize

I guess my question is, what defines LM:StringSubst as a function?  '+' is a built in functions used by LISP but 'LM:StringSubst' is defined by you.  I think this is where I am getting lost.  Is it in the structure of how your wrote the list itself?


Again if this is covered in the links just tell me to "read on" and tonight I will do my homework.

Thanks
Lee
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #32 on: April 04, 2011, 05:37:22 PM »
Ok, I think I have it but still have some questions

I removed the (setq str) from
Code: [Select]
(setq str (LM:StringSubst " " "\\P" str))and the function still works.
Code: [Select]
(LM:StringSubst " " "\\P" str)So when it looks like this I understand it. the setq was throwing me.
from your explainationg of 'x' holding the value of 6, this got me to remove the the 'str' to make it a global variable so when I type at the command prompt !str I got the result of "line1 line2 line3" as you said, holds the value.  I am with it so far.

The only reason I can think of for creating the 'str' variable (setq str) is for future use of the string, which we do not use or need here??? (is that a correct statment?) so it can be removed?

The tricky part for me now is lisp runs in a line by line format.  so how does the (setq str) know what the string is when the sub-function runs after the (setq str) line?  How does it go back and set itself to "line1 line2 line3".
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

CAB

  • Global Moderator
  • Seagull
  • Posts: 10395
Re: Storing variables
« Reply #33 on: April 04, 2011, 07:56:40 PM »
The function LM:StringSubst returns a string value so the line
Code: [Select]
(setq str (LM:StringSubst " " "\\P" str))stores that string value in the variable str.

So put the setq back as you found it. :-)
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.

chlh_jd

  • Guest
Re: Storing variables
« Reply #34 on: April 04, 2011, 11:51:20 PM »
Very exciting discussion , I learn a lot .
Since this , I always save my Global Variables by the 'TEXT' way , save in the '.ini' file . :-)


cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #35 on: April 05, 2011, 08:47:11 AM »
Hi CAB

Yes, I have left the setq in place, I can only assume that you gurus know what you are doing,  :-)
I am experimenting trying to understand how the code works.  I don't see the str later in the program so I don't understand why it is there and the function seems to work fine without it.  I am also trying not to be the annoying newb with too many questions, I am bent on learning this stuff.  Anyways, I will understand it soon enough, I just need to find my lightswitch.

This has given me a better understanding how to use arguments, (that does not include my wife.  She always wins, pees me off it does.)
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #36 on: April 05, 2011, 08:54:02 AM »
I guess my question is, what defines LM:StringSubst as a function?  '+' is a built in functions used by LISP but 'LM:StringSubst' is defined by you.  I think this is where I am getting lost.  Is it in the structure of how your wrote the list itself?

The 'defun' is what defines it as a function - those earlier links should help you understand this  :-)

The only reason I can think of for creating the 'str' variable (setq str) is for future use of the string, which we do not use or need here??? (is that a correct statment?) so it can be removed?

OK, I can see how that might be misleading - in my example code, if run on its own, you wouldn't necessarily need this extra variable assigment, since the last expression evaluated is the 'LM:StringSubst' function and so the return of this function is printed to the command line. However, I assumed this would not be the final product of what you were trying to achieve, hence I assigned the return to the variable 'str' for future use in the code.

The tricky part for me now is lisp runs in a line by line format.  so how does the (setq str) know what the string is when the sub-function runs after the (setq str) line?  How does it go back and set itself to "line1 line2 line3".

LISP runs 'line by line' within the function definition, so if we call another function, the LISP now runs line by line within said function and then returns to the point at which the function was called. To illustrate how the code is evaluated, use the 'animate' option as part of the VLIDE debugging tools - tutorial here.

To understand how the 'setq' statement works, you need to understand that a LISP function will return the value of the last expression evaluated.

Looking back at my subfunction:

Code: [Select]
(defun LM:StringSubst ( new old string / l i ) (setq l (strlen new) i 0)
  (while (setq i (vl-string-search old string i))
    (setq string (vl-string-subst new old string i) i (+ i l))
  )
  string
)

Notice that I have the local variable 'string' on its own at the end of the code. This holds the value of the modified string and is the last expression in the function and hence the value of string is returned by the function, just as the sum of supplied numbers is returned by the '+' function.

The function LM:StringSubst returns a string value so the line
Code: [Select]
(setq str (LM:StringSubst " " "\\P" str))stores that string value in the variable str.

So put the setq back as you found it. :-)

Thanks Alan for the support  :-)
« Last Edit: April 05, 2011, 08:57:51 AM by Lee Mac »

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #37 on: April 05, 2011, 08:55:33 AM »
I am also trying not to be the annoying newb with too many questions, I am bent on learning this stuff.  Anyways, I will understand it soon enough, I just need to find my lightswitch.

That doesn't even come into the equation, ask away - that is what this forum was created for  :-)

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #38 on: April 05, 2011, 11:38:25 AM »
Hi Lee

Quote
I assumed this would not be the final product of what you were trying to achieve, hence I assigned the return to the variable 'str' for future use in the code.
  Yes, this is the answer I am looking for.  Very good

Quote
The 'defun' is what defines it as a function - those earlier links should help you understand this
Yes, I understand this part, no worries.  I did not ask my question right, let me try again.

When I run this by itself
Code: [Select]
(defun c:test ( / ent str )
  (if
    (and
      (setq ent (car (entsel)))
      (setq str (cdr (assoc 1 (entget ent))))
    )
    (setq str (LM:StringSubst " " "\\P" str))
  )
)

I get this at the command line
Quote
Command: test
Select object: *Cancel*
no function definition: LM:STRINGSUBST
It is looking for LM:STRINGSUBST, how does it know to look for this?  What makes it look for LM:STRINGSUBST?  Is it in the way the list is structured?  Because '+' is a AutoLisp functions that adds but LM:STRINGSUBST is nothing, I can change the spelling and it will look for different spelling too AC:NEWSPELLING
(defun c:test ( / ent str )
  (if
    (and
      (setq ent (car (entsel)))
      (setq str (cdr (assoc 1 (entget ent))))
    )
    (setq str (AC:NEWSPELLING " " "\\P" str))
  )
)
Quote
Command: TEST
Select object: *Cancel*
no function definition: AC:NEWSPELLING
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #39 on: April 05, 2011, 11:49:35 AM »
Quote
That doesn't even come into the equation, ask away - that is what this forum was created for

Sometimes I think it does, because it is hard to put into text what is in ones mind, specialy when one is limited in experiance and does not know how to express ones thought properly.  You spent time and effort in explaining to me something that seems simple and logical to you when I am looking for a different answer but not sure how to express my thoughts without just rewording my question.  I don't want to wear anyone out.

Thanks for the reassurance
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9719
Re: Storing variables
« Reply #40 on: April 05, 2011, 11:55:28 AM »
cadman6735,
preform a search for my (Se7en) "refine your methods" document in the "teach" me forum. it should answer your last  questions.
TheSwamp.org (serving the CAD community since 2003)

Donate to TheSwamp.org

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #41 on: April 05, 2011, 01:14:02 PM »
It is looking for LM:STRINGSUBST, how does it know to look for this?  What makes it look for LM:STRINGSUBST?  Is it in the way the list is structured?

It is the position of the symbol 'LM:STRINGSUBST' in the code that informs the interpreter (the facility that turns the code into 'machine language' so to speak) to look for a function defined as 'LM:STRINGSUBST'. When a symbol is placed immediately after an opening bracket, it is interpreted as a function to be evaluated.

Because '+' is a AutoLisp functions that adds but LM:STRINGSUBST is nothing, I can change the spelling and it will look for different spelling too AC:NEWSPELLING

In the same way that we give other symbols meaning when we assign variables:

Code: [Select]
(setq x 1)
The symbol 'x' is arbitrary, and could very well be renamed to 'y', however, this is irrelevant since it is merely a symbol to help us structure the code. From the above expression we know that 'x' is a variable holding a value of 1, hence we might use in the following way:

Code: [Select]
(1+ x)
However, consider that the symbol 'x' could very well be a defined as a function instead. We could have defined it as follows:

Code: [Select]
(defun x ( a ) (+ a 3))
In which case the symbol 'x' is now a function that adds three to the supplied argument. Now, of course, if we attempt to use the symbol 'x' in our previous expression we receive an error:

Code: [Select]
_$ (defun x ( a ) (+ a 3))
X
_$ (1+ X)
; error: bad argument type: numberp: #<USUBR @13df96f4 X>

Because the function '1+' was expecting a numerical argument, not a function. Used as a function, however:

Code: [Select]
_$ (x 5)
8

Note that this is because the symbol 'x' points to a user defined subroutine (USUBR), and hence this subroutine is evaluated when 'x' is used as a function.

If we tried to use another symbol in place of 'x', say 'y', we receive the following error:

Code: [Select]
_$ (y 5)
; error: no function definition: Y

Since the symbol 'y' has no value at this point.



OK, so I realise that this post isn't as structured as it could be, and hopefully you can glean more from Se7en's document to help with your understanding; but the point I am attempting to make is that the symbols we use for variables and functions are merely aids for the construction of a program, they are arbitrary - it is the value they point to which is relevant:

Code: [Select]
_$ (setq a 1 b "CAD" c 1+ d (eval (defun x ( a ) (+ a 3))) e 1.2 f '(1 2 3))

_$ (type a)
INT
_$ (type b)
STR
_$ (type c)
SUBR
_$ (type d)
USUBR
_$ (type e)
REAL
_$ (type f)
LIST

I hope this helps with your understanding, if you still have questions, please do ask.

Lee

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #42 on: April 05, 2011, 01:41:18 PM »
Quote
When a symbol is placed immediately after an opening bracket, it is interpreted as a function to be evaluated.
I remember reading this early in my first weeks of starting my LISP journy, but I assosiated to actual built in Lisp functions such as '+', 'setq' etc ...  This is the answer that I am looking for, this  clears it for me.  Now I just need to build upon my new found knowledge.

Thanks for being patient.


Se7en:
I found your post but the link is broke, I downloaded the PDF, is this the same thing?
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #43 on: April 05, 2011, 02:00:45 PM »
Quote
When a symbol is placed immediately after an opening bracket, it is interpreted as a function to be evaluated.
I remember reading this early in my first weeks of starting my LISP journy, but I assosiated to actual built in Lisp functions such as '+', 'setq' etc ...  This is the answer that I am looking for, this  clears it for me.  Now I just need to build upon my new found knowledge.

Thanks for being patient.

You're welcome CADMan, happy that I could clarify things for you with my incohesive waffling  :lol:

I'm sure Se7en's document will be the icing on the cake  :wink:

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9719
Re: Storing variables
« Reply #44 on: April 05, 2011, 02:05:57 PM »
...
Se7en:
I found your post but the link is broke, I downloaded the PDF, is this the same thing?

The PDF is what you want. Read and study it; that document was written to be used by both beginers and "more advanced" users (I touch on a lot of subjects in that document). That document (because of how i wrote it) took me almost two years to write. Its almost sick that i put that much work into something most people just read and dismiss after the first read.

Good luck, and i hope you enjoy it.
TheSwamp.org (serving the CAD community since 2003)

Donate to TheSwamp.org

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #45 on: April 06, 2011, 08:55:48 AM »
Se7en
I have read only half of your document so far, I like the concept.  This seems to be like building modules in Visual Basic.  (I know nothing about VBA, this will be my next venture) but seems to follow the module concept as I would understand it.

I am going to have some questions when I am done reading it, would you be opposed if I stated a new thread to discuss this topic and get your document back to the top of the thread pile so others can join?
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

Lee Mac

  • Seagull
  • Posts: 12514
  • London, England
Re: Storing variables
« Reply #46 on: April 06, 2011, 10:02:54 AM »
(I know nothing about VBA, this will be my next venture)

I'd steer clear, VBA is dead.

cadman6735

  • Bull Frog
  • Posts: 255
  • Life is all about the attitude.
Re: Storing variables
« Reply #47 on: April 06, 2011, 11:02:27 AM »
Quote
I'd steer clear, VBA is dead.
Really?  Revit is programed using VBA or C# I am going in what ever direction Revit is programmed in, so I will look into your comment and adjust accordingly.

Thanks for the heads up.
  Ability is what you're capable of doing.
  Motivation determines what you do.
  Attitude determines how well you do it.

    Lou Holtz
----------------------------------------------

  Revit Certified Professional

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9719
Re: Storing variables
« Reply #48 on: April 06, 2011, 01:29:20 PM »
Se7en
I have read only half of your document so far, I like the concept.  This seems to be like building modules in Visual Basic.  (I know nothing about VBA, this will be my next venture) but seems to follow the module concept as I would understand it.

I am going to have some questions when I am done reading it, would you be opposed if I stated a new thread to discuss this topic and get your document back to the top of the thread pile so others can join?

Hi cadman6735,
Yes sorta. All programing has the ability to build modules (as you put it) so the concepts i wrote about are concepts for all (worthwile) programing languages.

I dont do much lisp any more so i dont know how well i will be at answering spcific questions but i will definatly try to help as much as i can.


BTW, Revit is most likely written in C++ (but the language that Revit is written in has nothing to do with it). The API is what you are interisted in; you use C# to access the API for Revit. Search Wikipedia for "Application programming interface".
TheSwamp.org (serving the CAD community since 2003)

Donate to TheSwamp.org