Ptr_Persistent

Started by snowsnowsnow, April 28, 2016, 12:20:23 AM

Previous topic - Next topic

snowsnowsnow

Consider this code, from a Tech DB article about pointers:

Code (winbatch) Select

#DefineFunction GetRandom(task)
   ; Note this function keeps track of how many times it was
   ; called by using a persistent varaible accessed via persistent
   ; pointer, returned by the ptrPersistent function.

   ptr_Count = PtrPersistent(my_counter, 0)
   If task == "GET"
      *ptr_Count = *ptr_Count+1
      Return(Random(1000))
   EndIf
   If task == "REPORT"
      Return *ptr_Count
   EndIf
   Return
#EndFunction

a1 = GetRandom("GET")
a2 = GetRandom("GET")
a3 = GetRandom("GET")
a4 = GetRandom("GET")
a5 = GetRandom("GET")

count = GetRandom("REPORT")
Message("GetRandom Report", StrCat("GetRandom function was used ",count," times"))
Exit


It works as advertised, but my question is: "What is my_counter?"

I.e., the call to PtrPersistent() references "something" called "my_counter", but that string isn't used anywhere else in the program.  I tried to display the value of "my_counter", but it came back as an undefined variable.  So, it seems what you really get here is a pointer to an otherwise inaccessible variable.  Is that correct?

td

My_Counter a variable but the name has been changed to protect the innocent.  If you you used WinBatch Studio, all would be made clear.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on April 28, 2016, 06:43:17 AM
My_Counter a variable but the name has been changed to protect the innocent.  If you you used WinBatch Studio, all would be made clear.

I tried, but TBH, I don't get WB Studio.

I'm guessing it has something to do with the Watch Window, but how do I add variables to the list?

td

My apologies for not being explicit.  If you load your example into WBS and press the F5 key, the variables windows will automagically appear at the bottom of the editor.   Once your script has completed execution you will notice the names and values of all the variables of your script displayed in the variables window.   One of the those variables will have an 'illegal' name in WIL syntax.  The name will bear some resemblance to 'my_counter' and will have a value that looks suspiciously like the value you would expect for your 'my_counter' variable.

   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on April 28, 2016, 11:44:44 AM
My apologies for not being explicit.  If you load your example into WBS and press the F5 key, the variables windows will automagically appear at the bottom of the editor.   Once your script has completed execution you will notice the names and values of all the variables of your script displayed in the variables window.   One of the those variables will have an 'illegal' name in WIL syntax.  The name will bear some resemblance to 'my_counter' and will have a value that looks suspiciously like the value you would expect for your 'my_counter' variable.



Yes, verified.  Yup, that's what happens.

Begging the question: Why?

I assume there is some reason why you don't want people to be able to access it directly - that is, they should only access it via the pointer.

Which is fine.  But then why make them specify the name at all?  Why not just have it be like:

ptr_my_Counter = PtrPersistent(0)


td

It fills the same role that a C/C++ variable declared with the 'static' storage specifier inside a C/C++ function does.  Basically, it is private to the function like other function declared/instantiated variables but retains its value between calls to the function.  The name mangling enforces the privacy.   

I guess if you don't see value in its use then move on; otherwise, it is another tool in the box  to you help write maintainable and reliable scripts.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on April 29, 2016, 06:50:22 AM
It fills the same role that a C/C++ variable declared with the 'static' storage specifier inside a C/C++ function does.  Basically, it is private to the function like other function declared/instantiated variables but retains its value between calls to the function.  The name mangling enforces the privacy.   

I guess if you don't see value in its use then move on; otherwise, it is another tool in the box  to you help write maintainable and reliable scripts.

Yes, yes, I understand all that.  In fact, I've often thought that it would help the documentation if you said something like that - something like "If you are familiar with C, then you will recognize this as being like a 'static' variable inside a function".

Now, moving past that, ...  I'm inferring from your comments that the variable is, in fact, global, but it is name-mangled so that it can't be accessed (by anyone anywhere) by name.  The thing I just don't get, is why pass in a name that isn't used anywhere else in the program.  I.e., in most programming constructs, when we (the programmer/user) are called upon to make up a name for something, it is because we are going to use that name at least twice.  I.e., at least once (usually only once) to define it, and at least once (usually more than once) to use it.  It just seems odd that the programmer is asked to make up a name and then that name isn't used anywhere else.  In fact, the variable-name (as it is referred to in the documentation for PtrPersistent()) isn't a variable-name; it is really just a "tag" used in the construction of the object.

Couldn't the system just auto-generate the name/tag?

Anyway, that's my 2 cents worth...

td

??
You need to properly identify the storage you are targeting just like any other variable and preferably use a meaningful identifier while you are at it.

