multiple values in a return from function
Author Message
multiple values in a return from function

I'm not sure what I'm doing wrong here.  I wanted to return two values from
a function that computes solar positions--the right ascension and
declination of the sun.  Both are <floats>.  When I tried interactively
testing this function, it would only return 1 value.  I must be missing
something simple, but I don't get it.   If I change the function to return
an object that contains a right ascension slot and a declination slot, it
works fine.  If I return a list of the right ascension and declination, it
works too.

What Dylan concept do I need to bone up on?

I've included the source for illustration:

**** This one works when tested interactively ****
define method compute-solar-position( epoch-day :: <integer> ) =>
( results :: <astro-position>)

// Now pre-compute the important values based on epoch day
ecliptic-obliquity := 23.4393 - 3.563e-7 * epoch-day;
solar-eccentricity := 0.016709 - 1.151E-9 * epoch-day;
solar-mean-anomaly := 356.0470 + 0.9856002585 * epoch-day;
solar-arg-perihelion := 282.9404 + 4.70935E-5 * epoch-day;

// compute eccentric anomaly in radians
let eccentric-anomaly = solar-mean-anomaly +  (solar-eccentricity  *
sin( solar-mean-anomaly ) *
( 1.0 + solar-eccentricity *
os( solar-mean-anomaly )));
// compute x and y component of true anomaly position
let x-true-anom       = cos( eccentric-anomaly ) - solar-eccentricity;
let y-true-anom       = sqrt( 1.0 - solar-eccentricity ^ 2 ) *
in( eccentric-anomaly );

let true-anomaly = atan2( y-true-anom , x-true-anom );

// assume this is in AU?
let solar-distance = sqrt( x-true-anom ^ 2  + y-true-anom ^ 2);

// compute solar true longitude
let solar-true-long = true-anomaly + solar-arg-perihelion;

// compute solar ecliptic rectangular coordinates
let x-sun = solar-distance * cos( solar-true-long );
let y-sun = solar-distance * sin( solar-true-long );

// now convert these to equatorial, rectangular coordinates
let eq-x-sun = x-sun;
let eq-y-sun = y-sun * cos( ecliptic-obliquity );
let eq-z-sun = y-sun * sin( ecliptic-obliquity );

let suns-pos = make( <astro-position> );
// Finally, compute right ascension and declination
suns-pos.right-ascension := atan2( eq-y-sun, eq-x-sun );
suns-pos.declination     := atan2( eq-z-sun, sqrt( eq-x-sun ^ 2  +
eq-y-sun ^ 2));
suns-pos;

end method;

**** This one doesn't ****

define method compute-solar-position( epoch-day :: <integer> ) =>
( results :: false-or( <astro-position>))

// Now pre-compute the important values based on epoch day
ecliptic-obliquity := 23.4393 - 3.563e-7 * epoch-day;
solar-eccentricity := 0.016709 - 1.151E-9 * epoch-day;
solar-mean-anomaly := 356.0470 + 0.9856002585 * epoch-day;
solar-arg-perihelion := 282.9404 + 4.70935E-5 * epoch-day;

// compute eccentric anomaly in radians
let eccentric-anomaly = solar-mean-anomaly +  (solar-eccentricity  *
sin( solar-mean-anomaly ) *
( 1.0 + solar-eccentricity *
os( solar-mean-anomaly )));
// compute x and y component of true anomaly position
let x-true-anom       = cos( eccentric-anomaly ) - solar-eccentricity;
let y-true-anom       = sqrt( 1.0 - solar-eccentricity ^ 2 ) *
in( eccentric-anomaly );

let true-anomaly = atan2( y-true-anom , x-true-anom );

// assume this is in AU?
let solar-distance = sqrt( x-true-anom ^ 2  + y-true-anom ^ 2);

// compute solar true longitude
let solar-true-long = true-anomaly + solar-arg-perihelion;

