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.
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
- 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.
- 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
- 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!
Your Answer
4 Answers
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.
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:)
- 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.
- 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
- 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.
Thanks for the answer!