In programming, we can make the distinction between declarative / functional and procedural / imperative programming. The distinction is not exact, but nevertheless meaningful.
One major difference is that declarative style tends to make use of recursion in places where imperative style makes use of iteration.
Consider the following (informal) imperative style definition of a subset $X\subset \mathbb N$ given a function $f:\mathbb N \to \mathcal P( \mathbb N)$.
Put $0$ in $X$.
Repeat to infinity: For each $x\in X$, put the elements of $f(x)$ in $X$.
This means that $X$ is not an immutable object, but more akin to a “list” in imperative programming languages. I understand that mathematicians would call $X$ “ill-defined”, but as an imperative style program, this is (the pseudocode of) a perfectly well-defined program.
In general, I know that mathematicians don’t like “mutable” objects, and maybe this is the reason why they don’t like such imperative-style definitions. But I don’t really understand why.
Why do mathematicians consider such “imperative” style definitions bad, or even ill-defined, given that they can be quite intuitive and also well defined as an imperative program?
I cannot speak for all mathematicians, but one key difference in computer science versus mathematics is that objects in computer science are typically viewed as mutable (unless they are declared 'const' or similar), while in mathematics we use names to refer to specific mathematical objects that cannot change. The difference happens because computer scientists are typically thinking of how variables work in programming, while mathematicians only use variables as names for mathematical objects.
In the style of exposition from computer science, this makes sense:
Here the actual contents of the list $L$ changed twice during the instructions. We are thinking of the instructions as a kind of pseudocode.
In a common style of mathematical exposition, if we say "Let $L$ be the empty list", we mean that $L$ is the empty list. If we then say "put '1' on the left end of $L$", we obtain a new list, not $L$, because we already defined $L$ to be the empty list. We could say "Redefine $L$ to be the list obtained by push '1' on the left end of the current list $L$", but this is verbose.
However, the imperative style used above is completely possible in ordinary mathematical exposition. It would read like this:
Notice that we didn't "put things in" to an existing set in the sense of redefining a variable to stand for a new set after the variable was defined. Instead, we used different sets $X_i$ for each $i \in \mathbb{N}$.
At the same time, it is also perfectly normal to say something like "Make a $\{0,1\}$ matrix $M$ by putting in one column for each 8-bit binary number from $0$ to $255$ in lexicographic order". The key here is the "putting in" does not mean redefining $M$ at each step, it only says how to build the matrix $M$.