// compute solar ecliptic rectangular coordinates
let x-sun = solar-distance * cos( solar-true-long );
let y-sun = solar-distance * sin( solar-true-long );

// now convert these to equatorial, rectangular coordinates
let eq-x-sun = x-sun;
let eq-y-sun = y-sun * cos( ecliptic-obliquity );
let eq-z-sun = y-sun * sin( ecliptic-obliquity );

// Finally, compute right ascension and declination
let right-ascension = atan2( eq-y-sun, eq-x-sun );
let declination       = atan2( eq-z-sun, sqrt( eq-x-sun ^ 2  + eq-y-sun ^
2));

values( right-ascension, declination );
end method;

Tue, 30 Jul 2002 03:00:00 GMT
multiple values in a return from function

Quote:
>I'm not sure what I'm doing wrong here.  I wanted to return two values from
>a function that computes solar positions--the right ascension and
>declination of the sun.  Both are <floats>.  When I tried interactively
>testing this function, it would only return 1 value.  I must be missing
>something simple, but I don't get it.   If I change the function to return
>an object that contains a right ascension slot and a declination slot, it
>works fine.  If I return a list of the right ascension and declination, it
>works too.
>What Dylan concept do I need to bone up on?

The problem is that you have defined compute-solar-position to return only
one value (i.e., => (results :: <astro-position>) ).  Dylan (unlike CL)
will discard extra values if less values are defined than are actually
returned (and pad values with falses if more are defined than are actually
returned).  You can use #rest in the values specification if you want a
varying number of return values (e.g., => (#rest results ::
<astro-position>) ).

Jonathan Bachrach
President, Functional Objects, Inc.

Quote:
>I've included the source for illustration:

>   **** This one works when tested interactively ****
>define method compute-solar-position( epoch-day :: <integer> ) =>
>   ( results :: <astro-position>)

>    // Now pre-compute the important values based on epoch day
>    ecliptic-obliquity := 23.4393 - 3.563e-7 * epoch-day;
>    solar-eccentricity := 0.016709 - 1.151E-9 * epoch-day;
>    solar-mean-anomaly := 356.0470 + 0.9856002585 * epoch-day;
>    solar-arg-perihelion := 282.9404 + 4.70935E-5 * epoch-day;

>   // compute eccentric anomaly in radians
>   let eccentric-anomaly = solar-mean-anomaly +  (solar-eccentricity  *
>                                            sin( solar-mean-anomaly ) *
>                                            ( 1.0 + solar-eccentricity *
>os( solar-mean-anomaly )));
>   // compute x and y component of true anomaly position
>   let x-true-anom       = cos( eccentric-anomaly ) - solar-eccentricity;
>   let y-true-anom       = sqrt( 1.0 - solar-eccentricity ^ 2 ) *
>in( eccentric-anomaly );

>   let true-anomaly = atan2( y-true-anom , x-true-anom );

>   // assume this is in AU?
>   let solar-distance = sqrt( x-true-anom ^ 2  + y-true-anom ^ 2);

>   // compute solar true longitude
>   let solar-true-long = true-anomaly + solar-arg-perihelion;

>    // compute solar ecliptic rectangular coordinates
>   let x-sun = solar-distance * cos( solar-true-long );
>   let y-sun = solar-distance * sin( solar-true-long );

>   // now convert these to equatorial, rectangular coordinates
>   let eq-x-sun = x-sun;
>   let eq-y-sun = y-sun * cos( ecliptic-obliquity );
>   let eq-z-sun = y-sun * sin( ecliptic-obliquity );

>   let suns-pos = make( <astro-position> );
>   // Finally, compute right ascension and declination
>   suns-pos.right-ascension := atan2( eq-y-sun, eq-x-sun );
>   suns-pos.declination     := atan2( eq-z-sun, sqrt( eq-x-sun ^ 2  +
>eq-y-sun ^ 2));
>   suns-pos;

>end method;

