Sign in to follow this  
Followers 0
pdaughe

Dynamic Variable Allocation

9 posts in this topic

#1 ·  Posted (edited)

I tried to post this in the "Bug Reports" forum, but I didn't have permission to do so. When you run the following script, note that the dynamic allocation of the array is successful, as far as the ASSIGN function is concerned (ASSIGN returns 1, indicating success), and the dynamic allocation of the array is successful as far as the IsDeclared function is concerned.

However, the script fails on the "$List[1] = 1" assignment statement due to a "variable being used without being declared" message.

Note that I also included the dynamic allocation of a simple variable, which works fine.

It may be that the dynamic allocation of arrays is not supported. If so, it seems the Assign and IsDeclared functions should return 0. On the other hand, AutoIT is such a powerful language that the dynamic allocation of arrays would be a significant feature.

Edit: I am currently running the 3.2.2.0 RC3 Beta.

Global $Item_Count = 20

$Created_Array = "$List[" & $Item_Count & "]"

$Allocate = Assign ($Created_Array, 5, 2)

If Not IsDeclared ($Created_Array) Then MsgBox (0 , "Dynamic Allocation", "Failed")

If $Allocate Then
   MsgBox (0, "Dynamic Allocation", "Array successfully allocated")
Else
   MsgBox (0, "Dynamic Allocation", "Unable to allocate array")
EndIf

$Allocate = Assign ("Simple_Variable", "Hello", 2)
MsgBox (0, "Dynamic Allocation", "Simple Variable = " & $Simple_Variable)

$Simple_Variable = "Goodbye"

MsgBox (0, "Assignment to Simple Variable", "Simple Variable = " & $Simple_Variable)

$List[1] = 1

MsgBox (0, "Assignment to Array Variable", "Name = " & $Created_Array & @CRLF & "Value = " & $List[1])
Edited by pdaughe

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

per help

Global $variable

If Assign("variable", "Hello") Then MsgBox(4096, "", $variable) ; Will print "Hello"

you have to globalize ( declare ) the assigned variable first

and, as always..... an Array must be declared first

Global $Item_Count = 20, $Simple_Variable, $Created_Array, $List[2]

$Created_Array = "$List[" & $Item_Count & "]"

$Allocate = Assign ($Created_Array, 5, 2)

If Not IsDeclared ($Created_Array) Then MsgBox (0 , "Dynamic Allocation", "Failed")

If $Allocate Then
   MsgBox (0, "Dynamic Allocation", "Array successfully allocated")
Else
   MsgBox (0, "Dynamic Allocation", "Unable to allocate array")
EndIf

$Allocate = Assign ("Simple_Variable", "Hello", 2)
MsgBox (0, "Dynamic Allocation", "Simple Variable = " & $Simple_Variable)

$Simple_Variable = "Goodbye"

MsgBox (0, "Assignment to Simple Variable", "Simple Variable = " & $Simple_Variable)


$List[1] = 1

MsgBox (0, "Assignment to Array Variable", "Name = " & $Created_Array & @CRLF & "Value = " & $List[1])

8)

Edited by Valuater

NEWHeader1.png

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

I'm not sure what your trying to do, but Arrays are created with Dim/Local/Global...

maybe...

Global $Item_Count = 20, $List[$Item_Count]

$Created_Array = $List

$Allocate = Assign ($Created_Array, 5, 2)

If Not IsDeclared ($Created_Array) Then MsgBox (0 , "Dynamic Allocation", "Failed")

If $Allocate Then
   MsgBox (0, "Dynamic Allocation", "Array successfully allocated")
Else
   MsgBox (0, "Dynamic Allocation", "Unable to allocate array")
EndIf

$Allocate = Assign ("Simple_Variable", "Hello", 2)
MsgBox (0, "Dynamic Allocation", "Simple Variable = " & $Simple_Variable)

$Simple_Variable = "Goodbye"

MsgBox (0, "Assignment to Simple Variable", "Simple Variable = " & $Simple_Variable)

$List[1] = 1

MsgBox (0, "Assignment to Array Variable", "Name = " & $Created_Array & @CRLF & "Value = " & $List[1])

edit: sorry Valuater, i didnt see your post :P

Edited by piccaso

CoProc Multi Process Helper libraryTrashBin.nfshost.com store your AutoIt related files here!AutoIt User Map

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Edit to the above

help also states

flag [optional]controls the way that variables are assigned (add required options together):

0 = (default) Create variable if required

1 = Force creation in local scope

2 = Force creation in global scope

