Reply to topic  [ 6 posts ] 
Good coding style for defining an oxy class 
Author Message
Yorick Master

Joined: Tue Mar 07, 2006 10:31 pm
Posts: 125
Location: Meudon, France
Post Good coding style for defining an oxy class
Hi,

The oxy DOCUMENT comment tries to suggest a way to cleanly define "classes":
Quote:
This is slightly untidy, because you have to worry about never
colliding with the method names. So you could bundle it up neatly
by making myclass itself an object containing all its methods and
constructor(s):
myclass = save(new, method1, method2, ...); // save old values
func new(data1, data2, ...) {
// build and return the class, for example:
return save(method1, method2, ..., data1, data2, ...);
}
func method1(x) { return something; }
func method2(x,y) { return something; }
myclass = restore(myclass); // swap new values into myclass
(See help,save for examples of this trick.) Now the only variable
you have to worry about not clobbering is myclass, and you create
your object with:
mything = myclass(new, d1, d2);
and use it as before.


But this way doesn't work very well: if several classes have methods with the same name, the help function will get lost, as the debug messages upon errors. Typically, they will always issue information about the first (or last? didn't check) method defined by that name. If particular, if a runtime error occurs in your "new" method, yorick will often tell you the error is in another "new" method, in another file.

I therefore propose this scheme instead:

Code:
scratch = save(scratch, pkg_new, pkg_method1, pkg_method2);

extern pkg;
func pkg_new(void,data1=, data2=)
/* DOCUMENT      pkg class
        object = pkg(new, )
     or object = pkg(new, data1=data1, data2=data2)

    An OXY class to do stuff

    MEMBERS
      data1: ...
      data2: ....

    METHODS
      method1: ....
      method2: ....

    SEE ALSO: oxy, pkg.method1, pkg.method2
*/
{
  local method1, method2;
  restore, use, method1, method2;
  return save(data1, data2, method1, method2);
}

func pkg_method1 (...)
/* DOCUMENT obj, pkg_method, ....

    Where OBJ is an instance of the PKG class

    SEE ALSO: pkg
  */
{}

func pkg_method2 (...)
/* DOCUMENT value = obj(pkg_method2, .... )
  */
{}

pkg=save(new=pkg_new, method1=pkg_method1, method2=pkg_method2);
restore, scratch;


Help now works. In this example, the three calls below would display the relevant DOCUMENT comment:
Code:
help, pkg_new;
help, pkg.new;
help, pkg;


Also, if an error occurs in pkg.method, the error message will state that we are in pkg_method and the file/line information will be accurate.

So, stripping the document comments and pkg_new body:
Code:
scratch = save(scratch, pkg_new, pkg_method1, pkg_method2);
extern pkg;
func pkg_new(...) {}
func pkg_method1 (...) {}
func pkg_method2 (...) {}
pkg=save(new=pkg_new, method1=pkg_method1, method2=pkg_method2);
restore, scratch;


Last edited by thibaut on Thu Mar 15, 2012 12:30 pm, edited 1 time in total.



Thu Mar 15, 2012 4:36 am
Profile WWW
Yorick Guru

Joined: Thu May 10, 2007 12:07 pm
Posts: 62
Post Re: Good coding style for defining an oxy class
Hello,

The title of the post made me think, that it would be great to define "standard" methods for OXY object. Methods common to every OXY class-like objects that one creates, in order to help people to use them quickly.

In my mind I have these "standard" methods:

* help : Gives help on the object class or a specific method.
e.g. :
obj, help -> Will print help on what the object is for, and gives a list of method with a quick sentence about what they do.
obj, help, method -> Prints a help about the specified method (method can be string or yorick symbol, this is easy to implements thanks to wrap_args)

* info : As the info function in yorick, it will print (or return a string) about the basic object informations.
e.g. :
obj, info -> For instance will print something like: "Object of type MyType, with 34 keywords and float data of dim [2, 34, 56] red from file test.data" ... etc

* new : Create a new object of the same class

