Passing procedures to procedures

I want to pass a procedure to another procedure. I checked the User guide and it doesn't seem too difficult. For example,

proc myproc(&f, x, a, b);
local f:proc;
retp(f(x, a, b));
endp;

where f is an arbitrary procedure/function.

This is fine, but I want something a little different. Assume that if f is a linear function, I don't need the procedure/function f because it's easier to do it in myproc and the body of myproc also changes. In other words, I only need f if it's not linear. Something like this:

proc myproc(&f, x, a, b, ind);
local f:proc, z;
if ind eq 1;
z = a*x+b;
else;
z=f(x,a,b);
endif;
retp(z);
endp;

How can I do this? Can I just pass an empty argument in myproc such as myproc({}, x, a, b, ind)? Or do I have to define f anyway?

I know, I could write a simple f function for the linear specification, but the point is that if f is linear, then the procedure myproc is different. This is why I define the indicator variable ind. Is there a way to do this?

4 Answers



1



accepted

You do not have to define your procedure pointer f to point to a procedure. If the procedure pointer is not referenced, you can pass in any placeholder. However, you cannot define an empty matrix in a procedure call like this: myproc({}, x, a, b, ind).

Here is one way to do it:

b = 1.5;
x = 2;
a = rndn(100, 1).^2;

z = myproc(&logAproc, x, a, b, 0);
z = myproc("NULL", x, a, b, 1);


proc myproc(&f, x, a, b, ind);
    local f:proc, z;
    if ind eq 1;
        z = a*x+b;
    else;
        z=f(x,a,b);
    endif;
    retp(z);
endp;

proc (1) = logAproc(x, a, b);
    local z;
    z = a * ln(x) + b;
    retp(z);
endp;

There is nothing special about the string "NULL". You could replace "NULL" with a scalar 0 or a scalar error code. The code will even work if you replace "NULL" with an integer value. I would not recommend that, however, since procedure pointers are scalar integer pointers that provide the location of the procedure they point at. If you made a mistake in the code, you could end up with a much more confusing bug that way.

Since GAUSS does not treat the procedure pointer as a procedure pointer until after local f:proc, you could use the procedure pointer value as the indicator instead of ind. Below I use "NULL" as the indicator to perform the linear calculation, but you could also use a scalar 0 or a scalar error code as well.

b = 1.5;
x = 2;
a = rndn(100, 1).^2;

z = myproc(&logAproc, x, a, b);
z = myproc("NULL", x, a, b);


proc myproc(&f, x, a, b);
    local z;
    if f == "NULL";
        z = a*x+b;
    else;
        local f:proc;
        z=f(x,a,b);
    endif;
    retp(z);
endp;

proc (1) = logAproc(x, a, b);
    local z;
    z = a * ln(x) + b;
    retp(z);
endp;

While this is maybe a little more concise, there is no real significant advantage. I would recommend you choose the solution that seems most clear to you.

aptech

1,773


0



Great answer, thanks!

I like more your second solution, it seems more elegant and parsimonious.

Just one quick question. In the second version you write:

if f "NULL";

Should it not be this?

if f eq "NULL";

If I use, say, a scalar zero instead of the string, I assume it should be

if f eq 0;

Is this correct?

A final question, unrelated to this. How do you create these nice codes with indentations, colours, etc? I can't find these features in the forum editor, but perhaps you have a more fancy version:)



0



  1. Your are correct. I made a mistake. It should read either if f eq "NULL" or if f == "NULL". I corrected the earlier post for future reference.
  2. Yes, if you want to use a scalar zero instead of "NULL, then you would change if f eq "NULL" to if f eq 0
  3. If you surround code snippets with pre tags like this:
    <pre>
    //insert code here
    </pre>
    

    then your code will be: inside the light grey box, printed with a monospace font and any indentation will be preserved. As to color: for now you have to use span tags with one of the following clases: gkeyword, gcomment or gstring. Adding something like Markdown to do this portion automatically is on our backlog, but I do not have an estimate of when it will be completed.

aptech

1,773


0



Thanks for the answer!

Your Answer

4 Answers

1
accepted

You do not have to define your procedure pointer f to point to a procedure. If the procedure pointer is not referenced, you can pass in any placeholder. However, you cannot define an empty matrix in a procedure call like this: myproc({}, x, a, b, ind).

Here is one way to do it:

b = 1.5;
x = 2;
a = rndn(100, 1).^2;

z = myproc(&logAproc, x, a, b, 0);
z = myproc("NULL", x, a, b, 1);


proc myproc(&f, x, a, b, ind);
    local f:proc, z;
    if ind eq 1;
        z = a*x+b;
    else;
        z=f(x,a,b);
    endif;
    retp(z);
endp;

proc (1) = logAproc(x, a, b);
    local z;
    z = a * ln(x) + b;
    retp(z);
endp;

There is nothing special about the string "NULL". You could replace "NULL" with a scalar 0 or a scalar error code. The code will even work if you replace "NULL" with an integer value. I would not recommend that, however, since procedure pointers are scalar integer pointers that provide the location of the procedure they point at. If you made a mistake in the code, you could end up with a much more confusing bug that way.

Since GAUSS does not treat the procedure pointer as a procedure pointer until after local f:proc, you could use the procedure pointer value as the indicator instead of ind. Below I use "NULL" as the indicator to perform the linear calculation, but you could also use a scalar 0 or a scalar error code as well.

b = 1.5;
x = 2;
a = rndn(100, 1).^2;

z = myproc(&logAproc, x, a, b);
z = myproc("NULL", x, a, b);


proc myproc(&f, x, a, b);
    local z;
    if f == "NULL";
        z = a*x+b;
    else;
        local f:proc;
        z=f(x,a,b);
    endif;
    retp(z);
endp;

proc (1) = logAproc(x, a, b);
    local z;
    z = a * ln(x) + b;
    retp(z);
endp;

While this is maybe a little more concise, there is no real significant advantage. I would recommend you choose the solution that seems most clear to you.

0

Great answer, thanks!

I like more your second solution, it seems more elegant and parsimonious.

Just one quick question. In the second version you write:

if f "NULL";

Should it not be this?

if f eq "NULL";

If I use, say, a scalar zero instead of the string, I assume it should be

if f eq 0;

Is this correct?

A final question, unrelated to this. How do you create these nice codes with indentations, colours, etc? I can't find these features in the forum editor, but perhaps you have a more fancy version:)

0
  1. Your are correct. I made a mistake. It should read either if f eq "NULL" or if f == "NULL". I corrected the earlier post for future reference.
  2. Yes, if you want to use a scalar zero instead of "NULL, then you would change if f eq "NULL" to if f eq 0
  3. If you surround code snippets with pre tags like this:
    <pre>
    //insert code here
    </pre>
    

    then your code will be: inside the light grey box, printed with a monospace font and any indentation will be preserved. As to color: for now you have to use span tags with one of the following clases: gkeyword, gcomment or gstring. Adding something like Markdown to do this portion automatically is on our backlog, but I do not have an estimate of when it will be completed.

0

Thanks for the answer!


You must login to post answers.

Have a Specific Question?

Get a real answer from a real person

Need Support?

Get help from our friendly experts.