Step 3: Structs¶
In this step, you'll learn to group related values into struct types.
Struct Types¶
When a calculation produces multiple related values, group them into a
struct. In graphcal every type is an n-variant tagged union — a
struct is just a single-variant union whose sole constructor's name
matches the type's name:
dim Velocity = Length / Time;
dim GravParam = Length^3 / Time^2;
type TransferResult {
TransferResult(dv1: Velocity, dv2: Velocity, total_dv: Velocity, tof: Time),
}
Constructing a Struct¶
Build a struct value by calling its constructor:
node result: TransferResult = TransferResult(
dv1: 100.0 m/s,
dv2: 200.0 m/s,
total_dv: 300.0 m/s,
tof: 3600.0 s,
);
Graph node fields are passed with explicit @ references:
node dv1: Velocity = 100.0 m/s;
node dv2: Velocity = 200.0 m/s;
node total_dv: Velocity = @dv1 + @dv2;
node result: TransferResult = TransferResult(
dv1: @dv1,
dv2: @dv2,
total_dv: @total_dv,
tof: 3600.0 s,
);
Field shorthand is reserved for local variables (such as for/match
bindings) with the same name as the field.
Field Access¶
Access struct fields with the . operator:
Putting It Together: Hohmann Transfer¶
A Hohmann transfer between two coplanar circular orbits naturally
produces several related values. Express each intermediate as its own
node, then group the outputs into a TransferResult:
dim Velocity = Length / Time;
dim GravParam = Length^3 / Time^2;
type TransferResult {
TransferResult(dv1: Velocity, dv2: Velocity, total_dv: Velocity, tof: Time),
}
const node r_earth: Length = 6371.0 km;
const node gm_earth: GravParam = 3.986004418e5 km^3/s^2;
param parking_alt: Length = 200.0 km;
param target_alt: Length = 35786.0 km;
node r1: Length = @r_earth + @parking_alt;
node r2: Length = @r_earth + @target_alt;
node a: Length = (@r1 + @r2) / 2.0;
node v1: Velocity = sqrt(@gm_earth / @r1);
node v2: Velocity = sqrt(@gm_earth / @r2);
node dv1: Velocity = sqrt(2.0 * @gm_earth * @r2 / (@r1 * (@r1 + @r2))) - @v1;
node dv2: Velocity = @v2 - sqrt(2.0 * @gm_earth * @r1 / (@r2 * (@r1 + @r2)));
node transfer: TransferResult = TransferResult(
dv1: @dv1,
dv2: @dv2,
total_dv: @dv1 + @dv2,
tof: PI * sqrt(@a ^ 3.0 / @gm_earth),
);
node total_dv: Velocity = @transfer.total_dv;
node tof_hours: Time = @transfer.tof -> hour;
Every intermediate is a first-class node in the DAG. That makes them
visible in the LSP outline and in graphcal eval output, which is part
of why Graphcal exposes intermediates rather than hiding them inside a
local block.
In Step 4, you'll learn how to package a chunk of
this graph into a reusable, parameterized dag block.
What You Learned¶
typedeclarations as n-variant tagged unions (single-variant for record-shaped data)- Struct construction with the constructor-call form
TypeName(field: value, ...) - Field access with
.on values of single-variant unions