 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Sun Jan 27, 2008 10:34 am Post subject: OOP or how to create the equivalent |
|
|
Hi all!
I am trying to convert the following program in Java into AHK, but get stuck in finding more or less acceptable equivalent Here is java code:
| Code: |
///
public class MyCollection
{
public static final int MAXL = 20;
public static final int MAXS = 10;
Loc[] locs = new Loc[MAXL];
int size = 0;
public void add(int x, int y, int n)
{
size = Math.min(size + 1, MAXL);
for (int i = size - 1; --i > 0; )
locs[i] = locs[i - 1];
locs[0] = new Loc(x, y);
locs[0].set(n);
}
// more methods go here but it doesn't matter now
}
///
class Loc
{
// set
boolean [] groups = new boolean[MyCollection.MAXS];
int x, y;
public Loc(int x, int y) { this.x = x; this.y = y; }
public void set(int n) { groups[n] = true; }
public void unset(int n) { groups[n] = false; }
public boolean get(int n) { return groups[n]; }
public Pair getXY() { return new Pair(x, y); }
}
///
class Pair
{
public int a, b;
Pair(int a, int b) { this.a = a; this.b = b; }
}
|
To simulate an object, I can use ByRef parameter. And in simple cases it is direct equivalent.
To simulate a method for, say, Loc class, I can create functions like these:
| Code: |
Loc__new_(x, y) { ... return ... } ;; constructor
Loc_set(ByRef this, n) { ... }
Loc_unset(ByRef this, n) { ... }
Loc_get(ByRef this, n) { ... return ... }
Loc_getXY(ByRef this) { ... return ... }
|
But! What to do with the functions' bodies?
The stumbling block is java "dot notation", i.e. if we have an object (=reference) x, then we can use things like x.method or x.field. What I need in AHK is get access to variable or function from a reference:
| Code: |
Loc_getXY(ByRef this)
{
x = this.x
y = this.y
return Pair__new_(x, y)
}
|
How to achieve this?
Thanks in advance. |
|
| Back to top |
|
 |
Guest
|
Posted: Sun Jan 27, 2008 12:01 pm Post subject: |
|
|
| I would forget the java code style and write it in AHK syntax style. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Mon Jan 28, 2008 5:04 am Post subject: |
|
|
http://www.autohotkey.com/forum/viewtopic.php?p=172832#172832
| I wrote: | There are a number of ways to "emulate" object-oriented programming.
... |
| RaptoR wrote: | | What I need in AHK is get access to variable or function from a reference: | The answer depends on how the data is stored. If the objects have a static number of numeric fields, VarSetCapacity and NumPut/NumGet would probably be most efficient. If the objects have arrays or string fields, Scripting.Dictionary would be easier. Have a look at the above link, then decide whether you need wrapper functions.
| Quote: | | I would forget the java code style and write it in AHK syntax style. | If feasible, I'd also lean towards abandoning OOP concepts. |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Mon Jan 28, 2008 11:36 am Post subject: |
|
|
| lexikos wrote: | The answer depends on how the data is stored. If the objects have a static number of numeric fields, VarSetCapacity and NumPut/NumGet would probably be most efficient. If the objects have arrays or string fields, Scripting.Dictionary would be easier. Have a look at the above link, then decide whether you need wrapper functions.  |
Thank you for the answer!
I rethought the question and realized, that I need some sort of "packing" and "unpacking". "Packing" is gathering things together and assigning a name. "Unpacking" is taking the name and get access to the things.
According to your suggestion the first implementation of this concept is record type, in AHK it needs NumPut/NumGet, hardcoding offsets and wrapper functions to ease the usage.
Second implementation is hash map, but it needs special attention to the keys to avoid name clash. Or use several hash maps - one map per namespace.
Third implementation come into my head is combine names like arrays in AHK.
| Code: |
size := "_size"
value1 := "my_value_goes_here"
value1_size := 123444
value2 := "your_value_goes_here"
value2_size := 666342
function("value1")
function("value2")
function(var)
{
global size
Log("var = " %var%)
Log("var_size = " %var%%size%)
}
|
Obvious disadvantage is only one namespace - global.
Fourth implementation could be encode everything in the long string and parse it when one needs to use it. I doubt it could be made efficiently
Probably there are more ways to implement packing and unpacking. But for the problem at hand the most preferrable way is the first one. You rule!
| Quote: | | If feasible, I'd also lean towards abandoning OOP concepts. |
You mean there is something more powerful? (lets take no Haskell, Lisp etc, something for human programmers ) |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Mon Jan 28, 2008 11:38 am Post subject: |
|
|
| Anonymous wrote: | | I would forget the java code style and write it in AHK syntax style. |
Could you please show me, what AHK syntax style is? IMHO, concepts are independent of the language. |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Mon Jan 28, 2008 10:33 pm Post subject: |
|
|
| Perhaps Guest meant procedural code vs. objects in general, or maybe using AutoHotkey pseudo-arrays. |
|
| Back to top |
|
 |
