I'm new to PeopleCode and as I'm learning functions, I noticed that in PeopleCode, we'd normally pass value using %PATIENT_ID. A friend told me that you can also pass by reference in PeopleCode but how?
PeopleCode passes by reference for functions.
Function addOne(&num As integer)
&num = &num + 1
End-Function;
Local integer &val = 9;
addOne(&val);
MessageBox(0, "", 0, 0,String(&val));
Results in 10
If you are using App Classes it behaves differently
for methods:
Pass by value for simple types (string, int, number,etc)
Pass by reference for objects (rowsets, records, app classes)
Can pass by reference for simple types using the OUT keyword in the parameter list
method addOne(&num as integer out)
Functions which are defined in the same context as the executing code, e.g. page/component/record/field event PeopleCode, always consider parameters as refernces.
Within Application Classes, parameters of simple types on methods can be defined with the 'out' key word to state that they are a references. Methods also automatically pass parameters as references for complex types. Think: "If there is a lot of data, it is a reference"
This documentation will be very helpful for you.
https://docs.oracle.com/cd/E26239_01/pt851h3/eng/psbooks/tpcr/chapter.htm?File=tpcr/htm/tpcr07.htm
Passing Parameters with Object Data Types
Parameters with object data types are always passed by reference:
/* argument passed by reference */
method storeInfo(&f as File);
If you specify the out modifier for a method parameter with an object
data type, it becomes a reference parameter. This means that the
parameter variable is passed by reference instead of the object that
it is pointing at when passed.
For example, if you pass an object parameter with the out modifier:
method myMethod(&arg as MyObjectClass);
Local MyObjectClass &o1 = create MyObjectClass("A");
Local MyOtherObjectClass &o2 = create MyOtherObjectClass();
&o2.myMethod(&o1);
And inside myMethod this occurs:
Method myMethod
&arg = create MyObjectClass("B");
end-method;
Since the method argument is reassigned within the body of myMethod,
&o1 does not point at the new instance of MyObjectClass (initialized
with "B") after the method call completes. This is because &o1 still
references the original instance of MyObjectClass.
However, if &o1 had been passed with the out modifier, after the
method call completes, &o1 points at whatever the parameter was last
assigned to; in this case, the new instance of MyObjectClass. The
parameter, rather than the object, is passed by reference. Using
the Out Specification for a Parameter
In the following example, a class, AddStuff, has a single public
method, DoAdd. This adds two numbers together, then assigns them as
different numbers. In the signature of the method declaration, the
first parameter is not declared with an out statement, while the
second one is.
class AddStuff
method DoAdd(&P1 as number, &P2 as number out);
end-class;
method DoAdd
&X = &P1 + &P2;
&P1 = 1;
&P2 = 2;
end-method;
In the following PeopleCode example, an object named &Aref is
instantiated from the class AddStuff. Two parameters, &I and &J are
also defined.
local AddStuff &Aref = Create AddStuff();
local number &I = 10;
local number &J = 20;
The following code example is correct. &J is changed, because of the
outstatement in the method signature, and because the value is being
passed by reference. The value of &I is not updated.
&Aref.DoAdd(&I, &J); /* changes &J but not &I */
The following code example causes a design time error. The second
parameter must be passed by reference, not by value.
&Aref.DoAdd(10, 20); /* error - second argument not variable */
Related
Consider this dart code:
T t = T() // id field defaults to null
List<T> list = List()..add(t);
t.id = '123';
print('${list.first.id}') // What's output?
My question is about whether passed items to List are copied over to List or it's a reference.
I've encountered this ambiguity because I'm using flutter_redux where an action contains an instance of class T. on reducer, I add this T instance to my state. later on, in the middleware, I update this t's id. But surprisingly id field on the state(in this case List) changes too! So my only guess is that objects are passed by reference. Is this assumption correct?
Everything in Dart is an Object, so anything you are passing is passed by reference.
From the Dart Language Tour:
Everything you can place in a variable is an object, and every object
is an instance of a class. Even numbers, functions, and null are
objects. All objects inherit from the Object class.
mutable/immutable objects
There is a difference however between mutable and immutable objects. Some objects are immutable, and therefore cannot be modified, while mutable objects can be modified.
An example of immutable objects is String objects.
An example of mutable object is List just like you observed in your example.
constness
Dart has another interesting type of object, and if you are familiar with C++ or C, you would have encountered these. These are compile-time constants (const), and carry with them an attribute of immutability. Any object can be declared as const at the point of creation, provided the constructor being called has been declared as const.
Watch out with const objects if you are passing them to functions that expect mutable objects because attempting to mutate the constant, will result in a runtime error.
void modl(final List<int> l) {
l.add(90);
print(l);
}
void main() {
List<int> l = const [1,2,3,4];
modl(l); // Uncaught Error
print (l);
}
Running the above program will result in an Uncaught Error because l is a compile-time constant.
See Detecting when a const object is passed to a function that mutates it, in Dart
james=open('C:/Users/skora da_bura/Documents/data.txt')
jake=james.read()
james.close()
numblist=[]
charlist=[]
def Read(numblist,charlist):
for i in range(0,len(jake),4):
numblist.append(int(jake[i]))
for i in range(2,len(jake),4):
charlist.append(jake[i])
Bring = numblist,charlist
james = open('C:/Users/skora da_bura/Documents/data.txt')
jake22 = james.readlines()
james.close()
back='Number of lines read',len(jake22)
return back
print(Read([],[]))
print(charlist)
the charlist returns [] even though I had appended values to it to make a list when I was defining the function Read.
I don't seem to see what the problem is with the code
The charlist you define in the signature of Read shadows the global charlist. They're different variables that happen to have the same name. If you intend to modify the global variable, you shouldn't try to pass it as a parameter.
I am looking for examples of Chapel passing by reference. This example works but it seems like bad form since I am "returning" the input. Does this waste memory? Is there an explicit way to operate on a class?
class PowerPuffGirl {
var secretIngredients: [1..0] string;
}
var bubbles = new PowerPuffGirl();
bubbles.secretIngredients.push_back("sugar");
bubbles.secretIngredients.push_back("spice");
bubbles.secretIngredients.push_back("everything nice");
writeln(bubbles.secretIngredients);
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
bubbles = kickAss(bubbles);
writeln(bubbles.secretIngredients);
And it produces the output
sugar spice everything nice
sugar spice everything nice Chemical X
What is the most efficient way to use a function to modify Bubbles?
Whether Chapel passes an argument by reference or not can be controlled by the argument intent. For example, integers normally pass by value but we can pass one by reference:
proc increment(ref x:int) { // 'ref' here is an argument intent
x += 1;
}
var x:int = 5;
increment(x);
writeln(x); // outputs 6
The way that a type passes when you don't specify an argument is known as the default intent. Chapel passes records, domains, and arrays by reference by default; but of these only arrays are modifiable inside the function. ( Records and domains pass by const ref - meaning they are passed by reference but that the function they are passed to cannot modify them. Arrays pass by ref or const ref depending upon what the function does with them - see array default intent ).
Now, to your question specifically, class instances pass by "value" by default, but Chapel considers the "value" of a class instance to be a pointer. That means that instead of allowing a field (say) to be mutated, passing a class instance by ref just means that it could be replaced with a different class instance. There isn't currently a way to say that a class instance's fields should not be modifiable in the function (other than making them to be explicitly immutable data types).
Given all of that, I don't see any inefficiencies with the code sample you provided in the question. In particular, here:
proc kickAss(b: PowerPuffGirl) {
b.secretIngredients.push_back("Chemical X");
return b;
}
the argument accepting b will receive a copy of the pointer to the instance and the return b will return a copy of that pointer. The contents of the instance (in particular the secretIngredients array) will remain stored where it was and won't be copied in the process.
One more thing:
This example works but it seems like bad form since I am "returning" the input.
As I said, this isn't really a problem for class instances or integers. What about an array?
proc identity(A) {
return A;
}
var A:[1..100] int;
writeln(identity(A));
In this example, the return A in identity() actually does cause a copy of the array to be made. That copy wasn't created when passing the array in to identity(), since the array was passed by with a const ref intent. But, since the function returns something "by value" that was a reference, it's necessary to copy it as part of returning. See also arrays return by value by default in the language evolution document.
In any case, if one wants to return an array by reference, it's possible to do so with the ref or const ref return intent, e.g.:
proc refIdentity(ref arg) ref {
return arg;
}
var B:[1..10] int;
writeln(refIdentity(B));
Now there is no copy of the array and everything is just referring to the same B.
Note though that it's currently possible to write programs that return a reference to a variable that no longer exists. The compiler includes some checking in that area but it's not complete. Hopefully improvements in that area are coming soon.
My Objective is:
Using MATLAB, set the property value within one class method, and the property values are different between instances.
My Problem is:
When using SET in the class method, I will change the property value of all instances of this class, which is not what I want. I only want to change the property value of this instance.
About the dynamic property: I think it's used to create a unique property of the instance instead of setting the unique value of a general class property, is that right?
Code example:
classdef Storage
properties
tree = containers.Map('KeyType','int32', 'ValueType','any')
end
methods
function obj = set_tree(obj,period, value)
obj.tree(period) = value;
end
end
end
When setting the value using this method:
st1 = Storage();
st2 = Storage();
st1 = st1.set_tree(10,1);
st2 = st2.set_tree(10,2);
Right now, the value set to st2.tree(10) will override the value set to st1.tree(10), which I am trying to avoid.
The problem you're having is caused by setting a handle class object as a default value for a class property. The relevant documentation says this:
MATLAB® evaluates property default values only once when loading the class. MATLAB does not reevaluate the assignment each time you create an object of that class. If you assign an object as a default property value in the class definition, MATLAB calls the constructor for that object only once when loading the class.
So, for your Storage class above, all of your instances will be using the same default containers.Map object stored in the tree property. And since the containers.Map class is a subclass of the handle class it has reference behavior, which means the copies of the object will all point to the same underlying key/value map. If you want independent objects for each instance, you can initialize the tree property in the constructor:
classdef Storage
properties
tree
end
methods
function obj = Storage()
obj.tree = containers.Map('KeyType','int32', 'ValueType','any');
end
function obj = set_tree(obj, value, period)
obj.tree(period) = value;
end
end
end
This class example was taken from here.
class Celsius:
def __init__(self, temperature = 0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value")
return self._temperature
def set_temperature(self, value):
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
temperature = property(get_temperature, set_temperature)
The idea here is that when we create an instance of Celsius and set the temperature attribute (e.g. foo = Celsus (-1000) ), we want to make sure that the attribute is not less than -273 BEFORE setting the temperature attribute.
I don't understand how it seems to bypass self.temperature = temperature and go straight to the last line. It seems to me like there are three attributes/properties created here: the Class attribute, temperature; the Instance attribute, temperature; and the set_temperature function which sets the attribute _temperature.
What I DO understand is that the last line (the assignment statement) must run the code property(get_temperature, set_temperature) which runs the functions get_temperature and set_temperature and intern sets the private attribute/property _temperature.
Moreover, if I run: foo = Celsius(100) and then foo.temperature, how is the result of foo.temperature coming from temperature = property(get_temperature, set_temperature) and thus _temperature AND NOT self.temperature = temperature? Why even have self.temperature = temperature if temperature = property(get_temperature, set_temperature) gets ran every time the foo.temperature call is made?
More questions...
Why do we have two attributes with the same name (e.g. temperature) and how does the code know to retrieve the value of _temperature when foo.temperature is called?
Why do we need private attributes/properties an not just temperature?
How does set_temperature(self, value) obtain the attribute for parameter value (e.g. the argument that replaces value)?
In short, please explain this to me like a three year old since I have only been programming a few months. Thank you in advance!
When we are first taught about classes/objects/attributes we are often told something like this:
When you look up an attribute like x.foo it first looks to see if
'foo' is an instance variable and returns it, if not it checks if
'foo' is defined in the class of x and returns that, otherwise an
AttributeError is raised.
This describes what happens most of the time but does not leave room for descriptors. So if you currently think the above is all there is about attribute lookup property and other descriptors will seem like an exception to these rules.
A descriptor basically defines what to do when looking up / setting an attribute of some instance, property is an implementation that lets you define your own functions to call when getting / setting / deleting an attribute.
When you do temperature = property(get_temperature, set_temperature) you are specifying that when x.temperature is retrieved it should call x.get_temperature() and the return value of that call will be what x.temperature evaluates to.
by specifying set_temperature as the setter of the property it states that when ever x.temperature is assigned to something it should call set_temperature with the value assigned as an argument.
I'd recommend you try stepping through your code in pythontutor, it will show you exactly when get_temerature and set_temperature are called after which statements.