4 = Fail if variable does not already exist

so, on this i would agree that is does NOT have to be declared because apparently it can be declared by the flag in assign()

the helps "use" script shows it being declared

8)

Edit #2

edit: sorry Valuater, i didnt see your post

no... actually you made a better example than i did ( using the assign flags )

and neither of us know what the OP really is after

8)

Edited by Valuater

NEWHeader1.png

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Yes, the example from the help file shows the variable being explicitly declared, but note that one function of ASSIGN is to create the variable if it does not exist. The example script I posted does exactly that for the $Simple_Variable.

There are several data processing algorithms that "require" the dynamic allocation of storage, just as there are many alogrithms that "require" recursive invocation of functions. True, there are usually several ways to accomplish a given task, but it's far easier to compute N factorial or the Tower of Babels problem with recursion than without. Likewise, in a similar fashion, an array of arrays can be a very convenient data structure. I note that AutoIt even supports an array of arrays, although I haven't yet needed to use that capability. In my case I have a recursively called function (that is known to be limited in recursion depth) that must make the content of a list available to asynchronously executed functions (i.e. the normal argument/parameter correspondence cannot be used). The existence of the list "by name" however, it acceptable. Another way to accomplish this (in my case) I believe, is to in fact exploit AutoIt's ability to host an array of arrays. It will work for this alogrithm because I can place a fixed limit on the recursion depth; therefore I can declared a global variable, $List[20], for example where the maximum recursion depth is 20. Each element of the list will then be an array. Actually, now that I think I've written that, I realize that given AutoIt's ability to dynamically (at execution time) redimension an array, there is no reason to place a limit on the recursion depth.

The bottom line is that when you have a function that is called recursively, Global $Array[] inside the function doesn't meet the requirement, since the existing allocation of $Array would be reused. However, since each element of $Array can indeed be an array, the requirement can be met and in fact, this solution does not require the "by name" dependency.

My current implemenation was based on the dynamic creation of arrays and it took me a while to figure out what was going on because I was indeed checking the return code from ASSIGN and, before the array was used, checking for it's existence with IsDeclared. As the example script points out though, that doesn't work.

Edit: Well, I didn't get very far with using an array of arrays -- the array to be assigned to the array element must still be allocated in permanent (Global) storage. Here's perhaps a better example, and indeed a possible, though not attractive, solution:

Suppose you have a function that creates a listview. It is easy to make the listview available to other (even asynchronously executed) functions -- simply assign it's control id to a global variable. Now, suppose the function is called recursively. Easy, make the global variable an array, whose maximum subscript is the recursion level. You now have an array of control ids or, from another perspective, an array of arrays (viewing the ListView as an array of ListView items). You see, ListView allocates storage for ListView elements DYNAMICALLY and the storage is NOT associated with the local storage for a function.

Edited above paragraph for correctness: see post #8

Now, if you can envision that scenario (a function that dynamically creates ListViews), it's easy to see the need to dynamically allocate storage for other than simple variables. My bet is that AutoIt does support the dynamic allocation of arrays in permanent storage, but there's just a program anomaly -- I may of course be wrong, and I apologize if none of this makes sense!

Edited by pdaughe

Share this post


Link to post
Share on other sites

Yes, the example from the help file shows the variable being explicitly declared, but note that one function of ASSIGN is to create the variable if it does not exist. The example script I posted does exactly that for the $Simple_Variable.

There are several data processing algorithms that "require" the dynamic allocation of storage, just as there are many alogrithms that "require" recursive invocation of functions. True, there are usually several ways to accomplish a given task, but it's far easier to compute N factorial or the Tower of Babels problem with recursion than without. Likewise, in a similar fashion, an array of arrays can be a very convenient data structure. I note that AutoIt even supports an array of arrays, although I haven't yet needed to use that capability. In my case I have a recursively called function (that is known to be limited in recursion depth) that must make the content of a list available to asynchronously executed functions (i.e. the normal argument/parameter correspondence cannot be used). The existence of the list "by name" however, it acceptable. Another way to accomplish this (in my case) I believe, is to in fact exploit AutoIt's ability to host an array of arrays. It will work for this alogrithm because I can place a fixed limit on the recursion depth; therefore I can declared a global variable, $List[20], for example where the maximum recursion depth is 20. Each element of the list will then be an array. Actually, now that I think I've written that, I realize that given AutoIt's ability to dynamically (at execution time) redimension an array, there is no reason to place a limit on the recursion depth.

