Ultra Ironic: References in Papyrus are Pass-By-Value!

Post » Tue Jun 19, 2012 1:26 pm

OK, so the programmers here will probably find this amusing. There are two methods of passing variables to a function.

Pass By Value: Only the value of the variable is passed to the function. It cannot be changed in order to change the original variable back in the function it was called from.

Pass By Reference: The variable can be changed from within the function, and any changes will be reflected when control returns to the calling function.

The ironic part...References in Papyrus are Pass-By-Value! So you can't get more than one reference changed by any particular function!

For example, let's say you want to reverse the variables akActor1 and akActor2 back in the calling function by calling a function to do so

MyReferenceSwapFunction(Actor akActor1, Actor akActor2); Do some stuff here.    Actor TempHolder = akActor1    akActor1 = akActor2    akActor2 = TempHolder; Do some more stuff here.endFunction

won't work!
User avatar
Marie
 
Posts: 3405
Joined: Thu Jun 29, 2006 12:05 am

Post » Tue Jun 19, 2012 8:20 pm

Yeah, object variables are essentially pointers, but whenever something is passed to a function a copy is made, and the copy is used in the function.

It would probably be a good idea to make this information available somewhere, as telling people that object variables are essentially pointers does have the implication that they'd also be pass-by-reference. Any ideas where on the wiki might be most appropriate? The http://www.creationkit.com/Function_Reference#Parameters section of the function reference perhaps? That section currently has this:
Parameters are essentially http://www.creationkit.com/Variable_Reference the function has access to that the caller gives initial values to.
This phrase seems to imply what you've shared here, but I wouldn't have thought so if it weren't already on my mind.

Cipscis
User avatar
stevie trent
 
Posts: 3460
Joined: Thu Oct 11, 2007 3:33 pm

Post » Wed Jun 20, 2012 1:22 am

OK, so the programmers here will probably find this amusing. There are two methods of passing variables to a function.

Pass By Value: Only the value of the variable is passed to the function. It cannot be changed in order to change the original variable back in the function it was called from.

Pass By Reference: The variable can be changed from within the function, and any changes will be reflected when control returns to the calling function.

The ironic part...References in Papyrus are Pass-By-Value! So you can't get more than one reference changed by any particular function!

For example, let's say you want to reverse the variables akActor1 and akActor2 back in the calling function by calling a function to do so

MyReferenceSwapFunction(Actor akActor1, Actor akActor2); Do some stuff here.    Actor TempHolder = akActor1    akActor1 = akActor2    akActor2 = TempHolder; Do some more stuff here.endFunction

won't work!
I'm pretty much a programming novice, so I really don't understand many of the intricacies between different languages, but what you explain seemed to invoke a "well, duh..." response in me. I think I must have only worked in languages where values are passed by value and not reference. In what programming languages would your example code function correctly?
User avatar
mollypop
 
Posts: 3420
Joined: Fri Jan 05, 2007 1:47 am

Post » Tue Jun 19, 2012 8:12 pm

In C++, for example, it's possible to declare a function with "pass by reference" parameters like this:
void foo(int &bar)
That would allow you to pass an integer value into the function "foo" just like normal, but instead of being passed by value it's passed by reference, so instead of manipulating a copy of the variable passed into the function, you'd be manipulating the very same variable.

Cipscis
User avatar
sarah taylor
 
Posts: 3490
Joined: Thu Nov 16, 2006 3:36 pm

Post » Wed Jun 20, 2012 12:03 am

In C++, for example, it's possible to declare a function with "pass by reference" parameters like this:
void foo(int &bar)
That would allow you to pass an integer value into the function "foo" just like normal, but instead of being passed by value it's passed by reference, so instead of manipulating a copy of the variable passed into the function, you'd be manipulating the very same variable.

Cipscis
Oh that's right, I remember doing that now. (Been a good year since I was taught C++, haven't really worked in it since.)
User avatar
Tanya Parra
 
Posts: 3435
Joined: Fri Jul 28, 2006 5:15 am

Post » Tue Jun 19, 2012 11:32 pm

Forgive me, but isn't this how pointers normally work?

