I committed the first yorick 2.2 code to CVS this morning. The version number is 2.2.00x. There is no 2.2.00; the first stable release of 2.2 will be 2.2.01. The final 2.1 version is 2.1.99, tagged y_2_1_99 in CVS.

The version number increments in honor of the first significant new feature in yorick in a long time: an object oriented extension, "oxy". When you build 2.2.00x, do help,oxy; help,save; help,is_obj to get a fairly comprehensive explanation of the new features. What I implemented was quite similar to the description in the forum post http://yorick.sourceforge.net/phpBB2/viewtopic.php?t=273.

The new "group" object makes _lst, struct, and pointer obsolete in interpreted code. The group object integrates much better into yorick's declarative-free, informal language than these now-obsolete borrowings from Lisp and C. Soon, groups will be able to be written directly to binary files using save and restore, at which point there will be scant excuse for not using them.

The 2.2 version also includes Eric Thiebaut's closure objects, which provide a clean alternative to using external variables to pass hidden arguments to callback functions.

You can look in i/testoxy.i for usage examples. Discussion is welcome; make a new topic in the Discussion and Support forum.

I just committed the fix, both Thierry's fix to testoxy.i, and the fix to yorick/oxy.c for the uninitialized variable in Y_is_obj that caused testoxy.i to work correctly for me, while failing for Francois.

Eternal vigilance...

Please keep the bug reports coming in.

Sat Jul 17, 2010 2:48 pm

sguieu

Yorick Guru

Joined: Thu May 10, 2007 12:07 pmPosts: 62

Nice ! Very nice. It opens a lot of new possibilities.

I am wondering about one thing: is it wanted that obj("x") and obj.x have not the same behavior when the member "x" does not exists ? e.g.:

From my point of view I would prefer that both return a void value instead of an error as when you type an empty symbol in yorick. (Sure it still can be tested with obj(-,"x") ).

-------------------------------------- Optional Reading -------------------------------------Did you plan to make users able to change the behavior of evaluation (e.g.: obj(args)) or the member extraction with the "." operator (e.g. obj.member) by a yorick user function ?

It would be great if one can define the member extraction (and the evaluator) like as follow:

I am agree that it can be confusing and one can make infinity loop easily, plus one need a dedicated built in function to get the member of object without calling the user evaluator function (e.g. gget(obj,"x") ).
I can feel that you will not like to do that

It seems that when you do not explicitly add a void argument use() return a void object inside the function test. [/code]

Thu Sep 09, 2010 11:13 am

dnagle

Yorick Master

Joined: Wed Jun 01, 2005 11:34 amPosts: 112

I believe that's a feature. From the documentation under "help, oxy":

Code:

When you pass more than one argument to an object, the first onespecifies a single member, and subsequent arguments apply to thatmember. Thus, obj(m, i, j, k) is similar to obj(m)(i, j, k)In fact, these are exactly the same as long as M does not specifya function. When M is a function, there is a slight difference,which is that the function (whether built-in or interpreted) isexecuted in the context of the object obj.

So of your three test cases, only the third called "test" using the object's context. Specifically:

a(test) -- calls test as a subroutine without context

a(test)() -- calls test as a function without context

a(test,) -- calls test as a function with context

To add a few more cases:

a.test -- calls test as a subroutine without context

a.test() -- calls test as a function without context

a, test -- calls test as a subroutine with context

Fri Sep 10, 2010 6:32 am

sguieu

Yorick Guru

Joined: Thu May 10, 2007 12:07 pmPosts: 62

Hum, okay, but, from the yorick-user-point-of-view, does it makes sense that
"a, test" is called with context and "a(test)" without context ?
Naturally, without thinking to much (that my way), I would believe that both are called with context one as subroutine the other as function.

Mon Sep 13, 2010 7:22 am

dnagle

Yorick Master

Joined: Wed Jun 01, 2005 11:34 amPosts: 112

I think it makes sense. "a(test)" asks Yorick to retrieve the value for "test" in "a". In this case, it's a function reference. Then, since you put that function reference on a line by itself without any functional arguments, it gets evaluated as a subroutine. Perhaps it'd help to consider that it's effectively equivalent to the following:

Code:

> tmp = a(test)> tmp

Once you've pulled the value for "test" outside of the object, it no longer has its context.

If "a(test)" called test as a function, then you'd have no way to just retrieve the value for "test".

Mon Sep 13, 2010 9:30 am

sguieu

Yorick Guru

Joined: Thu May 10, 2007 12:07 pmPosts: 62

When there is a cyclic reference, the info function cause an infinite loop :

DNagle's answers are correct for the most part. Cyclic references are never correct in yorick; there is no way to delete them because yorick uses reference counting, not garbage collection. That's a feature, not a bug. So you need to design your data structures (of all kinds, not just objects -- it's easy to create a ring of pointers that fails for the same reason) so that they are trees, not rings. This is a pretty minor design requirement, I think, but you do need to be aware of it.

Let me try to clarify what goes wrong with both obj(method)(args) and obj.method(args). In both cases, if you disassemble the virtual machine code (with the disassemble function), you will see that the Eval or GetMember call happens before any of the args are even pushed onto the stack. Thus, the interpreter has no idea what you are going to DO with the method member. Furthermore, the method function, which is the return value of the Eval or GetMember action, has no idea that it "belongs" to the obj object -- in fact, it will usually be a member of many different object instances. Hence, by the time the args are being pushed onto the stack, let alone by the time of the Eval action corresponding to the final close parenthesis, the interpreter has completely forgotten that the method was extracted from obj. Thus it is not possible even in principle for those syntaxes to yield a call to method in the context of obj.

Eventually, I would like to change the parser to make x.m(args) produce exactly the same virtual machine code as x("m",args). At that point, the object.method(args) syntax will work properly, that is, it will work the same as in C++ or Java. That syntax will always be slightly less efficient than object(method,args), however, because the lookup of the string "method" is deferred to runtime in the former case, while the parser does the lookup in the latter case. So I encourage you to get used to the current syntax.

I'm not sure that I understand the get_my_member feature request in the 08/Sep sguieu post. I think the API can already do what you want, just in a slightly different way.

Mon Sep 20, 2010 7:15 pm

sguieu

Yorick Guru

Joined: Thu May 10, 2007 12:07 pmPosts: 62

Would it be more logic that when an oxy object is called with a void argument it return a copy of the object instead of the object itself ?

Code:

> g = save(a=1, b=2)> g() == g1> g(1:0) == g0

I do not see any cases where this behavior can be useful but it had, for me, a bit of confusion.

Who is online

Users browsing this forum: No registered users and 1 guest

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