AutoHotkey Community

It is currently May 27th, 2012, 12:28 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 259 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 18  Next
Author Message
 Post subject:
PostPosted: March 3rd, 2009, 8:54 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Yeah, the class is only a wrapper if you specify "Wrapper" as a class option. You can have a _GetValue function without it making it a wrapper. All the functions that unwrap first check that the object is a wrapper, then unwrap it. It will prevent that class from becoming a wrapper class though, unless your getValue IS the "unwrapped" value.


As for the search, does that sound too farfetched to make sense (specifing the negative of the object to use regex)? I can't think of any other way that makes any sense (not like this way does). However, this way is backward compatable. So, if there is no way that makes sense, why not use the one that's backward compatable, right?


For Cloneable, does the suggested method work? If not, I might be able to change the design, any feedback?

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 3rd, 2009, 9:04 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
For searching, I think a negative object value would be fine. Or if worse comes to worse, what about adding an additional search function with Regex on the end of its name, indicating that that's the one supporting Regex. I would be happy with either of those methods for now, as it will allow me to again remove the actual search functionality from my classes :)


I think the Cloneable method suggested will be work fine.

My cloneNode method in my DOMNode class is as follows, just for reference:

Code:
DOMNode_cloneNode(DOMNodeObject, deep) {
   Node := DOMNode_new()

   nodeType := DOMNode_getNodeType(DOMNodeObject)
   DOMNode_setNodeType(Node, nodeType)

   if (nodeType = 2)
      deep = true

   if (nodeType = 1) or (deep) {
      attributes := DOMNode_getAttributes(DOMNodeObject)
      newAttributes := DOMNamedNodeMap_clone(attributes, true)
   }

   baseURI := DOMNode_getBaseURI(DOMNodeObject)
   DOMNode_setBaseURI(Node, baseURI)

   if (deep) {
      childNodes := DOMNode_getChildNodes(DOMNodeObject)

      newChildNodes := DOMNodeList_clone(childNodes, true)
      newFirstChild := DOMNodeList_first(newChildNodes)
      newLastChild := DOMNodeList_last(newChildNodes)

      DOMNode_setChildNodes(Node, newChildNodes)
      DOMNode_setFirstChild(Node, newFirstChild)
      DOMNode_setLastChild(Node, newLastChild)
   }

   localName := DOMNode_getLocalName(DOMNodeObject)
   DOMNode_setLocalName(Node, localName)

   namespaceURI := DOMNode_getNamespaceUri(DOMNodeObject)
   DOMNode_setNamespaceURI(Node, namespaceURI)

   nodeName := DOMNode_getNodeName(DOMNodeObject)
   DOMNode_setNodeName(Node, nodeName)

   nodeValue := DOMNode_getNodeValue(DOMNodeObject)
   DOMNode_setNodeValue(Node, nodeValue)

   ownerDocument := DOMNode_getOwnerDocument(DOMNodeObject)
   DOMNode_setOwnerDocument(Node, ownerDocument)

   prefix := DOMNode_getPrefix(DOMNodeObject)
   DOMNode_setPrefix(Node, prefix)

   textContent := DOMNode_getTextContent(DOMNodeObject)
   DOMNode_setTextContent(Node, textContent)

   return Node
}

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 6:59 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
I need to clear up some functionality for the Clone method. Currently, I'm not sure how to handle user-defined values - since the code doesn't know their structure. I'm thinking a dynamic call to a _clone_private function. This can be dynamic, because if the function is not defined, then user-defined values aren't cloned. If the function is specified, then they will be cloned.

Some other questions:
1) Would a function in Class that has a format similar to the set method be useful?

I'm thinking:
Code:
Class_clone(TheClone, ClassObject, index, DeepCopy, Type = "uint")


You would call this function FOR EACH value in your Class.