>   **** This one doesn't ****

>define method compute-solar-position( epoch-day :: <integer> ) =>
>   ( results :: false-or( <astro-position>))

>    // Now pre-compute the important values based on epoch day
>    ecliptic-obliquity := 23.4393 - 3.563e-7 * epoch-day;
>    solar-eccentricity := 0.016709 - 1.151E-9 * epoch-day;
>    solar-mean-anomaly := 356.0470 + 0.9856002585 * epoch-day;
>    solar-arg-perihelion := 282.9404 + 4.70935E-5 * epoch-day;

>   // compute eccentric anomaly in radians
>   let eccentric-anomaly = solar-mean-anomaly +  (solar-eccentricity  *
>                                            sin( solar-mean-anomaly ) *
>                                            ( 1.0 + solar-eccentricity *
>os( solar-mean-anomaly )));
>   // compute x and y component of true anomaly position
>   let x-true-anom       = cos( eccentric-anomaly ) - solar-eccentricity;
>   let y-true-anom       = sqrt( 1.0 - solar-eccentricity ^ 2 ) *
>in( eccentric-anomaly );

>   let true-anomaly = atan2( y-true-anom , x-true-anom );

>   // assume this is in AU?
>   let solar-distance = sqrt( x-true-anom ^ 2  + y-true-anom ^ 2);

>   // compute solar true longitude
>   let solar-true-long = true-anomaly + solar-arg-perihelion;

>    // compute solar ecliptic rectangular coordinates
>   let x-sun = solar-distance * cos( solar-true-long );
>   let y-sun = solar-distance * sin( solar-true-long );

>   // now convert these to equatorial, rectangular coordinates
>   let eq-x-sun = x-sun;
>   let eq-y-sun = y-sun * cos( ecliptic-obliquity );
>   let eq-z-sun = y-sun * sin( ecliptic-obliquity );

>   // Finally, compute right ascension and declination
>   let right-ascension = atan2( eq-y-sun, eq-x-sun );
>   let declination       = atan2( eq-z-sun, sqrt( eq-x-sun ^ 2  + eq-y-sun ^
>2));

>    values( right-ascension, declination );
>end method;

Tue, 30 Jul 2002 03:00:00 GMT
multiple values in a return from function

Quote:

> I'm not sure what I'm doing wrong here.  I wanted to return two values from
> a function that computes solar positions--the right ascension and
> declination of the sun.  Both are <floats>.  When I tried interactively
> testing this function, it would only return 1 value.

It should work fine, but you don't show how you're testing it.

[interpreter thread starting.]
Marlais 0.5.11
? define method sincos(a)

Quote:
>  values(sin(a), cos(a))
> end;

==> sincos
? define variable (x, y) = sincos(3.141592654/6);;
? x;
==> 0.500000
? y;
==> 0.866025
?

Note that the *only* ways to make use of multiple return values are to
assign them to variables using either "define variable (foo, bar, baz) = "
or else "let (foo, bar, baz) = ".  Any other method of using the function
return will ignore all but the first value.

-- Bruce

Tue, 30 Jul 2002 03:00:00 GMT
multiple values in a return from function

Quote:

> define method compute-solar-position( epoch-day :: <integer> ) =>
>   ( results :: false-or( <astro-position>))
[...snip...]

>    values( right-ascension, declination );
> end method;

It's possibly because you are declaring the return result as being a
single value (of type false or instance of class <astro-position>),
whereas you are actually returning two values. The compiler will be
ignoring the second value.

Try it with just (ie. no return value declared):

Quote:
> define method compute-solar-position( epoch-day :: <integer> )
[...snip...]
>    values( right-ascension, declination );
> end method;

Chris.
--
http://www.double.co.nz/dylan

Tue, 30 Jul 2002 03:00:00 GMT

 Page 1 of 1 [ 4 post ]

Relevant Pages

Powered by phpBB® Forum Software