Tuncay
Joined: 07 Nov 2006 Posts: 384 Location: Berlin
|
Posted: Mon Jan 28, 2008 11:02 pm Post subject: |
|
|
RaptoR
Sometimes on big scripts, I would have a way to program in AutoHotkey using OOP. In real programming languages, this is a real advantage. But in an simple scripting language, OOP is overkilling most non programmers.
The AHK language does not support explicitly OOP or any feature of. So we have to emulate it somehow. But this would never be save. But emulating some aspects would impact the performance much and make things complicated. |
|
| Back to top |
|
 |
Guest
|
Posted: Tue Jan 29, 2008 12:58 am Post subject: |
|
|
| Tuncay wrote: |
Sometimes on big scripts, I would have a way to program in AutoHotkey using OOP. In real programming languages, this is a real advantage. But in an simple scripting language, OOP is overkilling most non programmers.
The AHK language does not support explicitly OOP or any feature of. So we have to emulate it somehow. But this would never be save. But emulating some aspects would impact the performance much and make things complicated. |
omg that really changed my perspective.
Danke  |
|
| Back to top |
|
 |
Tuncay
Joined: 07 Nov 2006 Posts: 384 Location: Berlin
|
Posted: Wed Jan 30, 2008 7:17 pm Post subject: |
|
|
| Guest wrote: | | omg that really changed my perspective. |
Are you RaptoR?? If you mean this in an ironical way ... so I donīt know why. |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Thu Jan 31, 2008 11:01 am Post subject: |
|
|
| Tuncay wrote: |
Are you RaptoR?? If you mean this in an ironical way ... so I donīt know why. |
Noooo! Guest is not me, dont be confused so easy!  |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Thu Jan 31, 2008 12:07 pm Post subject: |
|
|
| lexikos wrote: | | Perhaps Guest meant procedural code vs. objects in general, or maybe using AutoHotkey pseudo-arrays. |
I did a little step towards emulating OOP, although met with several obstacles.
First, it is not possible to use ByRef parameters because we sometimes have to return an object, like in the java code below:
| Code: |
public Pair getXY() { return new Pair(x, y); }
|
I don't know how to write it using Byrefs, so I had to use integer numbers as object references.
Second. Lets consider the "constructor":
| Code: |
Bug_new(x) ; constructor
{
global MAXS
VarSetCapacity(this, (MAXS + 1) * 4, 0)
NumPut(x, this)
return &this
}
|
Here returned this is just number numerically equal to pointer to the buffer. But for some reason the buffer is shared among different calls!:
| Code: |
bug1 := Bug_new(666)
bug2 := Bug_new(777)
Log(bug1 ", " bug2) ; ouptuts "4160032, 4160032" :-(
|
That's why I use now inner static object counter:
| Code: |
Bug_new(x) ; constructor
{
global MAXS
static obj := 0
obj++
VarSetCapacity(this%obj%, (MAXS + 1) * 4, 0)
NumPut(x, this%obj%)
return &this%obj%
}
|
And I find it sort of cumbersome. But it is not the main thing.
The main thing is the third one: somehow objecs get corrupted between calls. I better put the all the code here:
| Code: |
Log("the script is loaded")
MAXS := 5
MAXL := 10
bug1 := Bug_new(666)
bug2 := Bug_new(777)
Log(bug1 ", " bug2)
;; here the objects get corrupted !!
Log(Bug_to_string(bug1))
Log(Bug_to_string(bug2))
Bug_new(x) ; constructor
{
global MAXS
static obj := 0
obj ++
VarSetCapacity(this%obj%, (MAXS + 1) * 4, 0)
this := &this%obj%
NumPut(x, this+0)
;; debug output in constructor
Log(Bug_to_string(this))
return this
}
Bug_to_string(this)
{
global MAXS
str := "{"
loop % MAXS + 1
{
if (a_index == 1)
str .= NumGet(this+0, (a_index-1) * 4)
else
str .= "," . NumGet(this+0, (a_index-1) * 4)
}
str .= "}"
return str
}
|
it outputs this:
| Code: |
[04:44:55] the script is loaded
[04:44:55] {666,0,0,0,0,0}
[04:44:55] {777,0,0,0,0,0}
[04:44:55] 4161676, 4161832
[04:44:55] {512,0,0,0,0,0}
[04:44:55] {768,0,0,0,0,0}
|
I tend to the conclusion, that the corresponding local objects this1 and this2 are disposed after leaving constructor body. If I am right, then these objects should be made global, and the fact is very confusing - encapsulation and "packing-unpacking" concept is gone
Could you clarify when and where objects are allocated and disposed (or garbagecollected) in AHK and where can I read about that? |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 2558 Location: Australia, Qld
|
Posted: Thu Jan 31, 2008 1:00 pm Post subject: |
|
|
| RaptoR wrote: | | First, it is not possible to use ByRef parameters because we sometimes have to return an object, | Simple useinstead ofThis also solves the constructor issue:
| Code: | Bug_new(ByRef this, x)
{
global MAXS
VarSetCapacity(this, (MAXS + 1) * 4, 0)
NumPut(x, this)
} |
| Quote: | Here returned this is just number numerically equal to pointer to the buffer. But for some reason the buffer is shared among different calls!
...
somehow objecs get corrupted between calls.
| Local variables are never deleted. If beyond a certain size threshold, the contents of a local variable are freed when the function returns. If below the threshold, the variable is made blank and its memory is reused by the next call. Generally "made blank" means the first byte and the variable's internal length are both set to 0.
This isn't documented, so the only safe assumption is that the memory of a local variable is only "valid" for the duration of the function call. Once the function returns, it is not safe to access.
| Quote: | That's why I use now inner static object counter:
...
And I find it sort of cumbersome.
| Take a look at the second example in the post I linked to earlier (also below). GlobalAlloc returns a pointer to allocated memory. Pointers can be passed to and from functions, since they are simply numbers. The (second) example demonstrates allocating a structure, setting fields, getting fields, and deallocating/freeing the structure.
http://www.autohotkey.com/forum/viewtopic.php?p=172832#172832
| Quote: | | Could you clarify when and where objects are allocated and disposed (or garbagecollected) in AHK and where can I read about that? | You can read about it in posts like this one, or AutoHotkey's C++ source code.  |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Thu Jan 31, 2008 2:45 pm Post subject: |
|
|
[quote="lexikos"] | RaptoR wrote: | | First, it is not possible to use ByRef parameters because we sometimes have to return an object, | Simple useinstead ofThis also solves the constructor issue:
| Code: | Bug_new(ByRef this, x)
{
global MAXS
VarSetCapacity(this, (MAXS + 1) * 4, 0)
NumPut(x, this)
} |
Mmm, no I took this approach but get stuck with converting the following code:
| Code: |
public void add(int x, int y)
{
size = Math.min(size + 1, MAXL);
shiftr(size - 1);
locs[0] = new Loc(x, y);
}
|
Analog is
| Code: |
Set_add2(this, x, y)
{
size := Set_get_size(this)
Set_set_size(this, (MAXS < size + 1 ? MAXS : size + 1))
Set_shiftr(this, size - 1)
Loc_new(loc, x, y) ;; !!!!!!! loc is local!
Set_set_locs(this, 0, loc)
}
|
and I get the same "corrupting problem" again (loc disappears after exiting from the function). |
|
| Back to top |
|
 |
RaptoR
Joined: 27 Jun 2007 Posts: 22 Location: Earth, Cambrian period
|
Posted: Thu Jan 31, 2008 2:47 pm Post subject: |
|
|
| lexikos wrote: |
Take a look at the second example in the post I linked to earlier (also below). GlobalAlloc returns a pointer to allocated memory. Pointers can be passed to and from functions, since they are simply numbers... |
I consider GlobalAlloc as the last way to try, because it has obvious disadvantage - need to free memory manually. |
|
| Back to top |
|
 |
grupo Guest
|
Posted: Thu Jan 31, 2008 10:41 pm Post subject: |
|
|
Sorry,it is off topic...
I am the Guest from the first reply.
I must confess that I did not read your post carefully because
most(all??) threads I have seem here asking "how to convert this autoit|c++|c#|vb|js...etc code to ahk"
were posted by newbies with zero knowledge, then I adviced to try a basic ahk code. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|