<TheClone> is the address for the Clone object (created by a call to %ClassName%_new). <ClassObject> is the object you wish to clone. <Index> would be the index for the value to be cloned. <DeepCopy> would be a boolean - true to perform a deep copy (false to perform a shallow copy). <Type> would be the type used when SETTING the object (the get value doesn't matter). The function would automatically get the old value, clone it correctly (either deep or shallow), then set the value in the clone.

I think this will provide cleaner code than the "endless" getter and setter mess. Also, it allows the get type to be different than the set type. Ex. If you set a pointer to an object, but get the object as an "obj" to unwrap it, you CAN NOT use the getter function in the cloning process. Also, this way I can program the clone to be more efficient (low-level) because the user doesn't need to worry themself with it.


Rectangle will be cloneable and have an example. I'm also redoing Node to add a commented out setter, getter and their respective calls (in the new, destroy, clone, etc. functions). This is more so for my benefit and anyone like me who has problems remembering syntax. This way, you can copy and paste the getter and setter for each value and not have to type much at all to start your own Class.


2) For a shallow copy, can you clarify what it means.

I'm programming Array's clone, and not sure what a shallow copy means.

Does it mean:
1) Create a new Array object (of specified length)
2) Copy (not clone) the objects over - they will have the same address

Also, for String types, I presume a shallow copy would use the same address (not reallocate memory for the "clone"). If not, any help you can provide would be great.

Edit:
I just realized that a shallow copy would NOT "clone" the wrapper objects - it would only copy their address. Is that what a shallow copy is supposed to do? Sorry, for all the questions - I never use shallow copy.

Also, should deep or shallow copy be the default?

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 7:37 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
animeaime wrote:
I'm thinking a dynamic call to a _clone_private function. This can be dynamic, because if the function is not defined, then user-defined values aren't cloned. If the function is specified, then they will be cloned.

I like this idea.

animeaime wrote:
1) Would a function in Class that has a format similar to the set method be useful?
...
Code:
Class_clone(TheClone, ClassObject, index, DeepCopy, Type = "uint")

Yes, I think that would be useful. It would allow my wrapper clone() functions to be a lot simpler and more universal.

animeaime wrote:
2) For a shallow copy, can you clarify what it means.

I'm programming Array's clone, and not sure what a shallow copy means.

Does it mean:
1) Create a new Array object (of specified length)
2) Copy (not clone) the objects over - they will have the same address

It's hard to say in this case; the DOM doesn't deal with elements of a hard-coded length (aside from "read-only" elements) so my recent experience doesn't help here. I think creating a new array of specified length would be fine. The only other thing that would seem semi-intuitive to me would be to not clone the array at all, since it would normally be empty anyway, and it's likely if the user's not doing a deep clone the array may need to be a different size.

Kind of a head scratcher :)

animeaime wrote:
Also, for String types, I presume a shallow copy would use the same address (not reallocate memory for the "clone"). If not, any help you can provide would be great.

My original idea was to create a true copy of the string, so that it can be changed in the original object without it also being changed in the clone's reference. My idea was for shallow copies to only change whether or not object attributes (as opposed to string, uint, ushort, uchar, etc...) are cloned recursively.

I'm open to other concepts, though, too, if you think it would be more intuitive.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 7:42 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
animeaime wrote:
I just realized that a shallow copy would NOT "clone" the wrapper objects - it would only copy their address. Is that what a shallow copy is supposed to do? Sorry, for all the questions - I never use shallow copy.

Also, should deep or shallow copy be the default?


I think a shallow copy should clone the wrapper object, if possible. Could you have a check in the Class library of the object being cloned is a wrapper, and if so, override the unwrapping functionality for the clone process? Not sure what this would actually require, or if there's a better way.

I usually don't think of the standard wrappers (string, uint, etc) as objects, since I use them with the class getter/setter. I would expect those types to be cloned no matter what, but maybe that's not very intuitive.

I think a deep copy should be the default.

A shallow copy would be useful for creating a clone of a custom "container" class (like a document) with all settings and direct parameters in-tact but with no sub-objects (the document content, for instance)

