Why does Return[expr] print Return[expr] when immediately invoked?

It appears as though immediately-evaluated loops print Return[expr], whereas their evaluation-delayed counterparts do not. Is there any way to avoid this behavior without wrapping it in an immediately-invoked lambda or something else absurd?

A quick example:

immediate = 
 For[i = 0, i < 10, i++, 
  If[i == 5, Return[i]]] (* Out == Return[5] *)
delayed := 
 For[i = 0, i < 10, i++, If[i == 5, Return[i]]] (* Out == Null *)
immediate (* Out == 5 *)
delayed (* Out == 5 *)

By far the most frustrating part of this is that it completely ignores semicolons. It’s as if the expression were just a raw Return, i.e. foo = Return[5] and just Return[5] exhibit the same behavior. What gives?

From the documentation

Return[expr] exits control structures within the definition of a
function, and gives the value expr for the whole function

There are no function definitions in your examples. Return is rarely required in WL code.

There are much better alternatives to For e.g. Table, Map, …

Why do you need For and Return, what is the real problem you are trying to solve?

I see. I thought that While and For were considered functions in this sense.

I am trying to find the the first i > 0 such that, for a function f, f[n] == 0. It was my understanding that the alternatives you provided do not qualify because the iteration is technically unbounded.

This is the implementation I was hoping to use:

answer = For[i = 1, True, i++, If[f[n, i] == 1, Return[i]]]

I suppose Break may be of some use here, since i is not scoped in this case (strange as that may be).

Hi Elias,

Thanks for clarifying. The original example had a bounded For loop. You are right, Table and Map are not good options for unbounded iteration. A couple of alternatives

ClearAll[f, n, i];
f[n_, i_] := i == 10000

i = 1; While[! f[n, i], i++]; i
(* 10000 *)

Do[If[f[n, i], Return[i]], {i, Infinity}]
 (* 10000 *)