I'm guessing this question is going to apply to many similar languages other than MQL4 such as c++ (which I also forget how to use) which require you manually specify when you are passing by reference.
Method reference:
int[] previous = GetPrevious(i, ZigZagBuffer);
Method definition:
int GetPrevious[](int current, const double& buffer[])
{
int count = 0;
int result[];
// calculate count
ArrayResize(result,count);
// fill array
return result;
}
The resulting compile error is:
"Invalid Array Access"
From what I understand, this is because array's can only be passed by reference, but you have to explicitly state that you are passing it by reference. But the more I look up the syntax for passing by reference, the more I find articles about passing parameter by reference. (which I already know how to do as you can see in the code example.)
What is the syntax to assign the output of a method to a variable?
In case it matters, I only need to read the array multiple times; I'm not needing to alter or re-assign it after it is declared.
You cannot return array. You have to create it and pass into the function, fill inside the function and that's it.
OnTick(){
double array[]; //declaration of the array
fillArray(array,10); //passing array by ref, updating it there
Print(array[0]=0 && array[9]=9);//returns true
}
void fillArray(double &array[],int size){
ArrayResize(array,size);
for(int i=0;i<size;i++){array[i]=i;}
}
Related
ScreenShot of CodeCould someone please explain to me how everything works in this script except a simple int counter that I pass in as a parameter? However if I directly pass in the int counter field into the method instead of using/ref. the para, it works just fine, how is this even possible? HELP!
By default parameters you give to the function, are evaluated and its value is passed (eg. not int xy is passed but the value of int xy, so 5).
So if you change the value directly eg. CounterAi -= 1; you are just changing the value you've passed on not the underlying variable. So if you want to use Pass by Reference in these cases you must use out or ref.
If you change a parameter of the passed value however it's value will be changed without needing to use ref or out.
Example:
public void Example1(int myValue) {
// This won't change the actual variable, just the value of the parameter,
// that has been passed
myValue -= 1;
}
public void Example2(ref int myValue) {
// This will change the actual variable,
// it's changing just the value of the parameter again,
// but we're using pass by reference
myValue -= 1;
}
public void Example3(Transform finishLine) {
// This will change the actual variable,
// because it's changing the data within the object,
// that the parameter value refers to.
finishLine.position = flSpts[Random.Range(0, flSpots.Count)].position;
}
With arrays you can use a subscript to access Array Elements directly. You can read or write to them. With Sets I am not sure of a way to write its Elements.
For example, if I access a set element matching a condition I'm only able to read the element. It is passed by copy and I can't therefore write to the original.
For example:
columns.first(
where: {
$0.header.last == Character(String(i))
}
)?.cells.append(value: addValue)
// ERROR: Cannot use mutating member on immutable value: function call returns immutable value
You can't just change things inside a set, because of how a (hash) set works. Changing them would possibly change their hash value, making the set into an invalid state.
Therefore, you would have to take the thing you want to change out of the set, change it, then put it back.
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
columns.remove(thing)
thing.cells.append(value: addValue)
columns.insert(thing)
}
If the == operator on Column doesn't care about cells (i.e. adding cells to a column doesn't suddenly make two originally equal columns unequal and vice versa), then you could use update instead:
if var thing = columns.first(
where: {
$0.header.last == Character(String(i))
}) {
thing.cells.append(value: addValue)
columns.update(thing)
}
As you can see, it's quite a lot of work, so maybe sets aren't a suitable data structure to use in this situation. Have you considered using an array instead? :)
private var _columns: [Column]
public var columns : [Column] {
get { _columns }
set { _columns = Array(Set(newValue)) }
// or any other way to remove duplicate as described here: https://stackoverflow.com/questions/25738817/removing-duplicate-elements-from-an-array-in-swift
}
You are getting the error because columns might be a set of struct. So columns.first will give you an immutable value. If you were to use a class, you will get a mutable result from columns.first and your code will work as expected.
Otherwise, you will have to do as explained by #Sweeper in his answer.
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.
Hi I am trying to init an object with a double value in the format double filter[3][3];
but i keep getting the following error.
cannot convert 'double[3][3]' to 'double' in assignment.
in my header i have this
#interface filter : NSObject
{
double **matrix;
}
#property(nonatomic)double **matrix;
-(id)initWithMatrix:(double**)filterMatrix;
inside my class i have this method.
-(id)initWithMatrix:(double**)filterMatrix
{
matrix = filterMatrix;
return self;
}
and i am trying to call it like this.
double filter[3][3] = {0,0,0,0,1,0,0,0,0};
MyMatrix *myMatrix = [[MyMatrix alloc] initWithMatrix:filter];
I now get the error.
Error: Cannot convert double[*][3] to double** in argument passing
Any help on this issue would be amazing.
Thanks
A
That's because double** isn't the equivalent of double[*][*]. In fact, double[*][*] is an invalid type, because it leaves the stride undefined. double** is a pointer to a pointer to a double, or to put it another way, it's a pointer to an array of doubles. You should just use double* as your type.
Edit: To clarify, double[*][3] is still just an array of doubles, even though it has 2 dimensions. This is still the equivalent of double*.
A two-dimensional array is not the same thing as a pointer-to-a-pointer. You have two choices - change the filter class to contain a 2D array, or change your initialization to use pointer-to-pointers.
In choice #1, you're could keep a copy of the array in your filter instance, instead of just holding a pointer. You need to change the class interface:
#interface filter : NSObject
{
double matrix[3][3];
}
-(id)initWithMatrix:(double[3][3])filterMatrix;
Then your implementation of initWithMatrix: can just do a memcpy() or the equivalent to copy the data into your instance.
Choice #2 is a bit different. Keep your other code the way it is, but change your initialization of filter:
double row0[3] = {0,0,0};
double row1[3] = {0,1,0};
double row2[3] = {0,0,0};
double **filter[3] = { row0, row1, row2 };
It's probably safer to malloc() all of those arrays, since otherwise you're going to end up with references to stack variables in your filter class, but I think you get the idea.
you are passing as a parameter a double 2d array(double[][]) when your method signature asks for a double (a primitive like 34.2).
set the method declaration to
- (id)initWithMatrix:(double*) matrix;
this passes a pointer to your array (2d) to the method.
edit: missed a semicolon.
Hi I am trying to init an object with a double value in the format double filter[3][3];
but i keep getting the following error.
cannot convert 'double[3][3]' to 'double' in assignment.
in my header i have this
#interface filter : NSObject
{
double **matrix;
}
#property(nonatomic)double **matrix;
-(id)initWithMatrix:(double**)filterMatrix;
inside my class i have this method.
-(id)initWithMatrix:(double**)filterMatrix
{
matrix = filterMatrix;
return self;
}
and i am trying to call it like this.
double filter[3][3] = {0,0,0,0,1,0,0,0,0};
MyMatrix *myMatrix = [[MyMatrix alloc] initWithMatrix:filter];
I now get the error.
Error: Cannot convert double[*][3] to double** in argument passing
Any help on this issue would be amazing.
Thanks
A
That's because double** isn't the equivalent of double[*][*]. In fact, double[*][*] is an invalid type, because it leaves the stride undefined. double** is a pointer to a pointer to a double, or to put it another way, it's a pointer to an array of doubles. You should just use double* as your type.
Edit: To clarify, double[*][3] is still just an array of doubles, even though it has 2 dimensions. This is still the equivalent of double*.
A two-dimensional array is not the same thing as a pointer-to-a-pointer. You have two choices - change the filter class to contain a 2D array, or change your initialization to use pointer-to-pointers.
In choice #1, you're could keep a copy of the array in your filter instance, instead of just holding a pointer. You need to change the class interface:
#interface filter : NSObject
{
double matrix[3][3];
}
-(id)initWithMatrix:(double[3][3])filterMatrix;
Then your implementation of initWithMatrix: can just do a memcpy() or the equivalent to copy the data into your instance.
Choice #2 is a bit different. Keep your other code the way it is, but change your initialization of filter:
double row0[3] = {0,0,0};
double row1[3] = {0,1,0};
double row2[3] = {0,0,0};
double **filter[3] = { row0, row1, row2 };
It's probably safer to malloc() all of those arrays, since otherwise you're going to end up with references to stack variables in your filter class, but I think you get the idea.
you are passing as a parameter a double 2d array(double[][]) when your method signature asks for a double (a primitive like 34.2).
set the method declaration to
- (id)initWithMatrix:(double*) matrix;
this passes a pointer to your array (2d) to the method.
edit: missed a semicolon.