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}


/*REXX program  calculates  the   Cartesian product   of two  arbitrary-sized  lists.   */
@.=                                              /*assign the default value to  @. array*/
parse arg @.1                                    /*obtain the optional value of  @.1    */
if @.1=''  then do;  @.1= "{1,2} {3,4}"          /*Not specified?  Then use the defaults*/
                     @.2= "{3,4} {1,2}"          /* "      "         "   "   "      "   */
                     @.3= "{1,2} {}"             /* "      "         "   "   "      "   */
                     @.4= "{}    {3,4}"          /* "      "         "   "   "      "   */
                     @.5= "{1,2} {3,4,5}"        /* "      "         "   "   "      "   */
                end
                                                 /* [↓]  process each of the  @.n values*/
  do n=1  while @.n \= ''                        /*keep processing while there's a value*/
  z= translate( space( @.n, 0),  ,  ',')         /*translate the  commas  to blanks.    */
     do #=1  until z==''                         /*process each elements in first list. */
     parse var  z   '{'  x.#  '}'   z            /*parse the list  (contains elements). */
     end   /*#*/
  $=
     do       i=1   for #-1                      /*process the subsequent lists.        */
       do     a=1   for words(x.i)               /*obtain the elements of the first list*/
         do   j=i+1 for #-1                      /*   "    "  subsequent lists.         */
           do b=1   for words(x.j)               /*   "    " elements of subsequent list*/
           $=$',('word(x.i, a)","word(x.j, b)')' /*append partial Cartesian product ──►$*/
           end   /*b*/
         end     /*j*/
       end       /*a*/
     end         /*i*/
  say 'Cartesian product of '       space(@.n)       " is ───► {"substr($, 2)'}'
  end            /*n*/                           /*stick a fork in it,  we're all done. */