I have a feature request: "Named enum scope inference"

kenji hara k.hara.pg at gmail.com
Sat Sep 29 00:04:37 PDT 2012


2012/9/29 Tommi <tommitissari at hotmail.com>:
> On Saturday, 29 September 2012 at 04:26:01 UTC, Alex Rønne Petersen wrote:
>>
>>
>> It's an awful lot of magic (it's not as easy in the implementation as it
>> sounds like) for questionable gain when we have the with statement IMO.
>
>
> "it's not as easy in the implementation as it sounds like"
> ----------------------------------------------------------
> If this argument means: "It's going to increase the compilation time too
> much", then it's obviously a good reason not to do it. But if it means:
> "It's a lot of work to modify the compiler source code", then that's
> completely an unacceptable argument. The question of how much work it is to
> implement, has nothing to do with whether it's a good feature to have or
> not. And that's what we're discussing.
>
>
> "questionable gain"
> -------------------
> Well, if you never use enum flags to control the specifics of your types and
> functions, then the gain is zero. That is parallel to: if you never create
> any variables, then the gain of the keyword 'auto' is zero. If you do
> however do these things constantly, then the gain is: less typing and
> cleaner syntax. Comparison:
>
> enum Size    { small, medium, big }
> enum Fitness { thin, strong, weak, fat }
> enum Goal    { love, build, heal, kill }
>
> class Character(Size s, Fitness f, Motivation m)
> {
>     ...
> }
>
> auto c1 = new Character!(Size.big, Fitness.fat, Goal.kill);
> auto c2 = new Character!(big, fat, kill);
>

No, compiler implementation is not a problem.
In past, I've thought about such feature, but there is some
difficulties to determine an obvious semantic.

1. If the enum member name is same as local variable.

  enum E { foo ,bar }
  void test(E e) {}
  void main() {
    auto bar = E.foo;
    test(bar);
    // 1a) test receives E.bar, or
    // 1b) E.foo from local variable 'var'?
  }

If you select 1a, existing code will break.
But, 1b will introduce more worse case. See next.

2. The semantics based on 'whether is undefined name or not' is fragile.
First, you might write code such as the following.

  enum E { foo ,bar }
  void test(E e) {}
  void main() {
    test(foo);  // in here, the name 'bar' is undefined, so test can
receive E.foo
  }

After a while, you may add a global variable in module scope.

  enum E { foo ,bar }
  int foo = 10;
  void test(E e) {}
  void main() {
    test(foo);  // foo is defined, and look up module scope foo.
    // Then, now the code is broken implicitly!
  }

This is a hijacking of local scope, and it is awful.

----
P.S.

It seems to me the root problem is that using a raw-identifier for the
start of the inference.
If there is a symbol literal, the problem may be solved.

  test('bar);  // bar is a symbol, so it does not refer any normal declarations

Kenji Hara


More information about the Digitalmars-d mailing list