So for IniFile, a shallow clone would copy the IniFile object and its settings, but none of the sections or fields would be cloned (or even included in the cloned object). In that case, I think it should end up with either an empty sections Vector, or an empty sections parameter with no Vector at all.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 8:19 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Ok. Now, I'm officially confused.

bmcclure wrote:
So for IniFile, a shallow clone would copy the IniFile object and its settings, but none of the sections or fields would be cloned (or even included in the cloned object). In that case, I think it should end up with either an empty sections Vector, or an empty sections parameter with no Vector at all.

In my mind a deep copy means each object is created a new - a recursive copy. A shallow copy means the "shell" (the object) is a copy, but its contents are the same (i.e. same addresses, not cloned).

This is what the clone function will do. If you want a function that will clone the outside (with settings), but no insides (contents), I'm not sure what I can do... Maybe a three way toggle. Deep, shallow, "settings only". Since the clone will be done by the class, it can decide what "settings only" means and what behavior is done. After I get feedback (and sort this out in my head), Ill be sure to give a breakdown that explains the setup and how to use the Class_clone function to easily setup the clone method for Deep, Shallow, and "Settings only".

Deep would be the default - pass true (1) to use deep, pass false (0) to do a shallow copy, and pass -1 to do a "settings only" copy.

For shallow copy, based on what I read in the Shallow copy wiki article, it looks like a shallow copy only copies the address. Now, whether this should apply to string values or the wrappers is up to debate.

For string values, I agree, they should be cloned - allocated in another spot. Since I think the shallow copy should mimic loosely the "settings only" copy, string settings (like FilePath in IniFile) should be cloned (not copied). This allows changing settings on the original without changing the clone. This would allow making a copy that had the same contents, but different settings.

For the wrappers, I think they should be only copied (not cloned) in a shallow copy. Because the wrappers are meant to be used only in a Vector or Array - in all other places, you can use the basic types (i.e. no need to wrap them). A shallow copy should only copy, not clone the data - this is my understanding of the wiki. However, this may not be desired. I can say that by using this form of shallow copy, the shallow copy for Vector and Array will be really fast as it only needs to allocate memory, then do a DllCall to copy the memory. Also, a note, Vector and Array would not have a "settings only" copy - no settings.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 8:26 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
This is a separate post, because it's a separate topic - this is to clear up some confusion.

If I misread this, ignore this post.

bmcclure wrote:
I usually don't think of the standard wrappers (string, uint, etc) as objects, since I use them with the class getter/setter

When you specify "string", "uint", etc, as the type for a getter or setter this IS NOT using a wrapper object. A wrapper object is used to store a "string", "uint", etc. in an "obj" field (e.g. in a Vector or Array). In a getter/setter you are using built-in values (via NumGet/Put). String is an added type which allocates memory and sticks the string in it - but it is still not a wrapper object (it's not a Class object at all - just an address to a null-terminated string).

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 4th, 2009, 4:31 pm 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Hmm, I do get what you're saying--althought now I don't understand what a shallow clone would be good for if it clones the object but keeps references to its old content.

However I'm fine with you implementing it that way--I just won't have a use for it that I can think of.

As long as deep copy will be the default, that's cool--I'll create my own functionality for the cloning I need in the DOM.

Thanks for your work on this.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 12:51 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Well, what difference would your idea be from the shallow copy? Like I said, I can have a three way clone - deep, shallow, and "settings only" (which sounds like what you want).

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 1:18 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Really the only difference would be that instead of shallow-cloning objects, objects wouldn't be cloned at all (unless specific ones are selected maybe?). I'm thinking this could be done with the current method you're implementing, simply by not calling the clone method for those objects?

The goal of my shallow copy would be to copy the "shell" of the object, useful for copying object properties (attributes) without copying its content (child objects).

But really, I think the only way I'm going to get the cloning I need in my DOM library will be to create a custom clone method that specifically clones the attributes and objects it needs depending on the deep parameter--since it's so specific to the DOM structure, and some objects need to be cloned in that case even for shallow copies.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 2:44 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Well, the method is that you would need to call the clone function for each value. This allows you to shallow copy some and deep copy others. A "settings only" copy is done by the function, by not calling the clone for a specific value, or by doing something specific.

Here is the current idea for the Class_clone function:

1) Basic types and strings are copied for both shallow and deep copy.
2) For objects (wrapper objects included)
a) Shallow copy only copies the address
b) Deep copy creates a recursive clone of the object
c) A "Settings only" copy doesn't copy (leaves as 0 - "unset"). It leaves it up to the Class' clone function to decide how to handle objects. Of course, because a zero is set automatically (when the memory is allocated), you don't need to call Class_clone for objects). This behavior is to allow calling the function for each value (even "obj" types), passing the value for <DeepCopy> and then for a "settings only" copy, it leaves it up to the class' clone function to decide how to handle a "settings only" copy.

