On 5/31/22 2:30 PM, Don Allen wrote:
> On Tuesday, 31 May 2022 at 17:52:35 UTC, Adam D Ruppe wrote:
> On Tuesday, 31 May 2022 at 17:41:18 UTC, Don Allen wrote:
> This strikes me as pretty inconsistent behavior
Code in functions is actually executed in sequence. Nested functions aren't exactly code, but the same rule applies to them. Consider:
int a = 5;
a = 6;
int b = a;
What is b? Of course we know since it happens in sequence. Same rule applies with nested functions.
> I've also not found it documented, though I could have missed it (if someone could point me to where this is discussed, I'd
It has its own section on the function page:
https://dlang.org/spec/function.html#nested-declaration-order
Code in Scheme functions are also evaluated in sequence, but functions can be mutually recursive whether at top-level or not, so the mere fact of sequential evaluation is not the explanation.
The scheme code likely evaluates the definition of the function, without resolving what code to call until it encounters a call.
In other words, something like this in D (I haven't used scheme in a while, so we are going to use D syntax):
void foo() { bar(); }
void bar() { writeln("hello"); }
foo();
would work with scheme rules but
void foo() { bar(); }
foo();
void bar() { writeln("hello"); }
would not.
> What appears to matter is when the location of called functions are resolved -- compile-time
It's not a matter of when they are resolved. D is fully capable of resolving functions at compile time out of order. It's a question of what symbols are in scope.
Consider:
void foo() { writeln("outer foo"); }
void main()
{
void bar() { foo(); }
void foo() { writeln("inner foo"); }
bar();
}
what should print is "outer foo", because that is what foo
means at the point in which bar is being compiled. Inside functions, order of declaration is important and significant. Outside functions, they can be in any order, but must not be ambiguous. These are incompatible sets of rules. You have to pick one, and D chose to pick C rules inside functions (likely for compatibility), but allowed out of order declarations outside them because prototyping is just monotonous.
This is done on purpose. The easiest way to solve this is to declare the functions inside a struct in the function (as the workarounds suggest). I've done this many times when I have a significantly complex recursive algorithm that I don't want to expose outside the function.
Note that you can declare a prototype, but this also declares a symbol, and D does not allow you to redefine symbols.
-Steve