On Monday, 22 September 2014 at 06:05:42 UTC, Walter Bright wrote:
On 9/21/2014 2:17 PM, ketmar via Digitalmars-d wrote:
On Sun, 21 Sep 2014 13:04:49 -0700
Walter Bright via Digitalmars-d <digitalmars-d@puremagic.com>
wrote:
I don't know what mental model people have for how lookups
work, but
the above algorithm is how it actually works.
i believe that people expect this:
void foo (int a) {
import a;
a.bar(); // here we use 'a' module
xyzzy(); // it's actually 'a.xyzzy', and 'a as module' is
implicit
writeln(a); // here we use 'int a' argument
Context dependent lookups? That's an awful lot more complex
than the existing rules.
}
i.e. symbol resolver will try argument/local name first, and
only if it
failed tries to search in module.
That's how it does work. It's just that parameters are in an
enclosing scope.
or, more complicated sample:
struct A { int bar; int baz; }
void foo (in A a) {
import a;
a.bar(); // KABOOM, conflicting names
xyzzy(); // it's actually 'a.xyzzy', and 'a as module' is
implicit
writeln(a); // KABOOM (both module and arg are complex
types
writeln(a.baz); // it's ok until module 'a' doesn't have
'baz'
}
i'm not saying that this is how things *must* work, but this
is what
one excepts, i think.
I have no idea how to even write such rules, let alone what
kind of error messages to generate when the user does it wrong.
I believe it is far better to have simple rules, easy to
explain, and have a few awkward edge cases than having a
terribly complex setup with special cases that nobody
understands.
For example, probably 3 people on the planet understand C++
overloading rules (pages and pages of trivia). The rest just
try things at random until it appears to work.
+1
We should simply do a lookup for local symbol, and if that fail,
imported symbols.
In that case, a should resolve as the parameter, all the time.