Thread overview
Cases where I miss C++ 'using'
Nov 06, 2006
Bill Baxter
Nov 07, 2006
Daniel Keep
Nov 08, 2006
Daniel Keep
Nov 08, 2006
Bill Baxter
Nov 08, 2006
Bill Baxter
November 06, 2006
In C++ 'using' can be like a D alias but with the target name implied.

E.g.
   using Namespace::Class;

is like
   alias Module.Class Class;

I find I'm using the latter construct pretty often, and it just looks redundant compared to the equivalent in C++.  If not a new 'using' keyword, perhaps we could allow this?:

   alias some.package.module;

or this

   alias some.package.module .;  // unix 'ln -s' syntax!

as a synonym for

    alias some.package.module module;

If the thing being aliased has no dots,
    alias string;
then it would be an error (just like "alias x x" is an error).

--
Another use of 'using' in C++ is, within the current block scope, to bring every symbol in a namespace into the name table.  E.g.

   using namespace std;

makes std::string, std::vector, etc, all accessible without the std:: prefix.

This is quite similar to what with(std){...} would do, except 'using' does it in the _current_ block scope rather than requiring you create a new block scope.  I find 'with' to be quite handy, but sometimes the scope and extra nesting level are annoying, and it gets ugly if you want to 'with' two or more things simultaneously.  For example, say you want to use std.math and std.string in one function (but don't want them polluting your namespace elsewhere):

  static import std.math;
  static import std.string;
  ...
  void do_something()
  {
      with(std.math) {
          with(std.string) {
             str = format("%f <= %f", fmin(a,b), fmax(a,b));
             ...
             ...

          }
      }
  }

As an alternative to that, an alias-like "with declaration" would be handy:

  void do_something()
  {
      with std.math, std.string;
      str = format("%f <= %f", fmin(a,b), fmax(a,b));
      ...
      ...
  }

It's basically the same as 'import' (in fact "with m=std.math" would make sense too), except unlike import, it can be used anywhere, and not just at the top-level scope, and it doesn't actually import anything new, just gives new names to existing imported symbols.  For that reason it is probably a bad idea to use the 'import' keyword for this functionality.

Like in C++ the compiler can complain if there are some symbols that overlap.  Though I'd prefer it just use a 'last one wins' rule, which would be more equivalent to the nested 'with statements' case.  Anyway, I use that sort of pattern a lot in C++ (putting 'using' statements within functions or classes or individual scopes).  It's just good programming practice to minimize namepspace pollution as much as possible.

--
Finally I wish there were some way to bring all the values in an *enum* into the current name resolution scope.  For example:

enum Buttons {
   Left,
   Right,
   Middle
}
with(Buttons) {  // doesn't work!
   x = Left|Middle
}
alias Buttons B;
y = B.Left | B.Middle;  // ok, but not as nice looking


--bb
November 07, 2006

Bill Baxter wrote:
> ...
> 
> As an alternative to that, an alias-like "with declaration" would be handy:
> 
>   void do_something()
>   {
>       with std.math, std.string;
>       str = format("%f <= %f", fmin(a,b), fmax(a,b));
>       ...
>       ...
>   }
> 

Or, you could use this to keep it consistent with various other block-modifying keywords:

> void do_something()
> {
>     with(std.math):
>     with(std.string): // or even with(std.math,std.string):
>     str = format("%f <= %f", fmin(a,b), fmax(a,b));
>     ...
>     ...
> }

> -- 
> Finally I wish there were some way to bring all the values in an *enum* into the current name resolution scope.  For example:
> 
> enum Buttons {
>    Left,
>    Right,
>    Middle
> }
> with(Buttons) {  // doesn't work!
>    x = Left|Middle
> }
> alias Buttons B;
> y = B.Left | B.Middle;  // ok, but not as nice looking
> 
> 
> --bb

Allowing you to use an Enum's name without the prefix is one of the things I actually miss about Visual Basic.  Sure, requiring the prefix is nice for the sake of organisation, but it gets *really* aggravating after a while.

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
November 07, 2006
Daniel Keep wrote:
>> Finally I wish there were some way to bring all the values in an *enum* into the current name resolution scope.  For example:
>>
>> enum Buttons {
>>    Left,
>>    Right,
>>    Middle
>> }
>> with(Buttons) {  // doesn't work!
>>    x = Left|Middle
>> }
>> alias Buttons B;
>> y = B.Left | B.Middle;  // ok, but not as nice looking
>>
>>
>> --bb
> 
> Allowing you to use an Enum's name without the prefix is one of the things I actually miss about Visual Basic.  Sure, requiring the prefix is nice for the sake of organisation, but it gets *really* aggravating after a while.

I mostly use enums inside switch statements. Java makes a nice compromise here by only requiring the prefix outside switches. I don't like making them accessible everywhere without prefixing.
November 08, 2006

Jari-Matti Mäkelä wrote:
> Daniel Keep wrote:
>>> Finally I wish there were some way to bring all the values in an *enum* into the current name resolution scope.  For example:
>>>
>>> enum Buttons {
>>>    Left,
>>>    Right,
>>>    Middle
>>> }
>>> with(Buttons) {  // doesn't work!
>>>    x = Left|Middle
>>> }
>>> alias Buttons B;
>>> y = B.Left | B.Middle;  // ok, but not as nice looking
>>>
>>>
>>> --bb
>> Allowing you to use an Enum's name without the prefix is one of the things I actually miss about Visual Basic.  Sure, requiring the prefix is nice for the sake of organisation, but it gets *really* aggravating after a while.
> 
> I mostly use enums inside switch statements. Java makes a nice compromise here by only requiring the prefix outside switches. I don't like making them accessible everywhere without prefixing.

True, since that negates one of the benefits of Enums: organisation. One thing I thought was very cool (I can't remember if this was VB6 or VB.Net) was that if you were calling a function that took an enum, you could omit the prefix.  ie:

> Sub Foo(SomeEnum e)

Could be called:

> Foo(SomeEnum.Bar)

Or:

> Foo(Bar)

Maybe if we allowed the prefix to be omitted when

a. we're switching on an enum,
b. we're passing an enum argument to a function and
c. when we're assigning to an enum typed variable

that would be enough.  Then again, maybe that's just because I'm a lazy bugger :)

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
November 08, 2006
Daniel Keep wrote:
> 
> Jari-Matti Mäkelä wrote:
>> Daniel Keep wrote:
>>>> Finally I wish there were some way to bring all the values in an *enum*
>>>> into the current name resolution scope.  For example:
>>>>
>>>> enum Buttons {
>>>>    Left,
>>>>    Right,
>>>>    Middle
>>>> }
>>>> with(Buttons) {  // doesn't work!
>>>>    x = Left|Middle
>>>> }
>>>> alias Buttons B;
>>>> y = B.Left | B.Middle;  // ok, but not as nice looking
>>>>
>>>>
>>>> --bb
>>> Allowing you to use an Enum's name without the prefix is one of the
>>> things I actually miss about Visual Basic.  Sure, requiring the prefix
>>> is nice for the sake of organisation, but it gets *really* aggravating
>>> after a while.
>> I mostly use enums inside switch statements. Java makes a nice
>> compromise here by only requiring the prefix outside switches. I don't
>> like making them accessible everywhere without prefixing.
> 
> True, since that negates one of the benefits of Enums: organisation.

I don't want them to be available everywhere either.  Just in particular functions or scopes where I'm going to be using them heavily.  I don't see why that ability should be limited to the insides of switch statements.

> One thing I thought was very cool (I can't remember if this was VB6 or
> VB.Net) was that if you were calling a function that took an enum, you
> could omit the prefix.  ie:
> 
>> Sub Foo(SomeEnum e)
> 
> Could be called:
> 
>> Foo(SomeEnum.Bar)
> 
> Or:
> 
>> Foo(Bar)

I would like that.  That's one of my biggest annoyances with C++ that still remains in D right there.

But there are ambiguities with operator overloading.  But that's no biggie, the compiler just needs to complain if leaving off the enum type creates an ambiguous overload situation.

> Maybe if we allowed the prefix to be omitted when
> a. we're switching on an enum,
> b. we're passing an enum argument to a function and
> c. when we're assigning to an enum typed variable
> 
> that would be enough.  Then again, maybe that's just because I'm a lazy
> bugger :)

Me too.  But its not just laziness.  Having lots of repetitive cruft in the code makes it harder to see what's really going on.

--bb
November 08, 2006
Daniel Keep wrote:
> 
> 
> Maybe if we allowed the prefix to be omitted when
> 
> a. we're switching on an enum,
> b. we're passing an enum argument to a function and
> c. when we're assigning to an enum typed variable
> 
> that would be enough.  Then again, maybe that's just because I'm a lazy
> bugger :)

Another case would be comparing equality like

  SomeEnum val;
  ...
  if (val == SomeEnum.Bar) { ... }

Or any of the other operators defined for Enums probably - !=, |, &, etc.

--bb