Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • passing mata function arguments by value so they are not modified within the function

    I am having problems with a real scalar argument being passed to a Mata function having its value changed by the calling code. In programming terms I would like to pass the argument by value, but instead it is being passed by reference. It is obvious how to do the reverse (pass the pointer and then de-reference it within the called function), but I am stuck with how to pass the value only (i.e perform a bitwise copy to a new memory address). The example and output proving the passed scalar is being modified is included below. Thanks for your help.

    Code:
    class searchArgs {
        public real scalar x,n,p
        public void toString()
    }
    
    void searchArgs::toString(){
        printf("x:%f,n:%f,p:%f",this.x,this.n,this.p);
    }
    
    real scalar BinarySearch(
        real scalar target,
        real scalar min,
        real scalar max,
        class searchArgs scalar sa,
        pointer(real scalar function) delegate,
        | real scalar approx,
        real scalar maxIts)
    {
        real scalar k, val, argLen;
        argLen = args();
        if (argLen<6){
            approx = 0.0005;
        }
        if (argLen < 7){
            maxIts = 200;
        }
        for(k=0;k<maxIts;k++){
            sa.x = (min+max)/2;
            val = (*delegate)(sa);
            //debug tool - remove later
            sa.toString();
            if (val >= .) {
              return(.);
            }
            if ((abs(val-target)<=approx)){
              return(sa.x)
            }
            if (val<target) {
              min = sa.x;
            } else {
              max = sa.x;
            }
        }
        return(.);
    }
    
    real scalar LbBeta(class searchArgs sa){
        return(ibetatail(sa.x+1,sa.n-sa.x, sa.p))
    }
     
    real scalar UbBeta(class searchArgs sa){
        return(1-ibetatail(sa.x,sa.n-sa.x+1, sa.p))
    }
    when calling the binary search algorithm with
    Code:
    sa = searchArgs()
    sa.n=242
    sa.p=0.0414434
    BinarySearch(0.02275, 0, sa.n, sa, &LbBeta())
    the output looks like
    Code:
    x:121,n:242,p:.0414434  1
    x:60.5,n:121,p:.0414434  1
    x:30.25,n:60.5,p:.0414434  1
    x:15.125,n:30.25,p:.0414434  1
    Note that the value of sa.n is the value of sa.x in the previous iteration - that is "max = sa.x" is also assigning the value to sa.n, because that is the value passed as the max argument.

    Obviously I can get the function to give me the desired value by calling "BinarySearch(0.02275, 0, 242, sa, &LbBeta())", but generally I would like the scalar arguments passed to a function to remain untouched.

  • #2
    Mata passes all arguments by reference, an important design decision in a statistical language where we often pass around large amounts of data and copying would slow everything down. One way around this is to make a copy of the argument inside the function and work with that. This is a bit trickier in your case because the argument is a class, but it looks like in Mata sb = sa makes a copy of the values, not the reference, so you could do something like

    Code:
    real scalar BinarySearch( ..., class searchArgs scalar sb, ...) {
        ...
    class searchArgs scalar sa
        sa = sb
        ...
    }
    Alternatively, you could "unwrap" the class and call the function with x, n, p and inside the function make a copy of x and work with that.

    Comment


    • #3
      Thank you German, I will assign the function argument to a declared variable within the function itself.

      In regard to the class vs primitive data types, All languages I know of pass class instances and arrays by reference, it is simply the primitive data types often default to passed by value. As per the original post it is strange there is also the ability to pass and de-refrence pointers given this behavior as, combined with inbuilt vector/matrix handling, I cannot see many situations this might prove useful.

      Comment


      • #4
        I agree. Mata is unusual in passing everything by reference (even constants).I think Gauss was the opposite, passing everything by value (even vectors). I think the main use of pointers in Mata is to pass functions, which otherwise we couldn't do, and to build recursive structures such as linked lists.

        Comment

        Working...
        X