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.

Reply via email to