With regard to referencing C/C++ in WIL documentation, a large proportion of WinBatch user are not fluent C/C++ programmers so referencing those language's features would only add to the confusion.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on April 29, 2016, 02:44:05 PM
??
Sorry to hear that I have confused you.  What part of my post was unclear?
Quote from: td on April 29, 2016, 02:44:05 PM
You need to properly identify the storage you are targeting just like any other variable and preferably use a meaningful identifier while you are at it.
Yes. I get it now.  I think this means that you need to pass in some sort of user-conceived tag value in so that the Ptr_Persistent() function can setup the storage.  So, you can't really define that function to not take a tag argument at all.  I get that now.

It still seems like it would be clearer if it were defined (in the documentation) as a "tag", rather than as a "variable name", since no variable with that name is created.
Quote from: td on April 29, 2016, 02:44:05 PM
With regard to referencing C/C++ in WIL documentation, a large proportion of WinBatch user are not fluent C/C++ programmers so referencing those language's features would only add to the confusion.

I get what you're saying, but do note that there is at least one reference to C already in the various docs/tuts for pointers in WinBatch, so it is not unheard of.  It is not necessary for the novice user to understand these references, but they are there for the benefit of those who do.  Specifically, I am talking about the general introduction to why the * and & symbols are used; the docs state that it is because that's the way they are used in C.

td

Quote from: snowsnowsnow on April 30, 2016, 06:41:31 AM
Sorry to hear that I have confused you.  What part of my post was unclear?
'Confused' no but 'incredulous' yes.

Quote
Yes. I get it now.  I think this means that you need to pass in some sort of user-conceived tag value in so that the Ptr_Persistent() function can setup the storage.  So, you can't really define that function to not take a tag argument at all.  I get that now.

It still seems like it would be clearer if it were defined (in the documentation) as a "tag", rather than as a "variable name", since no variable with that name is created.
If it pleases you to think of it that way, do so.  We always appreciate suggestions.
   
Quote
I get what you're saying, but do note that there is at least one reference to C already in the various docs/tuts for pointers in WinBatch, so it is not unheard of.
Two wrongs don't make a right.

Quote
It is not necessary for the novice user to understand these references, but they are there for the benefit of those who do.  Specifically, I am talking about the general introduction to why the * and & symbols are used; the docs state that it is because that's the way they are used in C.
It is not a question of the novice user.  WinBatch has many long standing users that have very little to no familiarity with languages like C.  They are much more likely to be familiar with VB, DOS batch language, and  C#.

Writing technical documentation is an art.  Introducing to much information can be as bad or worse than not providing enough. In hind sight, I wish we had not used the term 'pointer' when adding reference functionality to WinBatch because while WinBatch 'pointer's may share a little bit of semantics with the C language, they are far from identical semantically or syntactically.   
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

snowsnowsnow

Quote from: td on May 02, 2016, 07:20:13 AM
Quote from: snowsnowsnow on April 30, 2016, 06:41:31 AM
Sorry to hear that I have confused you.  What part of my post was unclear?
'Confused' no but 'incredulous' yes.

OK.  6 of 1, ...

Quote
Quote from: snowsnowsnow on April 30, 2016, 06:41:31 AM
Yes. I get it now.  I think this means that you need to pass in some sort of user-conceived tag value in so that the Ptr_Persistent() function can setup the storage.  So, you can't really define that function to not take a tag argument at all.  I get that now.

It still seems like it would be clearer if it were defined (in the documentation) as a "tag", rather than as a "variable name", since no variable with that name is created.
If it pleases you to think of it that way, do so.  We always appreciate suggestions.
That's what I am here for - to give suggestions.
   
Quote
Quote from: snowsnowsnow on April 30, 2016, 06:41:31 AM
I get what you're saying, but do note that there is at least one reference to C already in the various docs/tuts for pointers in WinBatch, so it is not unheard of.
Two wrongs don't make a right.
True.  But 3 lefts do.

Quote
Quote from: snowsnowsnow on April 30, 2016, 06:41:31 AM
It is not necessary for the novice user to understand these references, but they are there for the benefit of those who do.  Specifically, I am talking about the general introduction to why the * and & symbols are used; the docs state that it is because that's the way they are used in C.
It is not a question of the novice user.  WinBatch has many long standing users that have very little to no familiarity with languages like C.  They are much more likely to be familiar with VB, DOS batch language, and  C#.
Got it.
Quote
Writing technical documentation is an art.  Introducing to much information can be as bad or worse than not providing enough. In hind sight, I wish we had not used the term 'pointer' when adding reference functionality to WinBatch because while WinBatch 'pointer's may share a little bit of semantics with the C language, they are far from identical semantically or syntactically.
Point taken, but, FWIW, my impression of the whole pointers-in-WB thing is that unless you are familiar with the underlying C (or assembler) concept, it won't make any sense to you.  Even with my C background, I still didn't get it for quite some time.

Just out of curiosity, what would be, say, the VB (or C#) equivalent of WB's pointers?
(Note that I've never used, nor do I know much about, either of these languages)