Search code examples
pythoncrecursionnestedcode-translation

Is there an equivalent to a nested recursive function in C?


First of all, I know that nested functions are not supported by the C standard.

However, it's often very useful, in other languages, to define an auxiliary recursive function that will make use of data provided by the outer function.

Here is an example, computing the number of solutions of the N-queens problem, in Python. It's easy to write the same in Lisp, Ada or Fortran for instance, which all allow some kind of nested function.

def queens(n):
    a = list(range(n))
    u = [True]*(2*n - 1)
    v = [True]*(2*n - 1)
    m = 0

    def sub(i):
        nonlocal m

        if i == n:
            m += 1
        else:
            for j in range(i, n):
                p = i + a[j]
                q = i + n - 1 - a[j]
                if u[p] and v[q]:
                    u[p] = v[q] = False
                    a[i], a[j] = a[j], a[i]
                    sub(i + 1)
                    u[p] = v[q] = True
                    a[i], a[j] = a[j], a[i]

    sub(0)
    return m

Now my question: is there a way to do something like this in C? I would think of two solutions: using globals or passing data as parameters, but they both look rather unsatisfying.

There is also a way to write this as an iterative program, but it's clumsy:actually, I first wrote the iterative solution in Fortran 77 for Rosetta Code and then wanted to sort out this mess. Fortran 77 does not have recursive functions.


For those who wonder, the function manages the NxN board as a permutation of [0, 1 ... N-1], so that queens are alone on lines and columns. The function is looking for all permutations that are also solutions of the problem, starting to check the first column (actually nothing to check), then the second, and recursively calling itself only when the first i columns are in a valid configuration.


Solution

  • Of course. You need to simulate the special environment in use by your nested function, as static variables on the module level. Declare them above your nested function.

    To not mess things up, you put this whole thing into a separate module.