www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Cases where I miss C++ 'using'

reply Bill Baxter <wbaxter gmail.com> writes:
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
Nov 06 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
Nov 06 2006
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
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.
Nov 07 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
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/
Nov 07 2006
next sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Nov 07 2006
prev sibling parent Bill Baxter <dnewsgroup billbaxter.com> writes:
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
Nov 07 2006