As in "Actor akActor1" is actually a pointer to an object of type Actor.
And akActor2 is another pointer.

No copy is made of the objects themselves (nor would we want to - we want that actor to stay where it is).
Instead, the function is sent pointers to them.
These pointers belong to the function only, so assigning them to each other (which modifies only the pointer) will have no effect on the objects themselves. Only actions that modify the object pointed to by the pointer will have an effect outside of the function.
Isn't that basically the point of pass-by-reference? The objects are passed by reference, via pointers, while POINTERS are passed by value?
User avatar
Brιonα Renae
 
Posts: 3430
Joined: Mon Oct 22, 2007 3:10 am

Post » Tue Jun 19, 2012 12:46 pm

The thing about pass-by-reference is that you can change the values of the actual variables. In this case, that would mean changing the addresses stored in object variables.

Instead, because it's pass-by-value, the address is passed to the function, but altering the address is not reflected in the variable that was passed to the function.

Cipscis
User avatar
Beat freak
 
Posts: 3403
Joined: Thu Dec 14, 2006 6:04 am

Post » Tue Jun 19, 2012 3:06 pm

Forgive me, but isn't this how pointers normally work? As in "Actor akActor1" is actually a pointer to an object of type Actor. And akActor2 is another pointer. No copy is made of the objects themselves (nor would we want to - we want that actor to stay where it is). Instead, the function is sent pointers to them. These pointers belong to the function only, so assigning them to each other (which modifies only the pointer) will have no effect on the objects themselves. Only actions that modify the object pointed to by the pointer will have an effect outside of the function. Isn't that basically the point of pass-by-reference? The objects are passed by reference, via pointers, while POINTERS are passed by value?

Um, no...a "pointer" can be re-directed to another reference...and the compiler doesn't complain if you do so, but often, you'll want to change more than one variable in a function (For example, if you want to set the X, Y, and Z variables you're going to be using to do rotations), but in Papyrus you can't do it...which is why the functions GetAngleX() GetAngleY() and GetAngleZ() are needed...you can't just say GetAngle(X,Y,Z) because there is no PBR in Papyrus.

And they haven't been called Pointers in quite a while...they're "references" now....
User avatar
Rinceoir
 
Posts: 3407
Joined: Thu Jun 29, 2006 1:54 am

Post » Tue Jun 19, 2012 11:34 pm

Are we sure there's not a mechanism for doing pass by reference? That can be incredibly handy at times.
User avatar
Marine x
 
Posts: 3327
Joined: Thu Mar 29, 2007 4:54 am

Post » Tue Jun 19, 2012 7:40 pm

hahaha..../courtesy laugh
User avatar
Sammykins
 
Posts: 3330
Joined: Fri Jun 23, 2006 10:48 am

Post » Tue Jun 19, 2012 11:08 am

Are we sure there's not a mechanism for doing pass by reference? That can be incredibly handy at times.
That's the bottom line. If function parameters are byVal only then we should make sure it's documented like Cipscis suggested.

There are plenty of way around this limitation. Returning an object or structure, setting values in Global variables, iterative calls, etc. The documentation could include a few examples of how to optimally account for this in Papyrus.
User avatar
Isabell Hoffmann
 
Posts: 3463
Joined: Wed Apr 18, 2007 11:34 pm

Post » Wed Jun 20, 2012 1:37 am

Array variables are passed by reference.

So yeah there's a workariound.
It's a shame that they're 1D only, and must contain all of the same type.
User avatar
Laura Mclean
 
Posts: 3471
Joined: Mon Oct 30, 2006 12:15 pm

Post » Tue Jun 19, 2012 4:07 pm

Actually, I think array variables are passed by value as well, although because of how they're set up you can edit the data stored in their elements and the change will be reflected outside the function.

Cipscis
User avatar
Alberto Aguilera
 
Posts: 3472
Joined: Wed Aug 29, 2007 12:42 am

Post » Tue Jun 19, 2012 9:57 pm

Yeah, Arrays are actually a reference to an array object (Thus the use of the "new" keyword in their creation)
User avatar
candice keenan
 
Posts: 3510
Joined: Tue Dec 05, 2006 10:43 pm


Return to V - Skyrim