Matthew Weinberg <[email protected]> writes,
> I'm trying to use structures for the first time and am having a little
> trouble. I want the function markups to take three arguments (s,p,b)
> and return three arguments (margins, marks, and costs). I'm getting
> back one
>
> My code is:
>
> struct mups { /*define the structure*/
> real matrix margins
> real matrix marks
> real matrix costs
> }
>
> struct mups function markups(s,p,b) /*define the function*/
> {
> struct mups scalar ms /*declare structure variable*/
> n=rows(s)
> S=J(n,n,0)
> for(i=1;i<=n;i++){
> for(j=1;j<=n;j++){
> S[i,j]=-b*s[i]*s[j]
> }
> }
> for(i=1;i<=n;i++){
> S[i,i]=-b*s[i]*s[i]+b*s[i]
> }
> Omega=I(n)*S
> ms.margins=invsym(Omega)*s
> ms.costs=p-ms.margins
> ms.marks=(p-ms.costs):/p
> return(ms)
> }
>
> When I evaluate my function, I get back what something like 0x27c65c
> instead of the three vectors margins, costs, and marks.
Everything is working as it should. The result 0x27c65c is the address
of the structure. That's what you see when you use a structure interactively,
such as
: markups(..., ..., ...)
0x27c65c /* you might see a different address */
However, in a programming context, they work as you might expect. Try the
following program with the above,
void listresult(struct mups scalar ms)
{
"margins is"
ms.margins
"marks is"
ms.marks
"costs is"
ms.cost
}
With that extra program, you could interactively type
: listresult(markups(..., ..., ...))
margins is
<matrix listed here>
marks is
<matrix listed here>
costs is
<matrix listed here>
More usefully, you might have another program that reads
void mainroutine(...)
{
struct mups scalar m
...
m = markups(..., ..., ...)
...
a = <calculation made with m.margins, m.marks, and m.costs>
...
printf("The final result is %9.2f\n", a)
}
or
void anotherroutine(...)
{
struct mups scalar m1, m2
...
m1 = markups(..., ..., ...)
m2 = markups(..., ..., ...)
...
a = <calculation made with m1.margins, m1.marks, and m2.costs
and m2.margins, m2.marks, and m2.costs>
...
printf("The final result is %9.2f\n", a)
}
or
void lastexample(...)
{
struct mups scalar m1, m2
...
m1 = markups(..., ..., ...)
m2 = markups(..., ..., ...)
...
a = perform_basic_calc(m1)
b = perform_basic_calc(m2)
...
printf("The final result is %9.2f\n", a+b)
}
real scalar perform_basic_calc(struct mps scalar m)
{
result = <calculation made with m.margins, m.marks, and m.costs>
return(result)
}
So what is 0x27c65c? In the above examples, markups() returned a structure,
not some hexadecimal number, and we just used what markups() returned as the
structure it is.
This is difficult to explain, so bear with me.
1. A structure is, internally, a "pointer" to a memory address.
That memory address contains the values of the elements of the
structure.
2. You are not required to know (1) or even understand what (1)
means; it is a detail of the implementation of Mata.
3. In the programs above, I used variables such as ms, m, m1, and m2
to hold the structures returned by markup(). Note that, in each
case, I explicitly declared ms, m, m1, and m2 to be struct mups.
4. Because I did that, Mata knew ms, m, m1, and m2 were struct mups,
and because it knew that, given the structure definition, Mata
knew (for instance) m.margins referred to the first element of the
structure, m.marks referred to the second, and m.costs referred to
the third. Mata also knew that, had I coded m.bill, that would be
a mistake because there is no element of the structure mups called
bill.
5. Now consider a line such as
: x = markups(..., ..., ...)
Note, I typed the line interactively. Well, you say to yourself,
then I suspect is can similarliy refer to x.margins, x.marks,
and m.costs. But you cannot because you did not previously declare
x to be a struct mups. x is just a transmorphic and, as such,
it can hold a structure such as a struct mups, but Mata doesn't
understand that it really is a structure. Said differently, Mata
understands that x is a structure of some sort, but it doesn't know
that it is in particular a struct mups, and so Mata does not know
how to translate things like x.margins, x.marks, and x.costs into
1st element, 2nd element, and 3rd element. For all Mata knows,
the translation might be 2nd element, 1st element, and 3rd element,
or x.marks might simply be an error and correspond to no element.
6. So what happens if you look at x interacctively? Mata just gives
up and shows you the memory address of the structure.
7. If the above makes no sense, I apologize. The short answer is
(1) structures work as you would expect INSIDE Mata programs and
(2) structures were never intended to work interactively, so
don't use them that way.
One more aside. Concerning notes 5 and 6, while structures cannot be
interpreted interactively, transmorphics can be used to hold the contents
of a structure. For instance, I might interactively type
: x = markup(.., ..., ...)
: listresult(x)
and that will work! x contains the structure, it is just that Mata
can't work out the details of the INTERPRETATION based on what is stored
in x. I've mentioned this before: Mata is a compiler, and being a
compiler is what makes Mata fast.
-- Bill
[email protected]
*
* For searches and help try:
* http://www.stata.com/support/faqs/res/findit.html
* http://www.stata.com/support/statalist/faq
* http://www.ats.ucla.edu/stat/stata/