View mode: basic / threaded / horizontal-split · Log in · Help
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 2012-04-03 11:08:38 +0000, Don Clugston <dac@nospam.com> said:

> On 03/04/12 12:32, Timon Gehr wrote:
>> On 04/03/2012 10:27 AM, Don Clugston wrote:
>>> This is asking for a complicated special case. In global scope, order of
>>> declarations doesn't matter. In function scope, order of declarations
>>> always matters.
>>> If you have type inference of function returns, things can get nasty:
>>> 
>>> void foo()
>>> {
>>> auto b() { return a(); }
>>> X x = whatever;
>>> auto a() { return x; }
>>> }
>>> Now b actually depends on the declaration of x. So it's not enough to
>>> say that only function declarations are immune to ordering rules.
>> 
>> I come to a different conclusion. If only function declarations are
>> immune to ordering rules, the above example is simply illegal. The
>> example cannot be used to demonstrate incompleteness of the approach.
> 
> I don't see a way to just declare it as "illegal". How would you detect 
> that situation in the general case?
> It's not easy.
> 
> Y b() { ... }
> Y y = b();
> X x = ...
> 
> Prove that y doesn't depend on x.

You're right Don, it shouldn't be illegal. But it could be part of the 
constrain. Let's rephrase Timon's idea like this:

If two or more functions declarations are following each other with no 
other statement in between, then these two functions can call one 
another. That could allow overloading too, as long as the declarations 
are following each other directly.

In fact, that'd probably be generalizable to templates, struct, class, 
and enum declarations too. Adjacent declarations would create some kind 
of island in the function's code where order of declaration does not 
matter. The island ends at the first non-declaration statement or local 
variable declaration, and a new island begins when new declarations are 
encountered.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 04/03/2012 01:08 PM, Don Clugston wrote:
>
> Y b() { ... }
> Y y = b();
> X x = ...
>
> Prove that y doesn't depend on x.

Since only function declarations are immune to ordering rules, b cannot 
forward reference x.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
"Don Clugston" <dac@nospam.com> wrote in message 
news:jlelnn$tm4$1@digitalmars.com...
>
> I don't see a way to just declare it as "illegal". How would you detect 
> that situation in the general case?
> It's not easy.
>
> Y b() { ... }
> Y y = b();
> X x = ...
>
> Prove that y doesn't depend on x.

We don't *have* to go the route of allowing nested functions to access 
forward-referenced variables. We could just limit it to forward-referenced 
nested functions. So this code could be illegal for exactly the same reason 
it's currently illegal:

Y b() { /+ use the var 'x' +/ }
Y y = b();
X x = ...

If 'x' were a nested function instead of a variable, then *that* we could 
decide to start allowing:

Y b() { /+ call function 'x' +/ }
Y y = b();
X x() { ... } // b can access this because this is a nested func, not a var

Of course, as you already pointed out and I replied to elsewhere in this 
thread, we'd still have to do something about this scenario:

X b() { return a(); }
X w = b();
X x = whatever;
X a() { return x; }

Alternatively, if I understand Timon right, I think he's suggesting that we 
could treat "groups" of nested function declarations as "unordered", and any 
one other statement/declaration would simply break the "group":

// These three can all reference each other freely,
// but they cannot reference f, x, y or z.
A a() {...}
B b() {...}
C c() {...}

// Something other than a nested function declaration.
// This ends the "grouping" of a, b, and c.
F f = ...;

// These three can all reference each other freely.
// Naturally, these can also reference a, b, c, and f
X x() {...}
Y y() {...}
Z z() {...}

That would allow mutual recursion while neatly avoiding any problems.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 03/04/12 13:35, Timon Gehr wrote:
> On 04/03/2012 01:08 PM, Don Clugston wrote:
>>
>> Y b() { ... }
>> Y y = b();
>> X x = ...
>>
>> Prove that y doesn't depend on x.
>
> Since only function declarations are immune to ordering rules, b cannot
> forward reference x.

But there could be another function a() which is below x, and which b() 
calls.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
"Timon Gehr" <timon.gehr@gmx.ch> wrote in message 
news:jlej27$mvi$1@digitalmars.com...
>
> This is the right way to work around this issue. It works now and does not 
> imply any kind of overhead at runtime:
>
> void foo(){
>     void a()(){ ... }
>     void b()  { ... }
> }
>

That's a very simple workaround (albiet unintuitive - unless I'm just too 
tired right now). It leads me to two questions:

1. How the heck does that work?

2. What, if any, problems would arise from just automatically doing that 
behind-the-scenes? Ie, to just automatically turn all non-templated nested 
functions into no-parameter templated nested functions? Would that be a 
feasable solution?
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 04/03/2012 01:55 PM, Don Clugston wrote:
> On 03/04/12 13:35, Timon Gehr wrote:
>> On 04/03/2012 01:08 PM, Don Clugston wrote:
>>>
>>> Y b() { ... }
>>> Y y = b();
>>> X x = ...
>>>
>>> Prove that y doesn't depend on x.
>>
>> Since only function declarations are immune to ordering rules, b cannot
>> forward reference x.
>
> But there could be another function a() which is below x, and which b()
> calls.

