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}


iterator product[T1, T2](a: openArray[T1]; b: openArray[T2]): tuple[a: T1, b: T2] =
  # Yield the element of the cartesian product of "a" and "b".
  # Yield tuples rather than arrays as it allows T1 and T2 to be different.
 
  for x in a:
    for y in b:
      yield (x, y)
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
when isMainModule:
 
  from seqUtils import toSeq
  import strformat
  from strutils import addSep
 
  #-------------------------------------------------------------------------------------------------
 
  proc `$`[T1, T2](t: tuple[a: T1, b: T2]): string =
    ## Overloading of `$` to display a tuple without the field names.
    &"({t.a}, {t.b})"
 
  proc `$$`[T](s: seq[T]): string =
    ## New operator to display a sequence using mathematical set notation.
    result = "{"
    for item in s:
      result.addSep(", ", 1)
      result.add($item)
    result.add('}')
 
#-------------------------------------------------------------------------------------------------
 
  const Empty = newSeq[int]()   # Empty list of "int".
 
  for (a, b) in [(@[1, 2], @[3, 4]),
                 (@[3, 4], @[1, 2]),
                 (@[1, 2],  Empty ),
                 ( Empty,  @[1, 2])]:
 
    echo &"{$$a} x {$$b} = {$$toSeq(product(a, b))}"