Announcement

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

  • Passing arguments to a function within another function

    Hello,

    Is there a simple way to pass an *arbitrary* number of arguments to a function called within another function?

    For example, I want to write a very silly function silly_f that takes a pointer to another function and the arguments (an arbitrary number) that are to be passed to that other function.

    All silly_f does is to execute the other function. The thing is, I don't know it in advance how many arguments the other function takes.

    (For the R users out there, I'm thinking of something similar to R's ...)

    I'd like to do something along these lines (warning: illegal Mata code ahead!)

    Code:
    mata
    
    real scalar myf(real scalar a, real scalar b) {
    c = a + b
    return(c)
    }
    
    real scalar myf2(real scalar a, real scalar b, real scalar c) {
    d = a + b + c
    return(d)
    }
    
    real scalar silly_f(ponter scalar f, ...) {
        (*f)(...)
    }
    
    silly_f(&myf(), 2, 4)
    silly_f(&myf2(), 2, 4, 5)
    
    end

  • #2
    Have you seen Bill Gould's old post on this subject? Or Ben Jann's implementation of a Mata function for it?

    Comment


    • #3
      Thank you Joseph, that's exactly what I was looking for.

      (I can't help but notice the difference in complexity between Mata and R in doing this. Is Mata's way to approach this issue somehow "better" than R's, although more cumbersome?).

      Comment


      • #4
        To be honest with you, if it were me, I would pass a Mata pointer vector and run down the (variable) length of the vector, picking off what I wanted, dereferencing the elements as I go.

        Depending upon my mood and the problem at hand, I would also consider passing an object array or an object wrapper (carrier) for a Mata associative array.

        I would also consider passing a Mata struct, if the problem seems amenable to that approach.

        Regardless, I wouldn't mess around trying to figure out how many optional arguments the function currently was given, or arbitrarily limiting the maximum number of arguments to 10 or whatever.

        Comment


        • #5
          Thank you again, Joseph.

          One last question, if you have time: could you expand a little on your first solution (pointer vector)? Do you mean to pass silly_f() a vector of pointers to the function I want to call inside silly_f() and to its arguments?

          Comment


          • #6
            Originally posted by Andrea Discacciati View Post
            Do you mean to pass silly_f() a vector of pointers to the function I want to call inside silly_f() and to its arguments?
            I wasn't thinking of that, but rather of passing through the pointer vector containing arguments to the function that you want silly_f() to evaluate. silly_f() would know absolutely nothing about what arguments the function-to-be-evaluated needs (if any: the pointer vector could be all NULLs if a particular function-to-be-evaluated doesn't need any arguments). The pointer vector approach is pretty general, allowing passing through everything from real scalars to string arrays, even functions, in case the function-to-be-evaluated needs to call another function that isn't in a Mata library in the ado path.

            In your example, the function just needs real scalars, and so you wouldn't need to go that far; you could just use a real vector of variable length that would be passed through. You would need to design your system so that the functions-to-be-evaluated take their arguments as a real vector instead of multiple real scalars. If you wanted to name the individual scalars and if they're in some kind of consistent arrangement (you have a, b, c, . . .), then you could work something out with a struct that contains a fixed number of real scalars, named appropriately, and pass that after the struct's component real scalars are populated with values needed by the particular function-to-be-evaluated.

            For an alternative in your situation, in lieu of the pointer vector approach, consider designing a Mata class that contains the function-to-be-evaluated as a public member method. At run time, first compose the object with one or more other objects that contain all of the arguments that the function needs, and then pass the object, complete, to the evaluator as the sole argument to it. For different functions-to-be-evaluated you can subclass, with the function-to-be-evaluated as a virtual member method in the parent class. Again, the evaluator doesn't know anything about the function-to-be-evaluated or its arguments. All it knows is that it has been passed an object of the type, and to call a method on it named, say, evaluateMe(). Everything else is transparent to it.

            Comment


            • #7
              Originally posted by Joseph Coveney View Post
              in case the function-to-be-evaluated needs to call another function that isn't in a Mata library in the ado path
              Sorry for the lapse. I meant in case you wanted to variably specify a function for the function-to-be-evaluated to use.

              Comment


              • #8
                Thank you very much Joseph, I see what you mean now.

                Comment

                Working...
                X