Pure functional programming languages do not allow mutable state. They can simulate it with monads, and they typically have impurities to allow io sode effects, but a for loop is an inherently imperative construct. Mostly functional languages like ocaml have things like ref. Functional languages aren't just about functions being composable and having no side effects, they also require that once a value is bound to a name, that it does not change. That isn't just pedantry either, it is what allows safe concurrency by default.
Ocaml is immutable. It has ref if you need mutation, this is not the default thing you grab tho. Haskell has unsafe and IORef, that does basically the same thing. Scala, rust etc has all escape hatches.
A loop by itself is not non-fp, as i can do the exact same thing via recursion. Its just syntax.
Hell, i can write a never halting program in lambda calculus with a fixed point combinator causing "undefined behaviour".