September 29, 2012
So, these would be the new rules we'd give to the compiler:

1) See if you can compile the code exactly the way you've been doing it thus far. If it compiles, great, we're done.

2) Else, if there are undefined identifiers that are passed to places where named enum variables are expected, try to see if prefixing those identifier names with the expected enum type name (plus a dot) would make the code compile.

This wouldn't break any existing code, and to me the rule seems intuitive enough.
September 29, 2012
On Saturday, 29 September 2012 at 02:57:42 UTC, David Piepgrass wrote:
>
> Plus, I don't like the fact that when you see something like "MyIterator!forward" by itself in code, there is no obvious clue that forward is an enum value and not a class name or a variable.

I might also add, that once we have an IDE that can do proper semantic analysis and colorization, you'll know it's an enum because it'll be colored like an enum.



September 29, 2012
On 29-09-2012 06:06, Tommi wrote:
> So, these would be the new rules we'd give to the compiler:
>
> 1) See if you can compile the code exactly the way you've been doing it
> thus far. If it compiles, great, we're done.
>
> 2) Else, if there are undefined identifiers that are passed to places
> where named enum variables are expected, try to see if prefixing those
> identifier names with the expected enum type name (plus a dot) would
> make the code compile.
>
> This wouldn't break any existing code, and to me the rule seems
> intuitive enough.

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.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 29, 2012
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);

September 29, 2012
On Saturday, 29 September 2012 at 05:08:12 UTC, Tommi wrote:
> 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.

Except a theoretical feature doesn't exist, so someone has
to write the code. So no, it's not an 'unacceptable
argument'.
September 29, 2012
2012/9/29 Tommi <tommitissari@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
September 29, 2012
On 29 September 2012 04:12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 9/29/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> you could simply use with to solve the problem:
>>
>> with(MyFruit)
>> {
>>     switch(fruit)
>>     {
>>         case apple: break;
>>         case orange: break;
>>         case banana: break;
>>     }
>> }
>>
>
> It's even simpler:
> switch(fruit) with (MyFruit)
> {
>     case apple: break;
>     case orange: break;
>     case banana: break;
> }

This. :-)



-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
September 29, 2012
Yeah, to respond to the larger topic, the with statement
is more than enough here. I'm not convinced that complicating
lookup rules further is worth it.


September 29, 2012
On Saturday, 29 September 2012 at 05:47:59 UTC, Bernard Helyer wrote:
>
> Except a theoretical feature doesn't exist, so someone has
> to write the code. So no, it's not an 'unacceptable
> argument'.

I'll explain my way of seeing this in the form we all understand: code.

bool tryImplement(Feature x)
{
    bool is_a_nice_feature_to_have = discussFeature(x);

    if (is_a_nice_feature_to_have)
    {
        bool do_we_implement_it = discussImplementation(x);

        if (do_we_implement_it)
        {
            implement(x);
            return true;
        }

        std.pause(10.years);

        bool does_someone_else_implement_it_in_2022 =
            discussImplementation(x);

        if (does_someone_else_implement_it_in_2022)
        {
            implement(x);
            return true;
        }

        std.pause(10.years);

        // ... and so on
    }

    return false;
}

And I think we're currently inside the function call 'discussFeature(x)'. There's no point in calling 'discussImplementation(x)' until we're in the scope of the if clause 'if (is_a_nice_feature_to_have)'.
September 29, 2012
On 29/09/2012 04:11, Andrej Mitrovic wrote:
> On 9/29/12, David Piepgrass <qwertie256@gmail.com> wrote:
>> I like the spirit of this feature, but as Alex pointed out,
>> ambiguity is possible (which could theoretically cause errors in
>> existing code)
>
> It could also cause subtle problems because enum values are implicitly
> convertible to the enum's base type. Take this for example:
>
> void test(bool state) { }
> enum Foo { no, yes }
> class Class
> {
>      enum Bar { yes, no }
>      void test() { .test(no); }  // pass Foo.no (true) or Bar.no (false) ?
> }
>

This isn't an issue with this proposal. There is no enum type available to use for inference, so 'no' simply doesn't resolve there.

If you're ever working in Java using Eclipse, you'll notice that Eclipse has this very feature in its autocomplete engine. For example, if you write:

if (myEnumValue ==

and then press Ctrl+Space, then it'll list the enum constants. When you select one, it'll generate the qualified name because it has to.

The point is to use what we know about the type that is *likely* to occur here (by considering assignment LHS, comparison LHS, parameters to possibly matching methods, method return type in argument to 'return', etc.) to infer which enum type's members to consider (if any).

Hope that clarifies :)