Alternatively, if you prefer a linked structure:
// A cell is a basic variant type whose value can be either
// * An integer, or
// * A pair of cells
struct cell_t;
struct pair_t;
// Enum of cell type, currently INT or PAIR
typedef enum { INT, PAIR } cell_type;
// Definition of type cell and pair, which are pointers to the respective structs
typedef struct cell_t* cell;
typedef struct pair_t* pair;
// Definition of pair_t: two pointers to cell (first and second)
// For a list structure, the type of second should always be PAIR.
struct pair_t {
cell first;
cell second;
};
// Definition of cell_t: type + union value
struct cell_t {
cell_type type;
union {
int i;
pair p;
} value;
};
// Constructors
//////////////////////////////////////////////////////////////////////////////////
// Returns an integer cell
cell Int(int i);
// Returns a pair cell
cell Pair(cell a, cell b);
// Returns a empty pair, type: PAIR, value.p==NULL
cell Nil();
To understand how this can represent the "deep" lists, have a read of this Wikipedia entry list.
Now we can create the example lists:
// Empty list
cell empty = Nil();
// [2, 3]
cell sublist23 = Pair(Int(2),
Pair(Int(3), empty));
cell sublist11 = Pair(Int(1), Pair(Int(1), empty));
cell sublist1_11 = Pair(Int(1), sublist11);
// [1, [2, 3], 4]
cell list1 = Pair(Int(1),
Pair(sublist23,
Pair(Int(4), empty)));
cell list2 = Pair(sublist1_11, sublist1_11);