The bottom line is that when you have a function that is called recursively, Global $Array[] inside the function doesn't meet the requirement, since the existing allocation of $Array would be reused. However, since each element of $Array can indeed be an array, the requirement can be met and in fact, this solution does not require the "by name" dependency.

My current implemenation was based on the dynamic creation of arrays and it took me a while to figure out what was going on because I was indeed checking the return code from ASSIGN and, before the array was used, checking for it's existence with IsDeclared. As the example script points out though, that doesn't work.

Edit: Well, I didn't get very far with using an array of arrays -- the array to be assigned to the array element must still be allocated in permanent (Global) storage. Here's perhaps a better example, and indeed a possible, though not attractive, solution:

Suppose you have a function that creates a listview. It is easy to make the listview available to other (even asynchronously executed) functions -- simply assign it's control id to a global variable. Now, suppose the function is called recursively. Easy, make the global variable an array, whose maximum subscript is the recursion level. You now have an array of control ids or, from another perspective, an array of arrays (viewing the ListView as an array of ListView items). You see, ListView allocates storage for ListView elements DYNAMICALLY and, evidently, in permanent storage (although, not knowing the internals of AutoIT's function epilog, if the ListView is assigned to a local variable in the function, AutoIt may indeed automatically free the ListView storage).

Now, if you can envision that scenario (a function that dynamically creates ListViews), it's easy to see the need to dynamically allocate storage for other than simple variables. My bet is that AutoIt does support the dynamic allocation of arrays in permanent storage, but there's just a program anomaly -- I may of course be wrong, and I apologize if none of this makes sense!

In fact Assign is designed as stated in the doc to assign only variable not element of an array. There is a bug today as the assign is not returning an error.

This will be corrected in next beta 3.2.3.0. :P

Share this post


Link to post
Share on other sites

In fact Assign is designed as stated in the doc to assign only variable not element of an array. There is a bug today as the assign is not returning an error.

This will be corrected in next beta 3.2.3.0. :P

Thanks JPM! Is seems IsDeclared should also not return true as in the example script I posted. It sure would be nice is ASSIGN did work with arrays. And, (I'm certainly not arguing the point, but just pointing it out for the benefit of others), the documentation DOES NOT state that it doesn't work for arrays. The ASSIGN documentation only references the word VARIABLE. From the AutoIT Help file -- Language Reference - Variables, note that AutoIt (rightly I think) defines an array as variable. In fact, the IsArray function checks to see if a VARIABLE is an array TYPE. You can see, I think, how users like myself would expect ASSIGN to work with arrays. It may be helpful if under REMARKS for the ASSIGN function it was noted that ASSIGN does not work with variables of the array type.

Share this post


Link to post
Share on other sites

Well, it's late and we celebrate Christmas tomorrow, so there's no hope of me getting the project I've been working on done for my wife and family for their Christmas present. Thankfully, the SciTE editor prints AutoIT source code in color on our inkjet, and it won't require much Christmas paper to wrap!

I made an erroneous comment regarding my ListView analogy that I want to correct in case others read this. Obviously, since controls are automatically deleted when the owning window is deleted, the storage for controls is never "local" storage associated with a function.

I did solve my need for the dynamic allocation of arrays by using a simple list control. Even though I know it's not the "technically correct" solution, it works great. My function essentially dynamically allocates array storage by exploiting the fact that storage for a control is permanent storage associated with the window, not the function. I was concerned about speed, but even on my modest computer and a (uncommon) recursion depth of 15, it is lighting fast. That has been my experience with AutoIt in general -- lighting fast.

Merry Christmas to Everyone!

Sincerely,

Paul

Share this post


Link to post
Share on other sites

Thanks JPM! Is seems IsDeclared should also not return true as in the example script I posted. It sure would be nice is ASSIGN did work with arrays. And, (I'm certainly not arguing the point, but just pointing it out for the benefit of others), the documentation DOES NOT state that it doesn't work for arrays. The ASSIGN documentation only references the word VARIABLE. From the AutoIT Help file -- Language Reference - Variables, note that AutoIt (rightly I think) defines an array as variable. In fact, the IsArray function checks to see if a VARIABLE is an array TYPE. You can see, I think, how users like myself would expect ASSIGN to work with arrays. It may be helpful if under REMARKS for the ASSIGN function it was noted that ASSIGN does not work with variables of the array type.

I agree the difference with variable and an element of an array variable is not so clear.

You need to understand this part of the doc.

Before you can start using Arrays in your script, you must define their bounds using the 'Dim' keyword.

Merry Christmas :P

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0