Bookmark and Share

Notice: On April 23, 2014, Statalist moved from an email list to a forum, based at statalist.org.


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: st: Capture break in mata


From   James Fiedler <jrfiedler@gmail.com>
To   statalist@hsphsun2.harvard.edu
Subject   Re: st: Capture break in mata
Date   Tue, 1 Oct 2013 15:00:58 -0500

Hi,

The question about a Mata capture has come up at least one other time
on Statalist, in the thread starting with
http://www.stata.com/statalist/archive/2006-04/msg00739.html

At that time (April 2006) the answer was that there is nothing quite
like capture in Mata. People with more experience than me might also
say that capturing is not the Mata way to do things. And, probably,
someone might be along soon to show a better way to do this without
capturing.

However, I think there are times when capturing makes sense (for
example, if testing that a function returns an error when you expect
it to). So, I have written a capture function in Mata that works kinda
like Stata's -capture-. I don't know if this will give you exactly
what you want, but maybe this can be used together with an external
variable or a class attribute.

The definition of capture() is below. First, an example (make sure
break button works before using)

//---- begin Mata capture example ----

// Start in Stata (Ado) mode

run capture.mata  // to define capture()

mata

void while_func()
{
    while (1) {
        printf("blah ")
    }
}

rc = capture(&while_func(), J(0,0,.))
[this will loop until you press the beak button]
rc

//---- end Mata capture example ----

capture() takes
1st argument:  a function pointer
2nd argument: a vector of pointers to the function's arguments, or an
empty matrix if no args
3rd argument, optional: pointer to an initialized variable to hold the
function's return value, if needed

Now, the file capture.mata

//--- begin capture.mata ----
mata
    class Capture {
        pointer(function) scalar func_ptr
        pointer matrix arg_ptrs
        pointer scalar rv_ptr
    }

    capture = Capture()

    real scalar capture(pointer(function) scalar func_ptr,
                        pointer matrix arg_ptrs,
                        | pointer scalar rv_ptr)
    {
        real scalar rc, i, nargs
        string scalar run_str, arg_template
        external class Capture scalar capture

        // Check dimensions of arg_ptrs. It is allowed to be a vector, or
        // a zero-dimensional matrix if wanting to pass zero arguments.
        // I.e., J(0,0,.), J(0,1,.) J(123,0,.) are all allowed.
        if (rows(arg_ptrs) > 1 & cols(arg_ptrs) > 1) {
            exit(_error(3200, "arg pointers must be vector or zero-dim matrix"))
        }

        capture.func_ptr = func_ptr
        capture.arg_ptrs = arg_ptrs

        if (args() == 3) {
            capture.rv_ptr = rv_ptr
            run_str = "capture mata: *(capture.rv_ptr) = (*capture.func_ptr)("
        }
        else {
            run_str = "capture mata: (*capture.func_ptr)("
        }
        arg_template = "*(capture.arg_ptrs[%f])%s"

        nargs = length(arg_ptrs)
        for (i = 1; i <= nargs; i++) {
            run_str = run_str + sprintf(arg_template, i, i == nargs ? "" : ",")
        }
        run_str = run_str + ")"

        stata(run_str)
        stata("local rc = _rc")
        rc = strtoreal(st_local("rc"))

        return(rc)
    }
end
//---- end capture.mata ----


I've tested this code out, but I'm not quite 100% sure everything
works the way it should.


James

On Tue, Oct 1, 2013 at 1:48 PM, George Vega Yon <g.vegayon@gmail.com> wrote:
> Dear Stata listers,
>
> I've been reading Mata's documentation and I cannot find a way to
> simply of working with -capture- block of code. I know that in Stata
> one can create -capture- blocks such as
>
> capture {
>     ...code...
> }
>
> if (_rc) {
>     ...code....
> }
>
> But I haven't seen something like that in Mata. What I'm actually
> looking for is to, from within Mata, run a -while- loop and, if the
> break key is pressed, do something.
>
> Checking functions -setbreakintr()-, -resetbreakkey()- and
> -breakkey()- I know that I can suppress the break key from
> interrupting the program, but as I change its behavior the
> -breakkey()- function doesn't captures if the break key has been
> pressed (which is what I understand from the Diagnostics section in
> the help file).
>
> I've tried coding somethign like this
>
> mata:
> mata clear
> real scalar myfun() {
>
>     /* Definitions */
>     real scalar i, j, bk;
>     real scalar x;
>
>     /* Setting breakkey interrupt off */
>     bk=setbreakintr(0);
>     i=1;
>     while(!breakkey() & i   < 1e4)
>         for(j=1;j<=1000;j  ) x=i;
>
>     /* Restoring breakkey and its mode */
>     breakkeyreset();
>     (void) setbreakintr(bk);
>
>     return(x);
> }
>
> myfun();
>
> end
>
> For which, once running, I press the key Break, hoping that the while
> loop stops, the x value stores the last -i- used and the breakkey
> behavior restores; and what I get this message: "Break disallowed at
> this time", and the program continues and returns 1e4 (what means that
> it stayed in the loop until i=1e4, i.e. the breakkey() value never
> changed from 0).
>
> I know that -setbreakintr(0)- is intended to be used in the same way
> that Stata's -nobreak- blocks, but is there any way that I can work
> this out using solely Mata?
>
> Thank you and excuse for any nonsense that I'm probably saying.
>
> Best regards,
>
> George Vega Yon
> 7 647 2552
> http://cl.linkedin.com/in/georgevegayon
> *
> *   For searches and help try:
> *   http://www.stata.com/help.cgi?search
> *   http://www.stata.com/support/faqs/resources/statalist-faq/
> *   http://www.ats.ucla.edu/stat/stata/
*
*   For searches and help try:
*   http://www.stata.com/help.cgi?search
*   http://www.stata.com/support/faqs/resources/statalist-faq/
*   http://www.ats.ucla.edu/stat/stata/


© Copyright 1996–2018 StataCorp LLC   |   Terms of use   |   Privacy   |   Contact us   |   Site index