Jump to content


Photo

static arrays


  • Please log in to reply
34 replies to this topic

#1 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 12 October 2006 - 12:34 PM

Can we somehow have those one day ?

I find this to be a problem when creating black box functions that are totaly isolated from the rest of the script, so people can not see or change internal data by accident.

Example:
#SingleInstance, force

!p::
	ToggleMenu( WinExist("A") )
return

ToggleMenu( hWin )
{
	static hMenu, visible
	if hMenu =
		hMenu := DllCall("GetMenu", "uint", hWin)
	
	if !visible
			DllCall("SetMenu", "uint", hWin, "uint", hMenu)
	else	DllCall("SetMenu", "uint", hWin, "uint", 0)

	visible := !visible
}

This function will toggle menu of window on/off.
It works for one window only since window's menu is stored in static variable hMenu on first function usage.

If I want to change this so it works for all windows, it must remember handles of eatch window menu in array. Using global arrays is not good idea since those can be accessed and changed by accident.

Local static array would be much more convenient here - it will allow totaly function isolation no matter what is its environment.

LIke I once mentioned, it can be achieved with some metachar, like

static array*

Some meta like this one will also allow for local and global and static arrays at the same time:
global
static sArray*
local localArray*

The meaning of metachar * is that all variables starting with given prefix are to be considered static/local.

#2 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 12 October 2006 - 12:43 PM

Well, as you know, it is already in the TODO list, probably with some medium priority, unless it is part of the v2 features which seem high.

A convoluted way of doing what you want might be to set a large static variable with VarSetCapacity, then write the handles inside with SetInteger...
Note that it is isolated here because you have a unique function to do both operations, should you have two functions, you would need to share the variable between both, so it would go to some more or less global variable anyway.
The next wish would be to have some kind of object system... ;-)

I started a proposal on how I would like to see true arrays implemented (allowing associative arrays). If you don't mind, I could post it here, to avoid multiplication of similar wishes.

#3 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 12 October 2006 - 12:52 PM

I serached the TO DO list before I posted here for words array, local and static and I found nothing.

If you don't mind, I could post it here, to avoid multiplication of similar wishes.

Please do. Arrays are absolutely needed in AHK. I will add summary of your wish to the first post.


EDIT
Thalon just told me that if I place static alone, all variables will be static. This will help in this example. However problem is still present as you can't have local array then...


EDIT2
It appears that Thalon was only in a good mood for joking...
Static acctually don't work alone :)

#4 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 12 October 2006 - 01:51 PM

Ah, I misunderstood your problem, the initial subject was just "arrays", and I thought you wrote about true array support...

Arrays can be local, but it is convoluted, I always have to check the doc. to see how to do this. Let see...

Thalon just told me that if I place static alone, all variables will be static.

If I do that, I get a syntax error:
Line Text: static
Error: This line does not contain a recognized action.


Got it, here is the relevant quote:

For commands that create arrays (such as StringSplit), the resulting array will be local if the assume-global mode is not in effect or if the array's first element has been declared as a local variable (this is also true if one of the function's parameters is passed, even if that parameter is ByRef).

I don't understand the function's parameter part.

It doesn't mention static, and it doesn't work, alas:
F(_i, _x, _op)
{
	static a1	; The first element of the array
;	static a	; The prefix of the array, doesn't work either

	If _op = Add
	{
		a%_i% := _x
	}
	Else If _op = Get
	{
		Return a%_i%
	}
	ListVars
	Pause
}

F(1, 155, "Add")
F(3, 55, "Add")
F(7, 99, "Add")
MsgBox % F(1, 0, "Get") . F(3, 0, "Get") . F(7, 0, "Get")
ListVars
Pause

Space::Pause Toggle
Esc::ExitApp
Curiously, the local variables are still here from call to call, but empty...

The subjec to static arrays is tricky, because arrays are not actually one variable but a bunch of variables. A workaround would be to write: static a1, a2, a3... or some keyword/notation to mark a newly created variable as static (persistent). It seems they are more or less, already, but they are reset on each call.
But well, it is much simpler (?) and consistent to have true arrays, then declare the array as static.

#5 majkinetor

majkinetor
  • Fellows
  • 4511 posts

Posted 12 October 2006 - 02:36 PM

Hej this is good news, it means that we can have both local and global arrays in AHK, I didn't know that. So my proposed * metachar is acctually present for local arrays.


For static arrays not.
I agree that true array support is the best. Acctually I can not imagine even trivial programming language without arrays. I hope that Chris will rise priority for this.

PhiLho, can you point to the thread with your proposition ?

Thank you


BTW, How would you make local arrays with "associative arrays", like the one I created in ToggleMenu witch has window handle as an index. I don't know first element since it is dynamic :)... so I can create only "simple" numeric arrays this way :)

#6 JSLover

JSLover
  • Members
  • 920 posts

Posted 14 October 2006 - 12:19 PM

I serached the TO DO list before I posted here for words array, local and static and I found nothing.

...I called it...
Assume Static...or dynamic static variables.

#7 majkinetor !

majkinetor !
  • Guests

Posted 14 October 2006 - 07:02 PM