* is : Check if an input object is derived from the same class.
e.g.:
obj( is, obj2) : will return 1 if obj2 is from the same class than obj ; 0 otherwise.
A general "is" method can be defined easily by :
Code:
func is_myObj (obj2) {
   return is_obj(obj2,"new") && obj2(*,"new") && use(new)==obj2(new);
/*  Note that it can be broken if between obj and obj2 the file has been #include and the "new" function redefined */
}


Anything else am I missing ?
We can collect the idea here and after I can write a proper suggestion tutorial on how to create an OXY class-like object with standard methods.

Cheers,
Sylvain.


Thu Mar 15, 2012 10:24 am
Profile
Yorick Master

Joined: Tue Mar 07, 2006 10:31 pm
Posts: 125
Location: Meudon, France
Post Re: Good coding style for defining an oxy class
Hi,

Discussing "standard" methods is a good idea too.

I also often have an "eval" method if my object is sort of a functor. In this case, closure(obj, eval) makes alot of sense.

Another point is the doc comment: I often have the sections:

MEMBERS
(data)

METHODS
(obj, method...)

STATIC FUNCTIONS
(class.function())


Regards, Thibaut.


Thu Mar 15, 2012 12:15 pm
Profile WWW
Yorick Master

Joined: Mon Nov 22, 2004 9:43 am
Posts: 354
Location: Livermore, CA, USA
Post Re: Good coding style for defining an oxy class
We can certainly talk about these "standard" methods, but I want to make it clear that an arbitrary object is not going to respond to them. For one thing, the object interface is more general than just the group objects you are using. For another, any default "standard" method I might supply can equally well be implemented as an ordinary function which accepts the object as its argument. You can even easily write such a function so that it can be overridden by an object method if one happens to be defined, e.g.-

Code:
func info_o(obj) {
  if (is_obj(obj,info,1)==0 && is_func(obj,info)) obj, info;
  else info, obj;
}


In fact, since info is an interpreted function, I am willing to consider changing it to make it "overridable" in this way. Should I? How about "help" -- should that be overridable by objects like this?

Generic functions like this can easily be applied to any object, and give you the option of overriding the function in the same way you would override a method.

I want to emphasize that the problem with DOCUMENT comments and dbug file/line information is a completely different beast. I like Thibaut's workaround, which I think gets us started in a way that will continue to work into the future, but I am also pursuing a more general fix that doesn't confuse functions defined with the same name in the help or dbug processing. So let's restrict this discussion to "standard" query functions that do not involve the DOCUMENT comments.

Also, your "new" method doesn't make any sense in the yorick OXY context. I could imagine "copy", but your "new" is better served as a separate function new_thing for each kind of thing. There isn't really any analog in OXY to a C++ constructor, since there is never any definite block of memory that needs to be initialized. The current copy operation obj2=obj1 is a very shallow copy. A generic deeper copy function might be useful, which actually copied all the members.


Fri Mar 16, 2012 7:34 am
Profile
Yorick Master

Joined: Mon Nov 22, 2004 9:43 am
Posts: 354
Location: Livermore, CA, USA
Post Re: Good coding style for defining an oxy class
I just committed a partial fix for the DOCUMENT comment problem (commit 8bc3720 at github). This should work provided that the functions with the same name are defined in different files. It may also help with the related problem in dbug mode for such functions. I'm not sure how much help it will be in defining a "good style" for programming with oxy objects.


Sat Mar 17, 2012 10:36 am
Profile
Yorick Master

Joined: Tue Mar 07, 2006 10:31 pm
Posts: 125
Location: Meudon, France
Post Re: Good coding style for defining an oxy class
Hi, I confirm this fixes my concerns and obsoletes my initial post :-) (unless one wants to define several classes with homonymous methods in the same file).

Tried help and error with two files containing:
Code:
scratch = save(scratch, fcn);
obj1=save(fcn);
func fcn (void)
/* DOCUMENT fcn1
*/
{
  error("1");
}
obj1=restore(obj1);
restore, scratch;

and s/1/2/.


Sat Mar 17, 2012 2:52 pm
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 6 posts ] 

Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot 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:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by STSoftware for PTF.