Also, you don't call the %ClassName%_New function to create an object in the clone function. Instead, you call Class_createClone(ClassObject) which returns a Class object allocated with enough memory to hold the class object (including user-defined values). Also, it copies the "class values" to the clone. This function will also be overloaded to allow passing the objects structure (in order) to provide an easy way to copy all the built-in values. You then only need to call %ClassName%_clone_private, dynamically, to allow the user-values to be copied. There will be a function to allow copying the user-defined values in one passing the types for the user-defined values (in order).

I'm finishing up the functionality, and will post the update shortly. At that time, this should make more sense, and I can make adjustments at that time if the solution doesn't fit your needs.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 5:35 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Not sure how much sense this will make, as usual :)

Is there any way to implement class constants? I don't necessarily want to get/set values for some things, like mapping an error name to an error number, or a nodetype in the DOM to a nodeType value.

What I'm really looking for is some "standard" method that the Class library could use (or at least specify) for allowing "global" variables in the scope of the class?

Obviously the variables wouldn't be available within the functions without pulling them in, but perhaps it could be something like %ClassName%_constant(ClassObject, "value")

This could of course be implemented manually in every class without too much hassle, but I think it would be ideal if it were a defined method that all classes should use, for consistency, and which could then be included in the Node class as a template.

Within most OO languages, classes allow constants, somewhat like functions do with static in AHK, only they are available in all methods of the class, and externally by a call to the class. In Java, they can be retrieved by a call to ClassName.CONSTANT_NAME externally, or internally just by CONSTANT_NAME I believe. And there is also an ifDefined check on a constant to see if the class has defined it.

Did that make any sense? Can you see any way to accomplish anything remotely similar?

update
I suppose one way for a class to implement a constant would be to define a function like:
Code:
ClassName_CONSTANT_NAME() {
 return "Value"
}

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 6:24 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
Ok, for clarification.

1) You call them constants, so I presume you want a single value to be accessable by the entire class - instead of a variable like Rectangle's height and width which is stored with the class object.

2) Do the values need to be accessible without calling %ClassName%_constant(ClassObject, "value")? - hopefully not (because I have an idea)


Here is my thought.

1) static variables would be best. They don't interfer with the global "namespace", and they are retained between calls. Plus, it will be VERY easy using this approach.

2) The static variables would be defined (and preinitialized) in %ClassName%_constant.

3) This setup allows the ability to change the values.

4) There would be a function, Class_constant(ClassObject, variable, setValue = "") which would call the respective Class' function dynamically. Of course, you can call it from the Class directly too.

This method is a little "messy" maybe, but its the only way I could think to allow this without interfering with the global namespace. Note: It is not possible to set the constants to the empty string (nor can it ever be). The empty string functions both in the optional parameter (to allow storing a new value) and as the return to indicate that the specified value doesn't exist.

The parts in red are the only parts that would be modified - based on the variables/values used.