Chris, what do you say ?
Do we heave a deal ? :D

#8 Chris

Chris
  • Administrators
  • 10727 posts

Posted 14 October 2006 - 11:03 PM

Thanks for the suggestions. One of these days, I should just sit down and look at the source code to some language like PHP to see how they do associative arrays (the kind most people would propably prefer). I'm sure it involves hashing to improve performance.

I don't understand the function's parameter part.

I've changed it to read: "For commands that create arrays (such as StringSplit), the resulting array will be local if the assume-global mode is not in effect or if the array's first element has been declared as a local variable (this is also true if one of the function's parameters is passed, even if that parameter is ByRef, because parameters are similar to local variables)."

It doesn't mention static, and it doesn't work, alas:
static a1 ; The first element of the array
...
a%_i% := _x

Examples like the above would never work because only array-creating commands can use a mode other than the function's assume-mode when creating an array. However, I'll look into changing array-creating commands to create a static array if their base variable is static. Thanks for the idea.

Curiously, the local variables are still here from call to call, but empty...

That's because variables in AutoHotkey are currently never truly destroyed, just made empty to free their memory. This is done for performance reasons because it allows the lines inside a function to be optimized before the script begins running. For example, since the address of a local variable never changes, the program can exploit this and hard-code the address into the line so that it doesn't to be looked up every time the line is executed.

#9 majkinetor !

majkinetor !
  • Guests

Posted 15 October 2006 - 09:16 AM

One of these days, I should just sit down and look at the source code to some language like PHP to see how they do associative arrays

This is great. I can't wait.


However, I'll look into changing array-creating commands to create a static array if their base variable is static

Thank you.
We will be able to create from that moment function environment, that is, static variables can replace globals, thus function may never interfer with variable space of its caller.

For example, since the address of a local variable never changes, the program can exploit this and hard-code the address into the line so that it doesn't to be looked up every time the line is executed.

Interesting.


Thx.

#10 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 15 October 2006 - 09:38 AM

One of these days, I should just sit down and look at the source code to some language like PHP to see how they do associative arrays (the kind most people would propably prefer). I'm sure it involves hashing to improve performance.

I started to do this for you, but looking at Lua implementation, as it is small, fast, and flexible: if you put increasing numbers as keys, it automatically put them in an array part, allowing direct access as array, much faster than hashing the number and looking for the value in the hash table. There are some details in a paper giving some hints on the Lua 5.0 implementation and I found back the paper they refer too for hash table implementation. I have also the source, but it is harder to read...

I started to write a paper on true array implementation wish, more soon, I hope. Do you have precise ideas on syntax (I see issues here) or are you still open on suggestions?

#11 Chris

Chris
  • Administrators
  • 10727 posts

Posted 15 October 2006 - 10:04 AM

looking at Lua implementation, as it is small, fast, and flexible: if you put increasing numbers as keys, it automatically put them in an array part, allowing direct access as array, much faster than hashing the number and looking for the value in the hash table.

Nice.

I started to write a paper on true array implementation wish, more soon, I hope. Do you have precise ideas on syntax (I see issues here) or are you still open on suggestions?

I'm vaguely leaning toward PHP style arrays where everything is sort of dynamic and informal. For example:
Var := xyz  ; A normal variable.
Var := array()  ; But now "Var" is an array (empty in this case).
I'd like to avoid dimensioning and declaration if possible. However, I realize those things might allow performance and memory utilization to be improved.

Thanks.

#12 JSLover

JSLover
  • Members
  • 920 posts

Posted 15 October 2006 - 10:19 AM

I'd like to avoid dimensioning and declaration if possible.

...yes, do avoid that, but you could support some way to do it, just not require it...are you using array[] syntax to access elements?...numbered elements or strings too?

test:=myarray[0]
test:=myarray['myval']
test:=myarray["myval"]
...how about php array creating?...

myarray:=array('value')
myarray:=array(5 -> 'value')
myarray:=array('name' -> 'value')


#13 Chris

Chris
  • Administrators
  • 10727 posts

Posted 15 October 2006 - 12:00 PM

Hopefully all of the above.

#14 PhiLho

PhiLho
  • Fellows
  • 6850 posts

Posted 15 October 2006 - 12:19 PM

The question was on array access, mostly, as it is difficult, syntaxically wise.
Do you plan to put that in v2, and put [ and ] out of the list of characters allowed in variable names, breaking some scripts?
If so, OK, so more problem, and syntax is familiar.
Otherwise, some clever syntax must be thought, I have some ideas, but not need to work on them if you plan the above.

#15 Chris

Chris
  • Administrators
  • 10727 posts

Posted 15 October 2006 - 02:07 PM

...it is difficult, syntaxically wise. Do you plan to put that in v2, and put [ and ] out of the list of characters allowed in variable names, breaking some scripts?

Yes I think so. However, this does not mean that true arrays will be implemented in conjunction with the #v2 directive. Instead, that will probably have to wait until sometime later, perhaps even as late as v2 itself.

In other words, #v2 will probably outlaw [] characters in variable names to pave the way for having true arrays. For existing scripts that use those characters, there will be a conversion routine that transforms them (and many other things) into something acceptable by v2.