New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't log into http://yorick.sourceforge.net/phpBB3/ #16

Closed
jameshume opened this Issue Jun 1, 2015 · 2 comments

Comments

Projects
None yet
2 participants
@jameshume
Copy link

jameshume commented Jun 1, 2015

Hi,

Sorry to post this here, I know it's not a Yorick issue, but I cannot for the life of me log into the user forums (I used link off website: http://yorick.sourceforge.net/phpBB3/).

I know the following works

a = [1,2,3,4,5,6]
eq_nocopy, b, a
b(1) = 111
a(1)
111

All well and good. Should the following work?

a = [1,2,3,4,5,6]
eq_nocopy, b, a([1,3,5])
b(1) = 111
a(1)
1 /*< oops */

I was hoping that eq_nocopy()ing an array slice would not copy the slice but copy a reference to the slice. Should eq_nocopy be doing this (i.e., am i using it wrong) or is this not what it is for?

Many thanks,
James

@dhmunro

This comment has been minimized.

Copy link
Owner

dhmunro commented Jun 1, 2015

Yes, sorry about the forums. I can't figure out how to fix it -- if you are a phpBB3 expert, any advice on how to migrate to the sourceforge supported BB would be greatly appreciated.

You cannot do what you want in yorick -- there is no way a yorick array variable can reference a discontiguous hunk of memory. Yorick treats eq_nocopy like any other function, so it's arguments are evaluated before eq_nocopy is ever called. Thus, a([1,3,5]) is a temporary array of three elements whose values are copied from a. The lines::

eq_nocopy, b, <any yorick expression except a simple variable reference>;
b = <any yorick expression except a simple variable reference>;

have precisely the same effect, although the former is slightly slower. However, in the second case, yorick makes a distinction when the RHS is a simple variable reference::

b = a;

Usually, yorick uses references to arrays wherever possible. However, in my opinion, the overwhelming majority of the cases in which you write this statement, what you mean is for b to be a copy of a -- otherwise, you would have simply used a in whatever code followed. Therefore, yorick makes a copy. Python, for example, has the opposite behavior, which is one of the few serious inconveniences in that language. But the yorick convention has the downside that in the rare instances you do not want a copy, you have no way to achieve that. Hence the eq_nocopy function.

To go beyond your question, you might ask, so why do you ever need eq_nocopy? The answer has to do with how yorick's assignment operator notices that the RHS is a, as opposed to, say, a+0. Yorick has no garbage collection; instead it maintains a use count for every object, and when the use count drops to zero, it promptly destroys the object. (This rules out circular references in yorick -- a small loss in my opinion, since every language that supports them requires extremely complex memory management, and objects using them tend to become a kind of circus for code maintainers.) So the yorick redefinition operator looks at the use counter of the RHS object. The result of any yorick expression will have only a single use -- it is owned by the stack and nothing else. The redefinition operator knows that it will drop the RHS off the stack when it's done, and since that is its only use, it will be destroyed. Hence it makes no sense to make an identical copy -- it just steals the reference directly off the stack instead. On the other hand, the simple variable reference a has two uses -- the stack owns one, while the variable a owns the other. Hence, the redefinition operator makes a new copy. In either case, b winds up with the sole use of the object -- b=something makes a new thing called b in yorick.

I still haven't told you what eq_nocopy is good for. Consider a pointer p. The pointer owns a reference to an array, and the expression *p does not make a copy of that array -- it just pushes a use of the array onto the stack. Thus, the result of the expression *p has left an array on the stack with two uses -- the stack owns one, and the pointer p owns the other. Thus::

b = *p;   // makes b a copy of *p
eq_nocopy, b, *p;  // makes b refer to *p

The same problem arises with oxy_obj.b as with *p -- another important use case for eq_nocopy.

Unlike numpy, yorick does not have any way to refer to a slice of an object. All slicing operations happen immediately and result in a temporary array. On the LHS of an assignment statement, the slicing is deferred until the assignment takes place. Instead of creating a slice object, yorick encourages you to keep an index array pointing into your object when you want to assign back into the same subset you used for a calculation. This typically increases performance at the expense of using more memory than having an abstraction for slices. In your case, what you wanted was::

list = [1,3,5];
b = a(list);
a(list) = some_function_of(b);   // usual case
a(list(j)) = b(j);   // occasionally want only partial updates

The question is, why would you want to assign to b(1) instead of assigning directly to a(list(1))? Perhaps you really wanted to split up a into more subsets?

@dhmunro dhmunro closed this Jun 2, 2015

@jameshume

This comment has been minimized.

Copy link

jameshume commented Jun 2, 2015

Hi David,

Unfortunately I've never used phpBB :-S Thanks for getting back to me though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment