View mode: basic / threaded / horizontal-split · Log in · Help
September 29, 2012
I have a feature request: "Named enum scope inference"
I have a feature request: "Named enum scope inference"

The idea is, that whenever a named enum value is expected, you 
don't need to explicitly specify the scope of the enum value. 
This would reduce redundancy in typing, just like automatic type 
inference does.

Examples:
---------

enum MyDirection { forward, reverse }

struct MyIterator(MyDirection dir)
{
    ...
}

int forward = 42; // Doesn't interfere with the next line...
auto itr = MyIterator!forward(); // Infers MyDirection.forward

----------------------------------------------------------------

enum MyLockType { read, read_write }

struct MyScopedLock
{
    this(MyMutex mutex, MyLockType lockType)
    {
        ...
    }
}

shared MyMutex g_mutex;
...
auto scopedLock = MyScopedLock(g_mutex, read_write);
// Infered MyLockType.read_write

// Side note: Compare the above to having a boolean flag...
auto scopedLock = MyInferiorScopedLock(g_mutex, true);
// ... and you have to read the docs to know what 'true' means

----------------------------------------------------------------

enum MyFruit { apple, orange, banana }

MyFruit fruit;

switch (fruit)
{
    case apple:  break; // Case expressions know what type to
    case orange: break; // expect based on the switch expression
    case banana: break;
}
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
On 29-09-2012 03:55, Tommi wrote:
> I have a feature request: "Named enum scope inference"
>
> The idea is, that whenever a named enum value is expected, you don't
> need to explicitly specify the scope of the enum value. This would
> reduce redundancy in typing, just like automatic type inference does.
>
> Examples:
> ---------
>
> enum MyDirection { forward, reverse }
>
> struct MyIterator(MyDirection dir)
> {
>      ...
> }
>
> int forward = 42; // Doesn't interfere with the next line...
> auto itr = MyIterator!forward(); // Infers MyDirection.forward
>
> ----------------------------------------------------------------
>
> enum MyLockType { read, read_write }
>
> struct MyScopedLock
> {
>      this(MyMutex mutex, MyLockType lockType)
>      {
>          ...
>      }
> }
>
> shared MyMutex g_mutex;
> ...
> auto scopedLock = MyScopedLock(g_mutex, read_write);
> // Infered MyLockType.read_write
>
> // Side note: Compare the above to having a boolean flag...
> auto scopedLock = MyInferiorScopedLock(g_mutex, true);
> // ... and you have to read the docs to know what 'true' means
>
> ----------------------------------------------------------------
>
> enum MyFruit { apple, orange, banana }
>
> MyFruit fruit;
>
> switch (fruit)
> {
>      case apple:  break; // Case expressions know what type to
>      case orange: break; // expect based on the switch expression
>      case banana: break;
> }
>
>
>

The first issue with this proposal that comes to mind is this:

enum Foo { bar }

void func(Foo f)
{
    // ...
}

// ...

Foo bar = Foo.bar;
func(bar); // ?

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
On Saturday, 29 September 2012 at 02:01:15 UTC, Alex Rønne 
Petersen wrote:
> The first issue with this proposal that comes to mind is this:
>
> enum Foo { bar }
>
> void func(Foo f)
> {
>     // ...
> }
>
> // ...
>
> Foo bar = Foo.bar;
> func(bar); // ?

Maybe it should simply throw a compile error about the ambiguity 
of 'bar' in 'func(bar)'. But if the local variable 'bar' if not 
of Foo type, then there's no ambiguity. Or, if the local variable 
'bar' is a compile time constant that evaluates to Foo.bar, then 
there's no ambiguity either.
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
On 29-09-2012 04:31, Tommi wrote:
> On Saturday, 29 September 2012 at 02:01:15 UTC, Alex Rønne Petersen wrote:
>> The first issue with this proposal that comes to mind is this:
>>
>> enum Foo { bar }
>>
>> void func(Foo f)
>> {
>>     // ...
>> }
>>
>> // ...
>>
>> Foo bar = Foo.bar;
>> func(bar); // ?
>
> Maybe it should simply throw a compile error about the ambiguity of
> 'bar' in 'func(bar)'. But if the local variable 'bar' if not of Foo
> type, then there's no ambiguity. Or, if the local variable 'bar' is a
> compile time constant that evaluates to Foo.bar, then there's no
> ambiguity either.

Regardless of the conditions under which to throw an error, it would be 
a breaking change.

-- 
Alex Rønne Petersen
alex@lycus.org
http://lycus.org
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
> I have a feature request: "Named enum scope inference"
>
> The idea is, that whenever a named enum value is expected, you 
> don't need to explicitly specify the scope of the enum value. 
> This would reduce redundancy in typing, just like automatic 
> type inference does.
>
> Examples:
> ---------
>
> enum MyDirection { forward, reverse }
> struct MyIterator(MyDirection dir)
> {
>     ...
> }
>
> int forward = 42; // Doesn't interfere with the next line...
> auto itr = MyIterator!forward(); // Infers MyDirection.forward

I like the spirit of this feature, but as Alex pointed out, 
ambiguity is possible (which could theoretically cause errors in 
existing code) and while I'm not familiar with how the compiler 
is implemented, my spidey-sense thinks that what you're asking 
for could be tricky to implement (in a language that already has 
a very large amount of rules and features.) 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. So there is a sort of 
decrease in clarity of the entire language by increasing the 
total number of possible meanings that an identifier can have.

So I think this feature would need a more clear syntax, something 
to indicate that the value is an enum value. I don't currently 
have a really good counterproposal though....
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
On Saturday, September 29, 2012 03:55:48 Tommi wrote:
> enum MyFruit { apple, orange, banana }
> 
> MyFruit fruit;
> 
> switch (fruit)
> {
>      case apple:  break; // Case expressions know what type to
>      case orange: break; // expect based on the switch expression
>      case banana: break;
> }

This could be achieved by simply making it so that when a variable of an enum 
type is used in a switch statement, the cases permit you to omit the enum's 
type when referring to the enum values. None of the name inferrence stuff that 
you're suggesting would be required for that. Though at the moment, I believe 
that you could simply use with to solve the problem:

with(MyFruit)
{
   switch(fruit)
   {
       case apple: break;
       case orange: break;
       case banana: break;
   }
}

All that would be required to do it without the with would be to make it so 
that the compiler implicitly added the with when an enum type is used in the 
switch.

- Jonathan M Davis
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
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) ?
}
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
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;
}
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
On Saturday, 29 September 2012 at 02:37:40 UTC, Alex Rønne 
Petersen wrote:
>
> Regardless of the conditions under which to throw an error, it 
> would be a breaking change.

I guess that's a bad thing. Hmmm... too bad.

Well... maybe we could make it so that variables of the requested 
enum type are looked up first, and if such is found (even with a 
same name as one of the enumerations), then that variable is 
used. Only if no variables of that name exist, then you see if 
the name correctly maps to a named enum literal, and if not then 
you see if you can map the name using the enum type name as its 
scope. I think that's quite a logical rule anyway, because if 
you've defined a variable of the correct enum type and pass it to 
a function, you quite likely meant to pass that variable to that 
function (instead of passing an enum literal).
September 29, 2012
Re: I have a feature request: "Named enum scope inference"
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. So there is a sort of decrease in clarity of the 
> entire language by increasing the total number of possible 
> meanings that an identifier can have.

But, if you use the explicit "MyIterator!(MyDirection.forward)" 
in your code, I don't think that's any more clear about what 
"forward" actually is. It could be anything:

struct MyDirection
{
    struct forward {}
    // ... or:
    static @property int forward() { return 42; }
    // ... or:
    static enum forward = 1.5;
}

Only extra clue that get with the the explicit form 
(EnumType.enumerationName) is the name of the enum type. If it 
makes the code clearer, then use explicit form. But more often 
than not, the combination of the enumeration name and the context 
where it is used makes the intention clear enough.


On 9/29/12, David Piepgrass <qwertie256@gmail.com> wrote:
> 
> 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) ?
> }

But that's not what I'm suggesting. The feature suggested is:
"Try to perform implicit scoping (as a last resort), if a named 
enum variable is expected". Your function "void test(bool state)" 
doesn't *expect* a named enum as an argument. If it did expect, 
say Foo, as an argument, then Foo.no would be passed.
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home