The template version:
Code:
;returns the value associated with the specified variable
;returns the empty string if the specified variable doesn't exist

;specify a setValue to modify the specified variable
;(the return will be the previous value)
Node_constant(variable, setValue = "")
{
    if (variable = "")
        return
           
    ;comma-delimited list of used variables
    static variables
   
    if (variables = "")
    {
        ;only done once
       
        variables =
        (LTrim Comments Join,
            value1              ;description of value1
            value2              ;description of value2

        )
    }

    ;static values - shared between all instances
    static value1 = 5
    static value2 = 6



    ;variable name is not case-sensitive
    scs := A_StringCaseSense
    StringCaseSense, off
   
    if variable in %variables%
    {
        ;return previous value
        returnValue := %variable%
       
        if (setValue != "")
        {
            ;set the value to the new value
            %variable% := setValue
        }
    }

    ;restore previous setting
    StringCaseSense, %scs%
   
    return returnValue
}


Edit:
Saw your update, that could be used too. I could see how that could get messy with many values, but I never thought of it, thanks for the idea.

Edit2:
Forgot to say how to get the constant

Code:
MsgBox, % Node_constant("value1")


This also allows a "dymamic" retrieval and/or set
Code:
Variable := "value1"
MsgBox, % Node_constant(variable)


Edit3:
Just realized that you could use a similar structure that <variables> uses to initialize the static variable to something other than a string, number, etc. For example, you could use that method to call a function and initialize the value to it's return. Just make sure the value ends up with a value in it (non-empty).


On a side note, the clone method is almost done. I implemented it in a way to now allow automatic deletion of values - built-in and user-defined. You will have to specify the types, but that should be simple.

This design allows the previous method to be used - backward compatable. Also, I think this way will be much easier, and adds to the library's potential to grow.

I'm checking that everything works, and cleaning it up, so I should have the latest version shortly. I'm goning to call it a night soon. I'll double check it tomorrow (when I'm more awake), to verify I didn't miss anything.

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 7:39 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Cool, thanks a lot for implementing clones and constants; I can hardly wait to utilize the new functionality :)

The methods you've suggested for both seem excellent to me.

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 5th, 2009, 9:30 am 
Offline

Joined: November 24th, 2007, 9:07 pm
Posts: 774
Note: My next post expands on this one, providing some better ideas I think. Make sure to read that one too :)

Trying to figure out how exceptions could be built into the class library, and I got an idea, though it's only part of the puzzle:

A new class option: Throwable

a throwable class represents an exception.

the Class library is extended with a Class_throw() method, or Class_throwException(), which is global, and can be used anywhere, and requires a single parameter, which is a Throwable object. A second parameter might also be useful, "callingFunction" or something, which specifies the function that was run when the exception occurred (as a string)

Since there is no way for Class to access the call stack (reverse list of methods which were called when the exception occurred), I'm thinking when Class_throw() is called, Class determines the ClassName of the object, makes sure it's throwable, and then determines the Exception Handler to use by:
1. trying to call %ExceptionClass%_getHandler, which may contain the function name of a registered handler, or
2. trying to check for a Constant "handler" defined for the Exception class (that can be used to set a handler for all exceptions of that type)

Then Class calls the function it retrieved as the Handler, if one was registered, providing the exception as the parameter (and the "callingFunction" as the second parameter, if it was defined).



I haven't fully thought this through yet, but it seems that would allow exceptions to be thrown from anywhere, and have Class do the dirty work of deciding where to send it, so that you can separate the error processing from the code.

Exceptions could be totally ignored (no handler defined), or caught (handler found).

And that means I found a use for your new ability to set Constants dynamically :)

What do you think? Would something similar be possible?

_________________
Ben

My Trac projects
My Wiki
[Broken] - My music


Last edited by bmcclure on March 5th, 2009, 10:04 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 259 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11, 12 ... 18  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: rrhuffy and 1 guest


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group