Task

Show one or more idiomatic ways of generating the Cartesian product of two arbitrary lists in your language.

Demonstrate that your function/method correctly returns:

{1, 2} × {3, 4} = {(1, 3), (1, 4), (2, 3), (2, 4)}
and, in contrast:

{3, 4} × {1, 2} = {(3, 1), (3, 2), (4, 1), (4, 2)}
Also demonstrate, using your function/method, that the product of an empty list with any other list is empty.

 {1, 2} × {} = {}
 {} × {1, 2} = {}
For extra credit, show or write a function returning the n-ary product of an arbitrary number of lists, each of arbitrary length. Your function might, for example, accept a single argument which is itself a list of lists, and return the n-ary product of those lists.

Use your n-ary Cartesian product function to show the following products:

 {1776, 1789} × {7, 12} × {4, 14, 23} × {0, 1}
 {1, 2, 3} × {30} × {500, 100}
 {1, 2, 3} × {} × {500, 100}


#define MAXLEN 64
 
type listitem                  ' An item of a list may be a number
    is_num as boolean       ' or another list, so I have to account
    union                      ' for both, implemented as a union.
        list as any ptr        ' FreeBASIC is twitchy about circularly
        num as uinteger        ' defined types, so one workaround is to
    end union                  ' use a generic pointer that I will cast
end type                       ' later.
 
type list
    length as uinteger              'simple, fixed storage length lists
    item(1 to MAXLEN) as listitem   'are good enough for this example
end type
 
sub print_list( list as list )
    print "{";
    if list.length = 0 then print "}"; : return
    for i as uinteger = 1 to list.length
        if list.item(i).is_num then
            print str(list.item(i).num);
        else     'recursively print sublist
            print_list( *cast(list ptr, list.item(i).list) )
        end if
    if i<list.length then print ", "; else print "}";   'handle comma
    next i                                              'gracefully
    return
end sub
 
function cartprod( A as list, B as list ) as list
    dim as uinteger i, j
    dim as list C
    dim as list ptr inner  'for brevity
    C.length = 0
    for i = 1 to A.length
        for j = 1 to B.length
            C.length += 1
            C.item(C.length).is_num = false   'each item of the new list is a list itself
            inner = allocate( sizeof(list) )     'make space for it
            C.item(C.length).list = inner
            inner->length = 2                    'each inner list contains two items
            inner->item(1) = A.item(i)           'one from the first list
            inner->item(2) = B.item(j)           'and one from the second
        next j
    next i
    return C
end function
 
dim as list EMPTY, A, B, R
EMPTY.length = 0
A.length = 2 
A.item(1).is_num = true : A.item(1).num = 1
A.item(2).is_num = true : A.item(2).num = 2
B.length = 2 
B.item(1).is_num = true : B.item(1).num = 3
B.item(2).is_num = true : B.item(2).num = 4
 
R = cartprod(A, B)
print_list(R) : print   'print_list does not supply a final newline
R = cartprod(B, A) : print_list(R) : print
R = cartprod(A, EMPTY) : print_list(R) : print
R = cartprod(EMPTY, A) : print_list(R) : print