This scenario can be forbidden conservatively.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 03/04/12 13:51, Nick Sabalausky wrote:
> "Don Clugston"<dac@nospam.com>  wrote in message
> news:jlelnn$tm4$1@digitalmars.com...
>>
>> I don't see a way to just declare it as "illegal". How would you detect
>> that situation in the general case?
>> It's not easy.
>>
>> Y b() { ... }
>> Y y = b();
>> X x = ...
>>
>> Prove that y doesn't depend on x.
>
> We don't *have* to go the route of allowing nested functions to access
> forward-referenced variables. We could just limit it to forward-referenced
> nested functions.

But it's the same. If you can forward reference a function, you can also 
access a variable.

So this code could be illegal for exactly the same reason
> it's currently illegal:

>
> Y b() { /+ use the var 'x' +/ }
> Y y = b();
> X x = ...
>
> If 'x' were a nested function instead of a variable, then *that* we could
> decide to start allowing:
>
> Y b() { /+ call function 'x' +/ }
> Y y = b();
> X x() { ... } // b can access this because this is a nested func, not a var
>
> Of course, as you already pointed out and I replied to elsewhere in this
> thread, we'd still have to do something about this scenario:
>
> X b() { return a(); }
> X w = b();
> X x = whatever;
> X a() { return x; }

And I don't think there's any easy solution to that.
I think it's a dead end.

> Alternatively, if I understand Timon right, I think he's suggesting that we
> could treat "groups" of nested function declarations as "unordered", and any
> one other statement/declaration would simply break the "group":
>
> // These three can all reference each other freely,
> // but they cannot reference f, x, y or z.
> A a() {...}
> B b() {...}
> C c() {...}
>
> // Something other than a nested function declaration.
> // This ends the "grouping" of a, b, and c.
> F f = ...;
>
> // These three can all reference each other freely.
> // Naturally, these can also reference a, b, c, and f
> X x() {...}
> Y y() {...}
> Z z() {...}
>
> That would allow mutual recursion while neatly avoiding any problems.

Yeah, that'd work. It's a funky rule though.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 03/04/12 13:58, Timon Gehr wrote:
> On 04/03/2012 01:55 PM, Don Clugston wrote:
>> On 03/04/12 13:35, Timon Gehr wrote:
>>> On 04/03/2012 01:08 PM, Don Clugston wrote:
>>>>
>>>> Y b() { ... }
>>>> Y y = b();
>>>> X x = ...
>>>>
>>>> Prove that y doesn't depend on x.
>>>
>>> Since only function declarations are immune to ordering rules, b cannot
>>> forward reference x.
>>
>> But there could be another function a() which is below x, and which b()
>> calls.
>
> This scenario can be forbidden conservatively.

How?
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
On 04/03/2012 02:00 PM, Nick Sabalausky wrote:
> "Timon Gehr"<timon.gehr@gmx.ch>  wrote in message
> news:jlej27$mvi$1@digitalmars.com...
>>
>> This is the right way to work around this issue. It works now and does not
>> imply any kind of overhead at runtime:
>>
>> void foo(){
>>      void a()(){ ... }
>>      void b()  { ... }
>> }
>>
>
> That's a very simple workaround (albiet unintuitive - unless I'm just too
> tired right now). It leads me to two questions:
>
> 1. How the heck does that work?
>

Symbol lookup is done upon the first instantiation of the local template.

> 2. What, if any, problems would arise from just automatically doing that
> behind-the-scenes? Ie, to just automatically turn all non-templated nested
> functions into no-parameter templated nested functions? Would that be a
> feasable solution?
>
>

Your proposal is basically to allow a local function to forward 
reference any symbol that is declared before the local function is first 
referenced.

This still has the following problem:

void a(){/*cannot reference c*/}
void b(){/*because this references a*/}
void c(){/*references a and b*/ }

It would work by reordering the code like so:

void b(){/*references a*/}
void a(){/*references c*/}
void c(){/*references a and c*/}

That would be extremely unintuitive.
April 03, 2012
Re: Nested functions should be exempt from sequential visibility rules
Nick Sabalausky:

> I submit that nested functions should be exempt from the usual 
> sequential
> visibility rules. (Therefore, mutually recursive nested 
> functions would
> become possible.)

What about static nested functions? This seems a simpler
enhancement request:

import std.stdio;
void main() {
   static int male(in int n) pure nothrow {
     return n ? (n - female(male(n - 1))) : 0;
   }
   static int female(in int n) pure nothrow {
     return n ? (n - male(female(n - 1))) : 1;
   }
   writeln(female(15));
}

Bye,
bearophile
1 2 3
Top | Discussion index | About this forum | D home