www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - "with" should be deprecated with extreme prejudice

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
I think "with" is a very dangerous feature due to the way it hides 
symbols. It essentially makes the feeblest attempt at modular reasoning 
utterly impossible:

int x, y;
with (whatever)
{
     y += x;
     ++x;
}

What can be said about such code? Nothing. If whatever has or will ever 
have fields x or y or both, the names will bind to them; otherwise, 
they'll bind to the locals. Non-local code dependency at its finest.

Maintenance of any type that is being used with "with" becomes a very 
dangerous proposition because it can silently change meaning of code.

I therefore submit that "with" is an extremely dangerous feature and 
should be removed from the language. What say you?


Andrei
May 17 2009
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular reasoning
 utterly impossible:
 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }
 What can be said about such code? Nothing. If whatever has or will ever
 have fields x or y or both, the names will bind to them; otherwise,
 they'll bind to the locals. Non-local code dependency at its finest.
 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.
 I therefore submit that "with" is an extremely dangerous feature and
 should be removed from the language. What say you?
 Andrei

Absolutely not. It's far too useful as syntactic sugar when working heavily with plain old data structs, and saves a lot of tedious repetition of the struct instance name. There are lots of similar bonehead things one could do. For one, think of the opposite: accidentally declaring a local variable in a member function that hides the struct- or class-level variable. I see your point, but I simply think the benefits drastically outweigh the downsides. You can pry with() out of my cold, dead hands.
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Andrei Alexandrescu (SeeWebsiteForEmail erdani.org)'s article
 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular reasoning
 utterly impossible:
 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }
 What can be said about such code? Nothing. If whatever has or will ever
 have fields x or y or both, the names will bind to them; otherwise,
 they'll bind to the locals. Non-local code dependency at its finest.
 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.
 I therefore submit that "with" is an extremely dangerous feature and
 should be removed from the language. What say you?
 Andrei

Absolutely not. It's far too useful as syntactic sugar when working heavily with plain old data structs, and saves a lot of tedious repetition of the struct instance name.

Make it a member function! If you don't have access to the struct, use "s." as the prefix! I can't believe that's stopping you from getting work done!
 There are lots of similar bonehead things one could do.  For one,
 think of the opposite:  accidentally declaring a local variable in a member
 function that hides the struct- or class-level variable.  I see your point,
but I
 simply think the benefits drastically outweigh the downsides.  You can pry
with()
 out of my cold, dead hands.

That there are other bad things in D doesn't make "with" any more virtuous! I think you don't entirely get my point. The "with" statement is almost a textbook example of bad language design, creating a mess of long-distance dependencies. It is terrible. I can't believe it snuck under our nose for so long. It's a radioactive-leaking sarcophagus that must be buried. Andrei
May 17 2009
next sibling parent reply BCS <none anon.com> writes:
Hello Andrei,

 dsimcha wrote:
 
 Absolutely not.  It's far too useful as syntactic sugar when working
 heavily with plain old data structs, and saves a lot of tedious
 repetition of the struct instance name.
 

"s." as the prefix! I can't believe that's stopping you from getting work done!

I don't follow.
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
BCS wrote:
 Hello Andrei,
 
 dsimcha wrote:

 Absolutely not.  It's far too useful as syntactic sugar when working
 heavily with plain old data structs, and saves a lot of tedious
 repetition of the struct instance name.

"s." as the prefix! I can't believe that's stopping you from getting work done!

I don't follow.

"s." is hardly any typing. Andrei
May 17 2009
next sibling parent reply BCS <none anon.com> writes:
Hello Andrei,

 BCS wrote:
 
 Hello Andrei,
 
 dsimcha wrote:
 
 Absolutely not.  It's far too useful as syntactic sugar when
 working heavily with plain old data structs, and saves a lot of
 tedious repetition of the struct instance name.
 

use "s." as the prefix! I can't believe that's stopping you from getting work done!



wrong bit, I should have cut more:
 Make it a member function!

?
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
BCS wrote:
 Hello Andrei,
 
 BCS wrote:

 Hello Andrei,

 dsimcha wrote:

 Absolutely not.  It's far too useful as syntactic sugar when
 working heavily with plain old data structs, and saves a lot of
 tedious repetition of the struct instance name.

use "s." as the prefix! I can't believe that's stopping you from getting work done!



wrong bit, I should have cut more:
 Make it a member function!

?

In a member function there's no need to prefix each member. Andrei
May 17 2009
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 In a member function there's no need to prefix each member.

There isn't, but there should be. IMO. 'with' should be banned. Implicit access to members of 'this' should also be banned. I always use explicit 'this->' in C++ and explicit 'this.' in D. It makes the code much easier to read. -- Rainer Deyke - rainerd eldwood.com
May 17 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 In a member function there's no need to prefix each member.

There isn't, but there should be. IMO. 'with' should be banned. Implicit access to members of 'this' should also be banned. I always use explicit 'this->' in C++ and explicit 'this.' in D. It makes the code much easier to read.

You see, this is an interesting point. Not using "this." may lead to local bugs. The masking effected by "with" may lead to nonlocal bugs. The difference in risk is enormous. Andrei
May 17 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Rainer Deyke" <rainerd eldwood.com> wrote in message 
news:guqno8$2fci$1 digitalmars.com...
 Andrei Alexandrescu wrote:
 In a member function there's no need to prefix each member.

There isn't, but there should be. IMO. 'with' should be banned. Implicit access to members of 'this' should also be banned. I always use explicit 'this->' in C++ and explicit 'this.' in D. It makes the code much easier to read.

This is what I love about Ruby's member access. It's just like you suggest, but with " " prepended instead of "this." which IMO is much too clunky to require for something as common as accessing a member of the current instance. But other than that little quibble I love the idea.
May 17 2009
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei, I agree that "with" is dangerous when it shadows outer names (Python
designers have not added a "with" because of this).

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

Rainer Deyke:

 Implicit access to members of 'this' should also be banned.  I always
 use explicit 'this->' in C++ and explicit 'this.' in D.  It makes the
 code much easier to read.

I too usually add "this." in my D code to increase readability. But it's quite long (as "self." in Python), so the solution used by Ruby may be better: before instance attributes (Ruby also uses before class attributes, that are absent in D. D has static variables that are something different and more primitive). ------------------- Derek Parnell:
 int x, y;
 with (p as "somevery.long.struct.or.class[17].name") {
       y += p.x;
       ++p.x;
 }

I also use alias to create a shorter name, so it may be used an extension of the alias syntax (to allow to use {} to define where such alias exists. Also notice the "as" keyword, used in renamed imports too): int x, y; alias somevery.long.struct.or.class[17].name as s { y += p.x; ++p.x; } Bye, bearophile
May 18 2009
parent reply Leandro Lucarella <llucax gmail.com> writes:
bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

They did, but with different semantics =) It's used for RAII (I guess you already know that, but maybe other people don't). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------------
May 18 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Leandro Lucarella" <llucax gmail.com> wrote in message 
news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

They did, but with different semantics =) It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?
May 18 2009
next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Nick Sabalausky, el 18 de mayo a las 15:23 me escribiste:
 "Leandro Lucarella" <llucax gmail.com> wrote in message 
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

They did, but with different semantics =) It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?

I don't know C#'s "using" =) In Python, with calls a special method at the begining and some other special method at the end of the block: with lock: do_something() is like: lock.__enter__() try: do_something finally: lock.__exit__() Or something like that. I think you can use a special method to be called if an exception was raised (similar to scope(exit|failure|success)). You can also do something like: with file("some file") as f: x = f.read() to define an alias to a "temporary" object, so you can work with it. f.__enter__() does nothing and f.__exit__() closes the file. This is what I remember, for a full, authoritative, description: http://www.python.org/doc/2.5/whatsnew/pep-343.html -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ----------------------------------------------------------------------------
May 18 2009
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Nick Sabalausky:
 You mean like C#'s "using"? 

http://effbot.org/pyref/context-managers.htm http://www.python.org/dev/peps/pep-0343/ Bye, bearophile
May 18 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message 
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?

What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one. Andrei
May 18 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message 
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?

What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one. Andrei

http://msdn.microsoft.com/en-us/library/aa664736.aspx
May 18 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message 
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?

What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one. Andrei

http://msdn.microsoft.com/en-us/library/aa664736.aspx

I meant: "explain what were they sinking about when they designed this awful feature", not "explain this awful feature in detail". I know the feature, and that doesn't help its case. Andrei
May 18 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, May 18, 2009 at 1:14 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).


who explained that C# is cool - please explain this one.

Looks like using(Foo x = new Foo()) { // do stuff } It's basically equiv of { auto x = new Foo(); scope(exit) foo.Dispose; // do stuff } So it saves a little typing but is capable of less. scope(exit) is way cooler. Python has a similar feature to C#'s using. In Python it's called "with". http://effbot.org/zone/python-with-statement.htm

That's not an "equiv of". It's "completely missing the point of". Each "using" costs one new scope and one level of indentation which makes it non-scalable. Indentation is *expensive*. I think the C# folks missed the class when try/catch/finally showed with extensive examples just how expensive extra indentation is. Andrei
May 18 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, May 18, 2009 at 1:36 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 That's not an "equiv of". It's "completely missing the point of". Each
 "using" costs one new scope and one level of indentation which makes it
 non-scalable. Indentation is *expensive*. I think the C# folks missed the
 class when try/catch/finally showed with extensive examples just how
 expensive extra indentation is.

Oh. Is that the only thing that bothers you about it? That doesn't bother me much since it's basically for things you only want to hold on to for a short span. You should either do your business in a few lines of code and get out of there, or if you can't then make it a function. Anyway, if the indentation bugs you, you can always set emacs up not to indent on "using" blocks.

It's huge! In TDPL, as soon as I show the expansion of two scope(exit) statements, code became unreadable. No wonder today's software has so crappy error handling and state leaks: languages seem to make it as hard as possible to write correct transactional code. Andrei
May 18 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Andrei Alexandrescu wrote:
 Bill Baxter wrote:
 On Mon, May 18, 2009 at 1:36 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 That's not an "equiv of". It's "completely missing the point of". Each
 "using" costs one new scope and one level of indentation which makes it
 non-scalable. Indentation is *expensive*. I think the C# folks missed 
 the
 class when try/catch/finally showed with extensive examples just how
 expensive extra indentation is.

Oh. Is that the only thing that bothers you about it? That doesn't bother me much since it's basically for things you only want to hold on to for a short span. You should either do your business in a few lines of code and get out of there, or if you can't then make it a function. Anyway, if the indentation bugs you, you can always set emacs up not to indent on "using" blocks.

It's huge! In TDPL, as soon as I show the expansion of two scope(exit) statements, code became unreadable. No wonder today's software has so crappy error handling and state leaks: languages seem to make it as hard as possible to write correct transactional code. Andrei

Not to mention, C#'s implementation requires an object that implements IDisposable. This means the code that actually executes is highly non-local, and requires a fair bit of boilerplate. That makes 'using' even less maintainable. (This is also my complaint about using RAII for scope guards in C++.)
May 18 2009
prev sibling parent reply Joel Lucsy <jjlucsy gmail.com> writes:
Andrei Alexandrescu wrote:
 <SeeWebsiteForEmail erdani.org> wrote:
 using(Foo x = new Foo()) {
      // do stuff
 }

 It's basically equiv of

 {
     auto x = new Foo();
     scope(exit) foo.Dispose;
     // do stuff
 }

"using" costs one new scope and one level of indentation which makes it non-scalable. Indentation is *expensive*. I think the C# folks missed the class when try/catch/finally showed with extensive examples just how expensive extra indentation is.

You can mitigate this somewhat by realizing that multiple usings can be wrapped into only one indentation level. Like: using (Bar bar = new Bar()) using (Foo foo = new Foo()) using (Jim jim = new Jim()) { //do something } -- Joel Lucsy "The dinosaurs became extinct because they didn't have a space program." -- Larry Niven
May 19 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Joel Lucsy wrote:
 Andrei Alexandrescu wrote:
 <SeeWebsiteForEmail erdani.org> wrote:
 using(Foo x = new Foo()) {
      // do stuff
 }

 It's basically equiv of

 {
     auto x = new Foo();
     scope(exit) foo.Dispose;
     // do stuff
 }

"using" costs one new scope and one level of indentation which makes it non-scalable. Indentation is *expensive*. I think the C# folks missed the class when try/catch/finally showed with extensive examples just how expensive extra indentation is.

You can mitigate this somewhat by realizing that multiple usings can be wrapped into only one indentation level. Like: using (Bar bar = new Bar()) using (Foo foo = new Foo()) using (Jim jim = new Jim()) { //do something }

Thanks, that's a good point. (It's a limited option, though. My code uses scope() statements to do things transactionally (e.g. search Phobos for scope) and the pattern sometimes is to do some work, plant a scope(), then do some work, plan another, etc. This would be difficult with using().) Andrei
May 19 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Steven Schveighoffer wrote:
 On Mon, 18 May 2009 16:14:29 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message 
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).


What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one.

Had to look it up, never used it. Not sure it's that terrible, it looks to be the equivalent in D of: { scope C = new C(); ... } I suppose it's good in cases where you want to have somewhat manual memory management. Does seem poorly named though.

Or transactions, or locking, or similar things. One of the interesting uses of it that I've seen is in Rhino Mocks: using (Mocks.Ordered()) { everything in this block records expected calls where the order matters } but over here, order doesn't matter.
May 18 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, May 18, 2009 at 2:56 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Mon, May 18, 2009 at 1:36 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 That's not an "equiv of". It's "completely missing the point of". Each
 "using" costs one new scope and one level of indentation which makes it
 non-scalable. Indentation is *expensive*. I think the C# folks missed t=



 class when try/catch/finally showed with extensive examples just how
 expensive extra indentation is.

Oh. =A0Is that the only thing that bothers you about it? That doesn't bother me much since it's basically for things you only want to hold on to for a short span. =A0You should either do your business in a few lines of code and get out of there, or if you can't then make it a function. =A0 Anyway, if the indentation bugs you, you can always set emacs up not to indent on "using" blocks.

It's huge! In TDPL, as soon as I show the expansion of two scope(exit) statements, code became unreadable. No wonder today's software has so crappy error handling and state leaks: languages seem to make it as hard as possible to write correct transactional code.

I agree that scope(exit) is a more general solution that allows for more interesting tricks. I think I'm only disagreeing with you on the magnitude of the lameness. You can always create a new scope if you want one, but you can't remove a scope if it is defined to be a part of the construct. So to me it seems clear that not building the scope into the construct is the way to go. This is also a strike against D's current with(), which also forces a new scope whether you want it or not. --- In related news, scope(exit) is not without it's own issues. Mainly, this doesn't seem nice to me: void foo() { auto x =3D new Thing; scope(exit) x.doADance(); // bunch of code x =3D otherThing; // more code } This will happily doADance on otherThing instead of the original x when it exits. I'm guessing the C# using / Python with are safer wrt re-assignment, but I have not investigated this. Anyone know? --bb
May 18 2009
prev sibling parent reply BCS <none anon.com> writes:
Hello Andrei,

 BCS wrote:
 
 Hello Andrei,
 
 BCS wrote:
 
 Hello Andrei,
 
 dsimcha wrote:
 
 Absolutely not.  It's far too useful as syntactic sugar when
 working heavily with plain old data structs, and saves a lot of
 tedious repetition of the struct instance name.
 

use "s." as the prefix! I can't believe that's stopping you from getting work done!



 Make it a member function!
 


Andrei

how does that heplp you when you either don't have access to the type or don't want to add the code using the type to it module somelib; struct S { int x, y, z; } module someapp; import somelib; void fn(char[] str, S s) { with(s) { sscanf(str.ptr, "<%i, %i, %i>", &x, &z, &y); // I'm not adding this to S } }
May 17 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff5f598cba54ecba238c8 news.digitalmars.com...
 void fn(char[] str, S s)
 {
    with(s)
    {
         sscanf(str.ptr, "<%i, %i, %i>", &x, &z, &y); // I'm not adding 
 this to S
    }
 }

You don't really see that as an improvement over this do you?: void fn(char[] str, S s) { sscanf(str.ptr, "<%i, %i, %i>", &s.x, &s.z, &s.y); } If anything, the "with" version looks worse to me, and those three "s." are trivial.
May 17 2009
parent BCS <none anon.com> writes:
Hello Nick,

 "BCS" <none anon.com> wrote in message
 news:a6268ff5f598cba54ecba238c8 news.digitalmars.com...
 
 void fn(char[] str, S s)
 {
 with(s)
 {
 sscanf(str.ptr, "<%i, %i, %i>", &x, &z, &y); // I'm not adding
 this to S
 }
 }

void fn(char[] str, S s) { sscanf(str.ptr, "<%i, %i, %i>", &s.x, &s.z, &s.y); } If anything, the "with" version looks worse to me, and those three "s." are trivial.

I do like it over the full form: void someFn() { static void fn(char[] str, S s) { sscanf(str.ptr, "<%i, %i, %i>", &s.x, &s.z, &s.y); } fn(str); }
May 17 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 18 May 2009 16:14:29 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message  
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

It's used for RAII (I guess you already know that, but maybe other people don't).


What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one.

Had to look it up, never used it. Not sure it's that terrible, it looks to be the equivalent in D of: { scope C = new C(); ... } I suppose it's good in cases where you want to have somewhat manual memory management. Does seem poorly named though. -Steve
May 18 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, May 18, 2009 at 1:14 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Nick Sabalausky wrote:
 "Leandro Lucarella" <llucax gmail.com> wrote in message
 news:20090518141908.GB9277 burns.springfield.home...
 bearophile, el 18 de mayo a las 04:33 me escribiste:
 Andrei, I agree that "with" is dangerous when it shadows outer names
 (Python designers have not added a "with" because of this).

They did, but with different semantics =) It's used for RAII (I guess you already know that, but maybe other people don't).

You mean like C#'s "using"?

What a God awful feature. Honestly, "what were they sinking about?" People who explained that C# is cool - please explain this one.

Looks like using(Foo x = new Foo()) { // do stuff } It's basically equiv of { auto x = new Foo(); scope(exit) foo.Dispose; // do stuff } So it saves a little typing but is capable of less. scope(exit) is way cooler. Python has a similar feature to C#'s using. In Python it's called "with". http://effbot.org/zone/python-with-statement.htm --bb
May 18 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, May 18, 2009 at 1:36 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 That's not an "equiv of". It's "completely missing the point of". Each
 "using" costs one new scope and one level of indentation which makes it
 non-scalable. Indentation is *expensive*. I think the C# folks missed the
 class when try/catch/finally showed with extensive examples just how
 expensive extra indentation is.

Oh. Is that the only thing that bothers you about it? That doesn't bother me much since it's basically for things you only want to hold on to for a short span. You should either do your business in a few lines of code and get out of there, or if you can't then make it a function. Anyway, if the indentation bugs you, you can always set emacs up not to indent on "using" blocks. --bb
May 18 2009
prev sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Andrei Alexandrescu wrote:

 It is terrible. I can't believe it snuck under our nose for so long.

I wrote about that more than four years ago: http://www.digitalmars.com/d/archives/digitalmars/D/15653.html -manfred
May 18 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Manfred Nowak wrote:
 Andrei Alexandrescu wrote:
 
 It is terrible. I can't believe it snuck under our nose for so long.

I wrote about that more than four years ago: http://www.digitalmars.com/d/archives/digitalmars/D/15653.html

Very well put. I'm very sorry that costly mistake wasn't fixed at that time. Andrei
May 18 2009
prev sibling next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Andrei Alexandrescu Wrote:

 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }
 
 What can be said about such code? Nothing. If whatever has or will ever 
 have fields x or y or both, the names will bind to them; otherwise, 
 they'll bind to the locals. Non-local code dependency at its finest.
 
 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.
 
 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?
 
 
 Andrei

How about we keep in D's tradition and outlaw shadowing instead? I use "with" rarely, but appreciate it when I do.
May 17 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jason House wrote:
 Andrei Alexandrescu Wrote:
 
 I think "with" is a very dangerous feature due to the way it hides
  symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:
 
 int x, y; with (whatever) { y += x; ++x; }
 
 What can be said about such code? Nothing. If whatever has or will
 ever have fields x or y or both, the names will bind to them;
 otherwise, they'll bind to the locals. Non-local code dependency at
 its finest.
 
 Maintenance of any type that is being used with "with" becomes a
 very dangerous proposition because it can silently change meaning
 of code.
 
 I therefore submit that "with" is an extremely dangerous feature
 and should be removed from the language. What say you?
 
 
 Andrei

How about we keep in D's tradition and outlaw shadowing instead? I use "with" rarely, but appreciate it when I do.

That's a good alternative. At least if someone introduces a field name in the struct and that clashes with something you see, you'll have an error. Andrei
May 17 2009
prev sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Jason House wrote:
 Andrei Alexandrescu Wrote:
 
 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:

 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }

 What can be said about such code? Nothing. If whatever has or will ever 
 have fields x or y or both, the names will bind to them; otherwise, 
 they'll bind to the locals. Non-local code dependency at its finest.

 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.

 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?


 Andrei

How about we keep in D's tradition and outlaw shadowing instead? I use "with" rarely, but appreciate it when I do.

This. Just issue an error/warning if something in the with shadows something outside. That way, if the struct/class/template/whatever changes, affected code will be notified.
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Robert Fraser wrote:
 Jason House wrote:
 Andrei Alexandrescu Wrote:

 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular 
 reasoning utterly impossible:

 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }

 What can be said about such code? Nothing. If whatever has or will 
 ever have fields x or y or both, the names will bind to them; 
 otherwise, they'll bind to the locals. Non-local code dependency at 
 its finest.

 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.

 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?


 Andrei

How about we keep in D's tradition and outlaw shadowing instead? I use "with" rarely, but appreciate it when I do.

This. Just issue an error/warning if something in the with shadows something outside. That way, if the struct/class/template/whatever changes, affected code will be notified.

No warning, error! This is a great idea Jason. Andrei
May 17 2009
next sibling parent reply BCS <none anon.com> writes:
Hello Andrei,

 Robert Fraser wrote:
 
 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.
 


warning if it exist, error if used?
May 17 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
BCS wrote:
 Hello Andrei,
 
 Robert Fraser wrote:

 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.


warning if it exist, error if used?

I go with Walter's stance: either compiles or not. Warnings suck. Andrei
May 17 2009
parent reply BCS <none anon.com> writes:
Hello Andrei,

 BCS wrote:
 
 Hello Andrei,
 
 Robert Fraser wrote:
 
 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.
 



Andrei

warningd are optional and off by default.
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
BCS wrote:
 Hello Andrei,
 
 BCS wrote:

 Hello Andrei,

 Robert Fraser wrote:

 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.



Andrei

warningd are optional and off by default.

And that doesn't help either! Andrei
May 17 2009
parent reply Don <nospam nospam.com> writes:
Andrei Alexandrescu wrote:
 BCS wrote:
 Hello Andrei,

 BCS wrote:

 Hello Andrei,

 Robert Fraser wrote:

 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.



Andrei

warningd are optional and off by default.

And that doesn't help either! Andrei

If warnings exist, libraries must not do anything that creates a warning. They are NOT optional. Warnings suck.
May 18 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:gur1ec$18a$1 digitalmars.com...
 If warnings exist, libraries must not do anything that creates a warning. 
 They are NOT optional.

That's only true if a compiler (such as DMD) is only capable of treating warnings as errors.
May 18 2009
parent reply Don <nospam nospam.com> writes:
Nick Sabalausky wrote:
 "Don" <nospam nospam.com> wrote in message 
 news:gur1ec$18a$1 digitalmars.com...
 If warnings exist, libraries must not do anything that creates a warning. 
 They are NOT optional.

That's only true if a compiler (such as DMD) is only capable of treating warnings as errors.

No. Users complain if library code generates warnings. Because a user cannot make their code warning-free if the libraries they use are generating warnings.
May 18 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:gurkuo$17nv$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Don" <nospam nospam.com> wrote in message 
 news:gur1ec$18a$1 digitalmars.com...
 If warnings exist, libraries must not do anything that creates a 
 warning. They are NOT optional.

That's only true if a compiler (such as DMD) is only capable of treating warnings as errors.

No. Users complain if library code generates warnings. Because a user cannot make their code warning-free if the libraries they use are generating warnings.

They can if they use a prebuilt version of the library, a lib/a/dll.
May 18 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:guscm2$2jff$1 digitalmars.com...
 "Don" <nospam nospam.com> wrote in message 
 news:gurkuo$17nv$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Don" <nospam nospam.com> wrote in message 
 news:gur1ec$18a$1 digitalmars.com...
 If warnings exist, libraries must not do anything that creates a 
 warning. They are NOT optional.

That's only true if a compiler (such as DMD) is only capable of treating warnings as errors.

No. Users complain if library code generates warnings. Because a user cannot make their code warning-free if the libraries they use are generating warnings.

They can if they use a prebuilt version of the library, a lib/a/dll.

Warnings are optional built-in lint tools (kinda like how we already have a built-in doc tool, built-in code generation tool (ie, mixins), built-in profiling/code-coverage, etc). And it's pretty difficult to claim that lint tools are bad. So deciding that (optional) warnings are bad just because some people might get warnings from a non-pre-compiled lib and then bitch about it is a rather large case of "throwing away the baby with the bathwater". And even aside from pre-compiled lib's (which admittedly probably wouldn't work for template-using libs, although I consider that more a problem with the existing obj/lib formats than anything else), there are still other solutions that don't "throw away the baby with the bathwater". Like maybe a switch that only enables warnings for anything in the same package as "main". Or "-warn=this.package.only", or "-nowarn=tango", etc. And before anyone notices that I've filed a bug report in tango for a warning despite my "complaining about warnings in libs is silly" stance, I'll point out that I've filed bug reports for warnings in libs *only* because DMD refuses to allow warnings to actually be treated as warnings (or at least until bugzilla #2567 (with patch) gets taken care of). Yes, under current versions of DMD, fixing warnings are manditory for libs. But that's only because DMD's current handling of "warnings" is one hell of a bizarre anomoly (ie, In DMD, "warnings" are really "optional errors" at this point, *not* true warnings. And yes, *that* kind of so-called "warning" *is* a bad thing).
May 18 2009
parent Don <nospam nospam.com> writes:
Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message 
 news:guscm2$2jff$1 digitalmars.com...
 "Don" <nospam nospam.com> wrote in message 
 news:gurkuo$17nv$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Don" <nospam nospam.com> wrote in message 
 news:gur1ec$18a$1 digitalmars.com...
 If warnings exist, libraries must not do anything that creates a 
 warning. They are NOT optional.

warnings as errors.

cannot make their code warning-free if the libraries they use are generating warnings.


Warnings are optional built-in lint tools (kinda like how we already have a built-in doc tool, built-in code generation tool (ie, mixins), built-in profiling/code-coverage, etc). And it's pretty difficult to claim that lint tools are bad.

If they are standardised, they _are_ bad, because they become mandatory for libraries. If they're not standardised, no problem, it's just a third-party tool which you particular users find helpful in eliminating bugs; and demanding that a library support your third-party tool is unreasonable. Warnings can be categorised based on "probability that they indicate a bug", with a range from: (1) it almost always indicates a bug --> in this case, it should be an error. (2) it hardly ever indicates a bug --> in this case, it's useless at best, but in practice it's harmful. If there's anything in between, it indicates a weakness in that part of the language design. DMD's warnings are now extremely close to (1), I hope they can become errors soon. (Eg, leaving off a return statement in a function which doesn't contain asm statements is almost guaranteed to be a bug).
May 20 2009
prev sibling parent Spacen Jasset <spacenjasset yahoo.co.uk> writes:
BCS wrote:
 Hello Andrei,
 
 Robert Fraser wrote:

 This. Just issue an error/warning if something in the with shadows
 something outside. That way, if the struct/class/template/whatever
 changes, affected code will be notified.


warning if it exist, error if used?

It probably should be an error. Then though, you have the unfortunate thing whereby adding something to say struct X will shadow and generate a compile error, which you can only fix by: a) Not using with b) rename identifier in your sturct c) rename local variable I seem to remember some language (I think it's VB) supporting with that required a "." prefix in front of with enclosures. Like so: auto a = 0; with (foo) { a = 0; .a = 1; } This is a bit dangerous too though, in terms of typos.
May 18 2009
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Sun, 17 May 2009 20:56:14 -0500, Andrei Alexandrescu wrote:

 Andrei Alexandrescu Wrote:

 I think "with" is a very dangerous feature due to the way it hides 
 symbols.




 Jason House wrote:
 This. Just issue an error/warning if something in the with shadows 
 something outside. That way, if the struct/class/template/whatever 
 changes, affected code will be notified.


On Sun, 17 May 2009 20:56:14 -0500, Andrei Alexandrescu wrote:
 No warning, error!
 
 This is a great idea Jason.

Wow, that's they way I thought it already worked. I never use 'with' because of the reasons that Andrei has already cited, but if it doesn't trip such syntax-mines already then I'm even more glad that I haven't used it. So yes Jason, that idea has my support too ... though I still can't see me using the construct anytime soon. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 17 2009
prev sibling next sibling parent reply Georg Wrede <georg.wrede iki.fi> writes:
Andrei Alexandrescu wrote:
 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
     y += x;
     ++x;
 }
 
 What can be said about such code? Nothing. If whatever has or will ever 
 have fields x or y or both, the names will bind to them; otherwise, 
 they'll bind to the locals. Non-local code dependency at its finest.
 
 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.
 
 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?

Non-touch typers will riot.
May 17 2009
next sibling parent BCS <none anon.com> writes:
Hello Georg,

 Non-touch typers will riot.
 

Not a good reason as nobody cares about us (first person, plural, non inclusive of the second person (why can't English have a better set of pronouns?)).
May 17 2009
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Georg Wrede" <georg.wrede iki.fi> wrote in message 
news:guqdmn$1tks$2 digitalmars.com...
 Andrei Alexandrescu wrote:
 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?

Non-touch typers will riot.

I'm not a touch-typer, but I've never seen much of a point to "with". If I have to access a bunch of members of "foo.member.x.bar[17].fizzle", I'll just do "auto fizz = foo.member.x.bar[17].fizzle;" and use that, or put it into a function that takes a "typeof(fizze)", or do something else along those lines. I've yet to come across a case where something like that isn't perfectly sufficient.
May 17 2009
next sibling parent reply BCS <none anon.com> writes:
Hello Nick,

 "Georg Wrede" <georg.wrede iki.fi> wrote in message
 news:guqdmn$1tks$2 digitalmars.com...
 
 Andrei Alexandrescu wrote:
 
 I therefore submit that "with" is an extremely dangerous feature and
 should be removed from the language. What say you?
 


If I have to access a bunch of members of "foo.member.x.bar[17].fizzle", I'll just do "auto fizz = foo.member.x.bar[17].fizzle;" and use that, or put it into

that dosn't work if it's by value and is used as an Lvalue.
 a function that takes a "typeof(fizze)", or do something else along

like this? that looks... odd. void outer() { void inner(ref T t) { t.somthing; ... } inner(foo.member.x.bar[17].fizzle); }
 those lines. I've yet to come across a case where something like
 that isn't perfectly sufficient.
 

May 17 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"BCS" <none anon.com> wrote in message 
news:a6268ff5f5d8cba54f824da454 news.digitalmars.com...
 Hello Nick,

 I'm not a touch-typer, but I've never seen much of a point to "with".
 If I have to access a bunch of members of
 "foo.member.x.bar[17].fizzle", I'll just do "auto fizz = 
 foo.member.x.bar[17].fizzle;" and use that, or put it into

that dosn't work if it's by value and is used as an Lvalue.
 a function that takes a "typeof(fizze)", or do something else along

like this? that looks... odd. void outer() { void inner(ref T t) { t.somthing; ... } inner(foo.member.x.bar[17].fizzle); }
 those lines. I've yet to come across a case where something like
 that isn't perfectly sufficient.


Like I said, "or something along those lines". It all depends on the specific code. I just haven't ever had any specific case where I felt like I needed "with".
May 17 2009
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message 
 news:a6268ff5f5d8cba54f824da454 news.digitalmars.com...
 Hello Nick,

 I'm not a touch-typer, but I've never seen much of a point to "with".
 If I have to access a bunch of members of
 "foo.member.x.bar[17].fizzle", I'll just do "auto fizz = 
 foo.member.x.bar[17].fizzle;" and use that, or put it into

 a function that takes a "typeof(fizze)", or do something else along

void outer() { void inner(ref T t) { t.somthing; ... } inner(foo.member.x.bar[17].fizzle); }
 those lines. I've yet to come across a case where something like
 that isn't perfectly sufficient.


Like I said, "or something along those lines". It all depends on the specific code. I just haven't ever had any specific case where I felt like I needed "with".

I mainly use it for initialization of things: static S opCall(_x, _y) { S s; with(s) { x = _x; y = _y; happiness = null; } return s; }
May 17 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Robert Fraser" <fraserofthenight gmail.com> wrote in message 
news:guqpkf$2h49$2 digitalmars.com...
 I mainly use it for initialization of things:

 static S opCall(_x, _y)
 {
 S s;
 with(s)
 {
 x = _x;
 y = _y;
 happiness = null;
 }
 return s;
 }

For things like that I have a series of util mixins, for example: class Foo { int x; int y; char[] name; this(int x, int y, char[] name) { mixin(initMember!(x, y, name)); } } And even if I didn't, I've never considered the repeated "this." or "s.", etc, to be non-trivial enough to really be worth an extra language construct - and I'm normally a complete DRY-maniac.
May 17 2009
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Robert Fraser wrote:
 Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message 
 news:a6268ff5f5d8cba54f824da454 news.digitalmars.com...
 Hello Nick,

 I'm not a touch-typer, but I've never seen much of a point to "with".
 If I have to access a bunch of members of
 "foo.member.x.bar[17].fizzle", I'll just do "auto fizz = 
 foo.member.x.bar[17].fizzle;" and use that, or put it into

 a function that takes a "typeof(fizze)", or do something else along

void outer() { void inner(ref T t) { t.somthing; ... } inner(foo.member.x.bar[17].fizzle); }
 those lines. I've yet to come across a case where something like
 that isn't perfectly sufficient.


Like I said, "or something along those lines". It all depends on the specific code. I just haven't ever had any specific case where I felt like I needed "with".

I mainly use it for initialization of things: static S opCall(_x, _y) { S s; with(s) { x = _x; y = _y; happiness = null; } return s; }

Because of that, C# added the following syntax: new S { x = _x, y = _y, }; And I think that could replace "with" with no problem, because most of the time (or all of the time) you use it when initializing an object.
May 18 2009
parent bearophile <bearophileHUGS lycos.com> writes:
Ary Borenszweig:

 Because of that, C# added the following syntax:
 
 new S {
    x = _x,
    y = _y,
 };

Better to add named arguments to methods/functions and templates, it's a more general solution. Bye, bearophile
May 18 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Sun, May 17, 2009 at 9:53 PM, Robert Fraser
<fraserofthenight gmail.com> wrote:
 Nick Sabalausky wrote:
 "BCS" <none anon.com> wrote in message
 news:a6268ff5f5d8cba54f824da454 news.digitalmars.com...
 Hello Nick,

 I'm not a touch-typer, but I've never seen much of a point to "with".
 If I have to access a bunch of members of
 "foo.member.x.bar[17].fizzle", I'll just do "auto fizz =3D
 foo.member.x.bar[17].fizzle;" and use that, or put it into

that dosn't work if it's by value and is used as an Lvalue.
 a function that takes a "typeof(fizze)", or do something else along

like this? that looks... odd. void outer() { =A0 =A0void inner(ref T t) =A0 =A0{ =A0 =A0 =A0 =A0 t.somthing; =A0 =A0 =A0 =A0 ... =A0 =A0} =A0 =A0inner(foo.member.x.bar[17].fizzle); }
 those lines. I've yet to come across a case where something like
 that isn't perfectly sufficient.


Like I said, "or something along those lines". It all depends on the specific code. I just haven't ever had any specific case where I felt li=


 needed "with".

I mainly use it for initialization of things: static S opCall(_x, _y) { =A0 =A0 =A0 =A0S s; =A0 =A0 =A0 =A0with(s) =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0x =3D _x; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0y =3D _y; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0happiness =3D null; =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0return s; }

I find this to be the most convenient way to transform C++ constructors into struct static opCalls, so I've used it a lot in code I translated from C++. But the need there should be eliminated by giving structs real constructors instead of this static opCall kludge (I thought D2 had this already, actually...) One place 'with' is kinda cute is for configuring new objects in a fire & forget manner: with (new WindowWidget) { parent =3D mainWin; width =3D 100; height =3D 100; } That gives you something that works almost like named arguments. --- On a related note I do think some mechanism similar to C++'s "using" would be good to have that would let you bring particular namespaces into the direct lookup scope. However the same caveats apply -- it should never be possible to silently change the meaning of code that has "using foo.bar" by adding or removing something from module foo.bar. I think someone proposed allowing aliasing of dot like "alias foo.bar ." to achieve that -- kind of like alias this for structs. Anyway, I think if you're going to allow co-mingling of module scopes with top-level imports, then it should also be possible to limit the mingling to just inner scopes. --bb
May 18 2009
prev sibling next sibling parent reply Lester L. Martin II <lestermartin92 gmail.com> writes:
Andrei Alexandrescu Wrote:

 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }
 
 What can be said about such code? Nothing. If whatever has or will ever 
 have fields x or y or both, the names will bind to them; otherwise, 
 they'll bind to the locals. Non-local code dependency at its finest.
 
 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.
 
 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?
 
 
 Andrei

I agree with dsimcha. When you do this, do you consider how much code written in D actually uses this. I find it very, very useful. It's deprecation and further removal would take a huge hit on my code. What I would propose instead is that you can't modify variables outside of the scope, but only those that reside in the type whatever. In this case, you can't possibly change the variables outside of the with(whatever) scope, but you can modify anything that is in the type whatever, because this is how I believe it is mainly used. Deprecation of this feature should never happen. I doubt I and dsimcha will be the only unhappy coders. Lester L. Martin II
May 17 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lester L. Martin II wrote:
 Andrei Alexandrescu Wrote:
 
 I think "with" is a very dangerous feature due to the way it hides
  symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:
 
 int x, y; with (whatever) { y += x; ++x; }
 
 What can be said about such code? Nothing. If whatever has or will
 ever have fields x or y or both, the names will bind to them;
 otherwise, they'll bind to the locals. Non-local code dependency at
 its finest.
 
 Maintenance of any type that is being used with "with" becomes a
 very dangerous proposition because it can silently change meaning
 of code.
 
 I therefore submit that "with" is an extremely dangerous feature
 and should be removed from the language. What say you?
 
 
 Andrei

I agree with dsimcha. When you do this, do you consider how much code written in D actually uses this.

That code is a bomb waiting to explode.
 I find it very, very useful.

I believe you don't understand its extreme dangers.
 It's deprecation and further
 removal would take a huge hit on my code.

I understand.
 What I would propose
 instead is that you can't modify variables outside of the scope, but
 only those that reside in the type whatever. In this case, you can't
 possibly change the variables outside of the with(whatever) scope,
 but you can modify anything that is in the type whatever, because
 this is how I believe it is mainly used. Deprecation of this feature
 should never happen. I doubt I and dsimcha will be the only unhappy
 coders.

I think that restriction would be too harsh, as it would make with essentially an isolated bubble. Would you be ok with Jason's suggestion that shadowing will be flagged? Consider: struct Widget { //int wyda; } void main() { int wyda; Widget w; with (w) { wyda = 4; } } Would you agree to issue a compile-time error upon uncommenting the member of Widget. Andrei
May 17 2009
parent Lester L. Martin II <lestermartin92 gmail.com> writes:
Andrei Alexandrescu Wrote:

 Lester L. Martin II wrote:
 Andrei Alexandrescu Wrote:
 
 I think "with" is a very dangerous feature due to the way it hides
  symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:
 
 int x, y; with (whatever) { y += x; ++x; }
 
 What can be said about such code? Nothing. If whatever has or will
 ever have fields x or y or both, the names will bind to them;
 otherwise, they'll bind to the locals. Non-local code dependency at
 its finest.
 
 Maintenance of any type that is being used with "with" becomes a
 very dangerous proposition because it can silently change meaning
 of code.
 
 I therefore submit that "with" is an extremely dangerous feature
 and should be removed from the language. What say you?
 
 
 Andrei

I agree with dsimcha. When you do this, do you consider how much code written in D actually uses this.

That code is a bomb waiting to explode.
 I find it very, very useful.

I believe you don't understand its extreme dangers.
 It's deprecation and further
 removal would take a huge hit on my code.

I understand.
 What I would propose
 instead is that you can't modify variables outside of the scope, but
 only those that reside in the type whatever. In this case, you can't
 possibly change the variables outside of the with(whatever) scope,
 but you can modify anything that is in the type whatever, because
 this is how I believe it is mainly used. Deprecation of this feature
 should never happen. I doubt I and dsimcha will be the only unhappy
 coders.

I think that restriction would be too harsh, as it would make with essentially an isolated bubble. Would you be ok with Jason's suggestion that shadowing will be flagged? Consider: struct Widget { //int wyda; } void main() { int wyda; Widget w; with (w) { wyda = 4; } } Would you agree to issue a compile-time error upon uncommenting the member of Widget. Andrei

I understand that my suggestion makes with a bubble, but I always use and have always considered its use to mainly be for accessing the members of a variable and being able to act upon (set) them. That's why I believe that my idea was good. The shadowing idea will be fine. If I'm right, you can easily just escape the scope by placing the with statement in a new function if worst comes to worst and names match in almost every scope. Or it could automagically be made a member function.
May 17 2009
prev sibling next sibling parent reply BCS <none anon.com> writes:
Hello Andrei,

 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:
 
 int x, y;
 with (whatever)
 {
 y += x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

I'd be willing to go the half way solution of making accessing a shadowing symbol an error, resulting in (loudly) not being able to access either.
May 17 2009
parent reply Johan Granberg <lijat.meREM OVEgmail.com> writes:
BCS wrote:

 Hello Andrei,
 
 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:
 
 int x, y;
 with (whatever)
 {
 y += x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

I'd be willing to go the half way solution of making accessing a shadowing symbol an error, resulting in (loudly) not being able to access either.

I think this solution is a good idea but that removing or restricting anything more regarding with is a bad idea as others have pointed out. I'm using with quit a lot and it was one of thous things that attracted me to D (I get the feeling that D has a quite pragmatic way of looking at language features, if it's usefull lets have it unless it's harmfull to other parts of D, sort of.). On a similar note, Andrei, what is this spree of removing features? Ok some are obviously bad, imaginary types for example, but why remove other stuff such as commplex and with?
May 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Johan Granberg wrote:
 BCS wrote:
 
 Hello Andrei,

 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:

 int x, y;
 with (whatever)
 {
 y += x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

symbol an error, resulting in (loudly) not being able to access either.

I think this solution is a good idea but that removing or restricting anything more regarding with is a bad idea as others have pointed out. I'm using with quit a lot and it was one of thous things that attracted me to D (I get the feeling that D has a quite pragmatic way of looking at language features, if it's usefull lets have it unless it's harmfull to other parts of D, sort of.).

I personally still think it's a bad feature because it introduces long-distance coupling between symbols defined in two different places, both distinct from the place where the statement is used! Consider: import wyda; // defines symbol write import geeba; // defines struct S { ... } void main() { S s; with (s) { write(5); } } Machiavelly would jump in joy at such code. What did I achieve? I saved a few "s.". What did I lose? The ability so say anything, but absolutely anything on what the code does. If S changes, the code may compile and run, yet doing something completely different. The dependency is not between the code as seen and wyda or geeba. It's between wyda and geeba, intermediated by "with"! I mean, if one _planned_ to design a maximally damaging language feature one couldn't come up with something better. And for what? Because you find it convenient to not type "s." a few times or just go in the blessed object and define a member? Is _this_ what makes or breaks your productivity? And are you willing to pay the ability to do the feeblest reasoning about your code for that doubtful benefit? This is so against every single good notion of language design, I kid you not I feel my blood pressure rising only as I think of it. No amount of "but I find it useful" can protect this awful non-feature. It should be taken in the back and shot in the head, no trial. Shoot the lawyer too if it has one.
 On a similar note, Andrei, what is this spree of removing features? Ok some
 are obviously bad, imaginary types for example, but why remove other stuff
 such as commplex and with?

TDPL is coming out. This is quite literally the last chance to shed some old skin. Complex as a built-in does nothing of interest to anyone except a cute syntax for literals that nobody uses (how many remarkable complex literals could you imagine?) About "with"... see above before I die of a heart attack. The baroque "!<>=" operators became much more attractive since Walter said he's considering making them overloadable. On the other hand new features are coming, which I believe are "good skin". Narrowing integral conversions will go. Walter is working on a very cool scheme for inferring the range of expressions that makes casts unnecessary in many cases. Casts are a plague not only for safe code, but also for generic code that wants to be scalable and change-robust. The ease with which C and C++ allow losing state and the drowning necessity of integral casts in Java or C# are both extremes that I'm happy to see D avoid. Final switch works with enums and forces you to handle each and every value of the enum. Regular switch gets ranged cases by the syntax case a: .. case b: (I've always thought switch would be greatly helped by that). Static foreach might be making it too. Andrei
May 18 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

TDPL is coming out. This is quite literally the last chance to shed some old
skin.<

I think D2 will not fully stop evolving when TDPL is printed. I don't think D2 will be fully finished in few months.
 About "with"... see above before I die of a heart attack.<

Qualified imports are safer. And it's better for: import foo; to import in the current namespace only the "foo" module name.
 The baroque "!<>=" operators became much more attractive since Walter 
 said he's considering making them overloadable.

That makes them more flexible, but this doesn't make them more readable or nice looking :-)
 Walter is working on a very cool scheme for inferring the range of expressions
that makes casts unnecessary in many cases.<

I guess all we can do is Wait and Hope then? :-)
 Final switch works with enums and forces you to handle each and every value of
the enum.<

Do you mean like this? final switch (...) {...}
 Regular switch gets ranged cases by the syntax case a: .. case b: (I've always
thought switch would be greatly helped by that).<

Isn't a syntax like the following better? case a .. b: Or (much) better still, isn't it better to give a built-in syntax to something like your iota(), removing the special syntax of ranged foreach and such ranged switch case? Bye, bearophile
May 18 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 About "with"... see above before I die of a heart attack.<

Qualified imports are safer. And it's better for: import foo; to import in the current namespace only the "foo" module name.

Yeah, so for the sake of a feature intended to save some minor typing, I'm thrilled to introduce a feature requiring me a ton of typing.
 Do you mean like this? final switch (...) {...}

Yah. enum DeviceStatus { ready, busy, fail } ... void process(DeviceStatus status) { final switch (status) { case DeviceStatus.ready: ... case DeviceStatus.busy: ... case DeviceStatus.fail: ... } } If you then add a new value for DeviceStatus, the final switch won't compile.
 Regular switch gets ranged cases by the syntax case a: .. case b:
 (I've always thought switch would be greatly helped by that).<

Isn't a syntax like the following better? case a .. b: Or (much) better still, isn't it better to give a built-in syntax to something like your iota(), removing the special syntax of ranged foreach and such ranged switch case?

I think it's important to give switch a crack on properly optimizing its code. And case a .. b I just explained to Jarrett. Andrei
May 18 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

Yeah, so for the sake of a feature intended to save some minor typing, I'm
thrilled to introduce a feature requiring me a ton of typing.<

Please, be serious. You can have the same old behavour with just 2 added chars: import foo.*; I have discussed about something like this four times in the past.
 enum DeviceStatus { ready, busy, fail }
 ...
 void process(DeviceStatus status) {
     final switch (status) {
     case DeviceStatus.ready:
        ...
     case DeviceStatus.busy:
        ...
     case DeviceStatus.fail:
        ...
     }
 }
 If you then add a new value for DeviceStatus, the final switch
 won't compile.

1) I don't like this idea. I think that normal switches can behave like such final switches. 2) I'd like Walter to ask people before implement features. People here discuss about feature X for a week, that they think it is cool (or maybe even useful!), and then weeks later Walter implements feature Y that no one was asking for. This is not just wrong, it's silly. 3) If you want to add a second kind of switch, then let's add a truly safer one, with no fall-through, etc. We have discussed about this more than one time. See the switch of C#, for example.
I think it's important to give switch a crack on properly optimizing its code.<

Of course. That's why I was talking about a "built-in syntax". I am sure the compiler doesn't need rocket science to optimize a new syntax to say the same thing. I have done this in the ShedSkin compiler, and it's doable.
And case a .. b I just explained to Jarrett.<

1) The syntax you talk about isn't intuitive. This is bad. 2) Before introducing new syntax it's MUCH better to discuss it first, because what's intuitive for me can be not intuitive for you. So the best you can do is to ask for several ideas to people, and then use the one that is both logically sound, and intuitive for most people. This is how Python syntax is designed. And Python3 has less warts than most languages around. 3) In the past I have discussed how Ruby, Chapel and other languages solve this problem. A solution is to use a .. #b to denote that b is inclusive. You may not like this idea (and I am not sure I like it much), but it doesn't look so much worse than case a: .. case b: Thank you uncovering part of the future work of Walter, giving people 1 chance to cach design mistakes before they happen. Bye, bearophile
May 18 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 2) I'd like Walter to ask people before implement features. People
 here discuss about feature X for a week, that they think it is cool
 (or maybe even useful!), and then weeks later Walter implements
 feature Y that no one was asking for. This is not just wrong, it's
 silly.

To be brutally honest, I think many features discussed here are completely missing the point. Only a couple of posts ago, there were suggestions for alternate syntaxes for "with" that were not only useless, they added new keywords like they were up for grabs. If somebody wants to make "as" into a keyword, I'm liable to go postal. More to the point, I forgot the exact context, but recently a poster wrote a long message describing how he wants simultaneously two completely antagonistic features, to finally (and to his credit) courageously face the inevitable truth: that he had no idea what he really wanted. This is happening a lot in this group, just that most of the time it goes undetected. My perception is that the recently-added features are of good quality.
 3) In the past I have discussed how Ruby, Chapel
 and other languages solve this problem. A solution is to use a .. #b
 to denote that b is inclusive. You may not like this idea (and I am
 not sure I like it much), but it doesn't look so much worse than case
 a: .. case b:

It looks and is a million times worse. If you know D1 and see case 'a': .. case 'z': you pretty sure know exactly what's going on. If you know D1 but haven't been illuminated by the likes of Ruby and Chapel and see: case 'a' .. #'z': you're like, what the heck were they thinking about when they designed this ass-backward syntax? Andrei
May 18 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

Thank you for your answers.

To be brutally honest, I think many features discussed here are completely
missing the point.<

I know, most of the things I say are wrong or useless. I am not good at all. Yet, no one is perfect, and in the past I/we have discussed about several things that are badly designed in D.
Only a couple of posts ago, there were suggestions for alternate syntaxes for
"with" that were not only useless, they added new keywords like they were up
for grabs. If somebody wants to make "as" into a keyword, I'm liable to go
postal.<

That was me, and it was not a much serious proposal (I was not sure in the first place). But sometimes I don't like how much D relies on punctuation (like the semicolon in the middle of foreach). When I see a syntax like: alias foo bar; I often have troubles understanding if the new name is bar or foo. A syntax like: alias foo as bar; Is less ambigous. Now feel free to go postal :-) I have even troubles to remember if in the following syntax n is the number of rows or the number of columns: auto mat = new[][](n, m); Maybe I'm just dumb :-)
My perception is that the recently-added features are of good quality.<

This is probably thank to you too, because now there are two people designing things instead of just one.
 It looks and is a million times worse. If you know D1 and see
 case 'a': .. case 'z':
 you pretty sure know exactly what's going on. If you know D1 but haven't

 case 'a' .. #'z':
 you're like, what the heck were they thinking about when they designed this
ass-backward syntax?

The problem with a syntax like: case 'a': .. case 'z': Is that it's not general enough. The language clearly needs a syntax to specify ranges, both closed and open, that can iterated on, that support opIn_r, that can lazily iterated, that have a length, etc. Using a .. syntax inside the foreach, and another .. syntax inside the switch, and defining iota() into the std lib, doesn't like a good idea to me. It howls for a general language-wide solution. Bye, bearophile
May 18 2009
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
bearophile wrote:
 I am not good at all.

*shares some prozac*
May 18 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Robert Fraser wrote:
 bearophile wrote:
 I am not good at all.

*shares some prozac*

I'll have some too. I didn't mean to put bearophile or anyone down more than myself. The crude reality is that D does not have any real programming language expert on board. We are trying to do the best with what we have. Andrei
May 18 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:guscb3$2iqj$1 digitalmars.com...
 I have even troubles to remember if in the following syntax n is the 
 number of rows or the number of columns:
 auto mat = new[][](n, m);

That's just a matter of convention. Neither is inherently a row or a column.
May 18 2009
prev sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
bearophile wrote:
 When I see a syntax like:
 alias foo bar;
 I often have troubles understanding if the new name is bar or foo.
 A syntax like:
 alias foo as bar;
 Is less ambigous.
 Now feel free to go postal :-)

The more common suggestion is: alias bar = foo; This has the advantage of looking like renamed imports and not adding keywords. Additionally, C# uses similar syntax: using Name=My.Really.Long.Namespace.CollidingName;
May 18 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that. Bye, bearophile
May 18 2009
next sibling parent div0 <div0 users.sourceforge.net> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

bearophile wrote:
 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that. Bye, bearophile

That's rather nice. Would make coding after a few beers easier. - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFKEe/FT9LetA9XoXwRAoCuAJ9ns6O5kEMXVftt6GZP26wNTpCJxACgiSaN Q4ClZbiH5vGmlFHpBPnsSuc= =hJnG -----END PGP SIGNATURE-----
May 18 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that. Bye, bearophile

I'd love that. Andrei
May 18 2009
prev sibling next sibling parent Christopher Wright <dhasenan gmail.com> writes:
bearophile wrote:
 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that. Bye, bearophile

Why thank me? It's been batted around a few times, and it was not my suggestion originally.
May 18 2009
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Mon, 18 May 2009 19:24:13 -0400, bearophile wrote:

 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that.

But does that mean 'when I write "bar" I really mean "foo"' or visa versa? Just pointing out that the '=' sign doesn't really automatically make it fully intuitive. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 18 2009
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:2m4gnylh4ggc.1hhjynllwweim.dlg 40tude.net...
 On Mon, 18 May 2009 19:24:13 -0400, bearophile wrote:

 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

This is acceptable, thank you :-) Now I'd like to know what others think about that.

But does that mean 'when I write "bar" I really mean "foo"' or visa versa? Just pointing out that the '=' sign doesn't really automatically make it fully intuitive.

It makes it consistent with "auto foo = bar;" which is a big improvement in intuitiveness.
May 19 2009
parent Chris Mueller <ruun.net googlemail.com> writes:
Nick Sabalausky schrieb:
 "Derek Parnell" <derek psych.ward> wrote in message 
 news:2m4gnylh4ggc.1hhjynllwweim.dlg 40tude.net...
 On Mon, 18 May 2009 19:24:13 -0400, bearophile wrote:

 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

Now I'd like to know what others think about that.

Just pointing out that the '=' sign doesn't really automatically make it fully intuitive.

It makes it consistent with "auto foo = bar;" which is a big improvement in intuitiveness.

I would also welcome this change. Like someone here already mentioned it's also consistent with renaming imports, which has the same syntax. import io = std.stdio; Chris
May 18 2009
prev sibling parent Christopher Wright <dhasenan gmail.com> writes:
Derek Parnell wrote:
 On Mon, 18 May 2009 19:24:13 -0400, bearophile wrote:
 
 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

Now I'd like to know what others think about that.

But does that mean 'when I write "bar" I really mean "foo"' or visa versa? Just pointing out that the '=' sign doesn't really automatically make it fully intuitive.

It would work like assignments and renamed imports. Since when did you make an assignment in D where the right hand side was modified according to the value of the left hand side? It's not immediately obvious to someone who hasn't programmed yet, necessarily, but to someone even vaguely familiar with any modern programming language, there is one obvious meaning.
May 19 2009
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

I can add this too: typedef Bar = Foo; This changes in typedef and alias can solve two of the small problems I have with D. Let's see if Walter accepts such ideas. (In the last days two more ideas have floated in this newsgroup: disallowing floating point literals with nothing before the point like ".57", and making "with" safer). Such small improvements pile up. Bye, bearophile
May 20 2009
parent KennyTM~ <kennytm gmail.com> writes:
bearophile wrote:
 Christopher Wright:
 The more common suggestion is:
 alias bar = foo;

I can add this too: typedef Bar = Foo; This changes in typedef and alias can solve two of the small problems I have with D. Let's see if Walter accepts such ideas. (In the last days two more ideas have floated in this newsgroup: disallowing floating point literals with nothing before the point like ".57", and making "with" safer). Such small improvements pile up. Bye, bearophile

typedef int MyInt = 1;
May 20 2009
prev sibling parent Yigal Chripun <yigal100 gmail.com> writes:
Andrei Alexandrescu wrote:
 To be brutally honest, I think many features discussed here are 
 completely missing the point. Only a couple of posts ago, there were 
 suggestions for alternate syntaxes for "with" that were not only 
 useless, they added new keywords like they were up for grabs. If 
 somebody wants to make "as" into a keyword, I'm liable to go postal. 
 More to the point, I forgot the exact context, but recently a poster 
 wrote a long message describing how he wants simultaneously two 
 completely antagonistic features, to finally (and to his credit) 
 courageously face the inevitable truth: that he had no idea what he 
 really wanted. This is happening a lot in this group, just that most of 
 the time it goes undetected.
 

 Andrei

we don't need any new syntax to get rid of with. most of the time you use it like (for example): for (int i = 0; i < 10; ++i) { with (myLongVar[i].myLongMember.MylongOtherMember) { myLongMethod(); } } so why not allow: for (int i = 0; i < 10; ++i) { alias myLongVar[i].myLongMember.MylongOtherMember tempSymbol; tempSymbol.myLongMethod(); } this doesn't add any new syntax
May 18 2009
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Mon, 18 May 2009 14:33:29 -0400, bearophile wrote:

 3) If you want to add a second kind of switch, then let's
    add a truly safer one, with no fall-through, etc.

**WARNING** an off-topic aside follows ... The next version of the Euphoria programming language has implemented 'switch'. The language only had 'if-elsif-' constructs before. The new 'switch' has this syntax ... 'switch' ['with fallthru'] 'do' 'case' EXPRESSION 'then' STATEMENTS [( 'break' | 'fallthru')] . . . 'end' 'switch' Yeah, I know is not a punctuation-heavy language like D, but get over that for now. The point is that by default the cases do not fallthru. If you want cases to fallthru by default you need to add the 'with fallthru' qualifier. Furthermore, each case can have 'break' to explicitly prevent it falling thru to the next case, or 'fallthru' to explicitly cause it to fall thru to the next case. If you have neither, then it does the default action indicated on the 'switch' line. procedure classify(char c) write("You passed ") switch c do case '#' then writeln("a hash sign.") case in "012345679" then writeln("a digit.") case 'A' to 'Z', 'a' to 'z' then writeln("an ASCII character.") case '.', ',', ':', ';', '!', '?' then writeln("a punctuation mark.") case else writeln("quite a character!") end switch end procedure -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 18 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Mon, May 18, 2009 at 1:46 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Final switch works with enums and forces you to handle each and every value
 of the enum. Regular switch gets ranged cases by the syntax case a: .. case
 b: (I've always thought switch would be greatly helped by that).

Kind of an odd syntax. Why not "case a .. b:"? Parsing issues?

It's consistency. Everywhere in the language a .. b implies b is excluded. In a switch you want to include b. So I reflected that in the syntax. In fact, I confess I'm more proud than I should be about that little detail.
 Static foreach might be making it too.

That'd be a nice addition. Especially with __traits returning arrays/tuples, it'd be an alternative to CTFE (shudder) or template recursion.

Yah, can't wait. Andrei
May 18 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, May 18, 2009 at 10:46 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Johan Granberg wrote:
 BCS wrote:

 Hello Andrei,

 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:

 int x, y;
 with (whatever)
 {
 y += x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

shadowing symbol an error, resulting in (loudly) not being able to access either.

anything more regarding with is a bad idea as others have pointed out. I'm using with quit a lot and it was one of thous things that attracted me to D (I get the feeling that D has a quite pragmatic way of looking at language features, if it's usefull lets have it unless it's harmfull to other parts of D, sort of.).

long-distance coupling between symbols defined in two different places, both distinct from the place where the statement is used! Consider: import wyda; // defines symbol write import geeba; // defines struct S { ... } void main() { S s; with (s) { write(5); } } Machiavelly would jump in joy at such code. What did I achieve? I saved a few "s.". What did I lose? The ability so say anything, but absolutely anything on what the code does.

Shouldn't the feature just follow the same rules as module imports do? If I say import foo; import bar; void main() { write(5); } It's fine as long as foo and bar don't both define bar. Why shouldn't the same scope resolution mechanism not apply to with? So in your example write(5) is fine as long as S and some module don't both define a write(). I think that's what others were saying in the other thread, too. Makes things more consistent too. Given that do you still object to with() so vehemently?

I'd be happy if "with" were consistent in the way you describe. Nice idea! Andrei
May 18 2009
parent Georg Wrede <georg.wrede iki.fi> writes:
Andrei Alexandrescu wrote:
 Bill Baxter wrote:
 On Mon, May 18, 2009 at 10:46 AM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 Johan Granberg wrote:
 BCS wrote:

 Hello Andrei,

 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:

 int x, y;
 with (whatever)
 {
 y += x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

shadowing symbol an error, resulting in (loudly) not being able to access either.

anything more regarding with is a bad idea as others have pointed out. I'm using with quit a lot and it was one of thous things that attracted me to D (I get the feeling that D has a quite pragmatic way of looking at language features, if it's usefull lets have it unless it's harmfull to other parts of D, sort of.).

long-distance coupling between symbols defined in two different places, both distinct from the place where the statement is used! Consider: import wyda; // defines symbol write import geeba; // defines struct S { ... } void main() { S s; with (s) { write(5); } } Machiavelly would jump in joy at such code. What did I achieve? I saved a few "s.". What did I lose? The ability so say anything, but absolutely anything on what the code does.

Shouldn't the feature just follow the same rules as module imports do? If I say import foo; import bar; void main() { write(5); } It's fine as long as foo and bar don't both define bar. Why shouldn't the same scope resolution mechanism not apply to with? So in your example write(5) is fine as long as S and some module don't both define a write(). I think that's what others were saying in the other thread, too. Makes things more consistent too. Given that do you still object to with() so vehemently?

I'd be happy if "with" were consistent in the way you describe. Nice idea!

Then we could have "an implicit with" in effect all the time! I.e., every time i use 'write', and there's no ambiguity, I wouldn't have to write foo.write or bar.write. Saves a lot of ink! Yessss. And this should not be hard to implement at all. Except that code would then become hard to analyze. End result: using 's.' really isn't such a bad alternative.
May 18 2009
prev sibling next sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Jarrett Billingsley wrote:
 it'd be an alternative to CTFE (shudder)

Why shudder? CTFE has familiar syntax (the syntax of the runtime language) and, I've found, less bugs in general.
May 18 2009
prev sibling parent Johan Granberg <lijat.meREM OVEgmail.com> writes:
Andrei Alexandrescu wrote:
 I personally still think it's a bad feature because it introduces
 long-distance coupling between symbols defined in two different places,
 both distinct from the place where the statement is used! Consider:
 
 import wyda;  // defines symbol write
 import geeba; // defines struct S { ... }
 
 void main()
 {
     S s;
     with (s) {
        write(5);
     }
 }
 
 Machiavelly would jump in joy at such code. What did I achieve? I saved
 a few "s.". What did I lose? The ability so say anything, but absolutely
 anything on what the code does. 

I understand the problem you are pointing out even if I don't belive it's a significant issue. The problem with your assumption that it saves a few "s." is that where I usualy use it is in cases like this. with(listofdecentlysizedstructs[i].vector3d){ return x*x+y*y+z*z; } Maybe not an ideal example, usualy I have several lines of math algorithms or physics formula in the with scope. The gain here is both that I dont have to type long variable names (could be solved with an alias maybe) but more importantly it allows me to keep pysics and math formula close to the form they have in math or pysics. For example writing x y and z for the parts of some point I'm currently working on instead of p[i].x p[i].y and p[i].z can in a formula with lots of them make the code easier to read. For a single use of symbols I see no important use of the with statement.
May 19 2009
prev sibling next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sun, 17 May 2009 19:33:35 -0500, Andrei Alexandrescu wrote:

 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }

I guess the reason for using with() is to avoid typing repetitive stuff. Would this work instead ... int x, y; with (p as "somevery.long.struct.or.class[17].name") { y += p.x; ++p.x; } -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 17 2009
next sibling parent reply grauzone <none example.net> writes:
Derek Parnell wrote:
 On Sun, 17 May 2009 19:33:35 -0500, Andrei Alexandrescu wrote:
 
 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:

 int x, y;
 with (whatever)
 {
      y += x;
      ++x;
 }


I agree.
 I guess the reason for using with() is to avoid typing repetitive stuff.
 Would this work instead ...
 
 
  int x, y;
  with (p as "somevery.long.struct.or.class[17].name")
  {
       y += p.x;
       ++p.x;
  }
 

You could as well use auto and a block without statement before it to set the scope. But that'd look kind of ugly. A block without statement looks like you forgot an if. Here's another simple fix for with(); int x, y; with (whatever) { .y += x; //.y references this is whatever.y ++x; //x references local scope }
May 17 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"grauzone" <none example.net> wrote in message 
news:guqrj2$2l7h$2 digitalmars.com...
 Here's another simple fix for with();

 int x, y;
 with (whatever)
 {
       .y += x; //.y references this is whatever.y
       ++x;     //x references local scope
 }

That already means global scope.
May 18 2009
parent reply grauzone <none example.net> writes:
Nick Sabalausky wrote:
 "grauzone" <none example.net> wrote in message 
 news:guqrj2$2l7h$2 digitalmars.com...
 Here's another simple fix for with();

 int x, y;
 with (whatever)
 {
       .y += x; //.y references this is whatever.y
       ++x;     //x references local scope
 }

That already means global scope.

Yes, but who uses that anyway?
May 18 2009
parent Christopher Wright <dhasenan gmail.com> writes:
grauzone wrote:
 Nick Sabalausky wrote:
 "grauzone" <none example.net> wrote in message 
 news:guqrj2$2l7h$2 digitalmars.com...
 Here's another simple fix for with();

 int x, y;
 with (whatever)
 {
       .y += x; //.y references this is whatever.y
       ++x;     //x references local scope
 }

That already means global scope.

Yes, but who uses that anyway?

There's that perennial annoyance that class methods with a given name hide free functions of the same name, even if they are not covariant. This crops up a lot with toString, and the fix is to prepend a dot to the invocation.
May 18 2009
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Derek Parnell wrote:
 
 I guess the reason for using with() is to avoid typing repetitive stuff.
 Would this work instead ...
 
 
  int x, y;
  with (p as "somevery.long.struct.or.class[17].name")
  {
       y += p.x;
       ++p.x;
  }

{ ref p = somevery.long.struct.or.class[17].name; y += p.x; ++p.x; }
May 18 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Sean Kelly:

 {
      ref p = somevery.long.struct.or.class[17].name;
      y += p.x;
      ++p.x;
 }

{ alias somevery.long.struct.or.class[17].name p; y += p.x; ++p.x; } Or: { alias somevery.long.struct.or.class[17].name as p; y += p.x; ++p.x; } Or nicer: alias somevery.long.struct.or.class[17].name as p { y += p.x; ++p.x; } Bye, bearophile
May 18 2009
parent Derek Parnell <derek psych.ward> writes:
On Mon, 18 May 2009 12:59:08 -0400, bearophile wrote:

 Or nicer:
 
 alias somevery.long.struct.or.class[17].name as p {
      y += p.x;
      ++p.x;
 }

Yeah, that's nice too. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 18 2009
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Mon, 18 May 2009 09:55:42 -0700, Sean Kelly wrote:

 Derek Parnell wrote:
 
 I guess the reason for using with() is to avoid typing repetitive stuff.
 Would this work instead ...
 
  int x, y;
  with (p as "somevery.long.struct.or.class[17].name")
  {
       y += p.x;
       ++p.x;
  }

{ ref p = somevery.long.struct.or.class[17].name; y += p.x; ++p.x; }

Yes that would work too, and probably better code generation too. The difference being that my suggestion is a compile-time behaviour and yours is a run time behaviour. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
May 18 2009
prev sibling next sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Andrei Alexandrescu wrote:
 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
     y += x;
     ++x;
 }
 
 What can be said about such code? Nothing. If whatever has or will ever 
 have fields x or y or both, the names will bind to them; otherwise, 
 they'll bind to the locals. Non-local code dependency at its finest.
 
 Maintenance of any type that is being used with "with" becomes a very 
 dangerous proposition because it can silently change meaning of code.
 
 I therefore submit that "with" is an extremely dangerous feature and 
 should be removed from the language. What say you?

I agree, "with" makes code difficult to read. If one really wants to avoid typing, just use alias: alias my.very.long.string.of.symbols x; a = x.foo; x.foo = b; This works with lvalues as well. -Lars
May 18 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Lars T. Kyllingstad:

 f one really wants to avoid typing, just use alias:
     alias my.very.long.string.of.symbols x;
     a = x.foo;
     x.foo = b;

See my suggestion (where there's a p instead of s: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=90439 Bye, bearophile
May 18 2009
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
bearophile wrote:
 Lars T. Kyllingstad:
 
 f one really wants to avoid typing, just use alias:
     alias my.very.long.string.of.symbols x;
     a = x.foo;
     x.foo = b;

See my suggestion (where there's a p instead of s: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=90439 Bye, bearophile

Sorry, I didn't see that you had already made the suggestion. I don't think there is any need to extend the alias syntax, though. If you only want the alias to work in a limited scope, just enclose it in one: int x, y; { alias another.very.long.name s; y += s.x; s.x = x; } s.x = 1; // Doesn't work, s is not in scope. -Lars
May 18 2009
prev sibling next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
Andrei Alexandrescu wrote:

 I therefore submit that "with" is an extremely dangerous feature and  
 should be removed from the language. What say you?

I say 'with' is useful, but (as you say) dangerous. I believe this could be fixed by requiring an alias inside the parentheses. This way, code would look like this: with (alias foo.bar baz) { baz.x = y; } -- Simen
May 18 2009
prev sibling next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Andrei Alexandrescu wrote:
 I think "with" is a very dangerous feature due to the way it hides 
 symbols. It essentially makes the feeblest attempt at modular reasoning 
 utterly impossible:
 
 int x, y;
 with (whatever)
 {
     y += x;
     ++x;
 }

"with" is a useless feature and a waste of a keyword. I'd love to get rid of it.
May 18 2009
parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 18 May 2009 20:45:26 +0400, Sean Kelly <sean invisibleduck.org> wrote:

 Andrei Alexandrescu wrote:
 I think "with" is a very dangerous feature due to the way it hides  
 symbols. It essentially makes the feeblest attempt at modular reasoning  
 utterly impossible:
  int x, y;
 with (whatever)
 {
     y += x;
     ++x;
 }

"with" is a useless feature and a waste of a keyword. I'd love to get rid of it.

Same here. I don't remember myself using it ever.
May 18 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, May 18, 2009 at 1:46 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 Final switch works with enums and forces you to handle each and every value
 of the enum. Regular switch gets ranged cases by the syntax case a: .. case
 b: (I've always thought switch would be greatly helped by that).

Kind of an odd syntax. Why not "case a .. b:"? Parsing issues?
 Static foreach might be making it too.

That'd be a nice addition. Especially with __traits returning arrays/tuples, it'd be an alternative to CTFE (shudder) or template recursion.
May 18 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Mon, May 18, 2009 at 10:46 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Johan Granberg wrote:
 BCS wrote:

 Hello Andrei,

 I think "with" is a very dangerous feature due to the way it hides
 symbols. It essentially makes the feeblest attempt at modular
 reasoning utterly impossible:

 int x, y;
 with (whatever)
 {
 y +=3D x;
 ++x;
 }

 Maintenance of any type that is being used with "with" becomes a very
 dangerous proposition because it can silently change meaning of code.

I'd be willing to go the half way solution of making accessing a shadowing symbol an error, resulting in (loudly) not being able to access either.

I think this solution is a good idea but that removing or restricting anything more regarding with is a bad idea as others have pointed out. I'm using with quit a lot and it was one of thous things that attracted =


 to D (I get the feeling that D has a quite pragmatic way of looking at
 language features, if it's usefull lets have it unless it's harmfull to
 other parts of D, sort of.).

I personally still think it's a bad feature because it introduces long-distance coupling between symbols defined in two different places, b=

 distinct from the place where the statement is used! Consider:

 import wyda; =A0// defines symbol write
 import geeba; // defines struct S { ... }

 void main()
 {
 =A0 S s;
 =A0 with (s) {
 =A0 =A0 =A0write(5);
 =A0 }
 }

 Machiavelly would jump in joy at such code. What did I achieve? I saved a
 few "s.". What did I lose? The ability so say anything, but absolutely
 anything on what the code does.

Shouldn't the feature just follow the same rules as module imports do? If I say import foo; import bar; void main() { write(5); } It's fine as long as foo and bar don't both define bar. Why shouldn't the same scope resolution mechanism not apply to with? So in your example write(5) is fine as long as S and some module don't both define a write(). I think that's what others were saying in the other thread, too. Makes things more consistent too. Given that do you still object to with() so vehemently? --bb If S changes, the code may compile and run,
 yet doing something completely different. The dependency is not between t=

 code as seen and wyda or geeba. It's between wyda and geeba, intermediate=

 by "with"! I mean, if one _planned_ to design a maximally damaging langua=

 feature one couldn't come up with something better. And for what? Because
 you find it convenient to not type "s." a few times or just go in the
 blessed object and define a member? Is _this_ what makes or breaks your
 productivity? And are you willing to pay the ability to do the feeblest
 reasoning about your code for that doubtful benefit?

 This is so against every single good notion of language design, I kid you
 not I feel my blood pressure rising only as I think of it. No amount of "=

 I find it useful" can protect this awful non-feature. It should be taken =

 the back and shot in the head, no trial. Shoot the lawyer too if it has o=

 On a similar note, Andrei, what is this spree of removing features? Ok
 some
 are obviously bad, imaginary types for example, but why remove other stu=


 such as commplex and with?

TDPL is coming out. This is quite literally the last chance to shed some =

 skin. Complex as a built-in does nothing of interest to anyone except a c=

 syntax for literals that nobody uses (how many remarkable complex literal=

 could you imagine?) About "with"... see above before I die of a heart
 attack.

 The baroque "!<>=3D" operators became much more attractive since Walter s=

 he's considering making them overloadable.

 On the other hand new features are coming, which I believe are "good skin=

 Narrowing integral conversions will go. Walter is working on a very cool
 scheme for inferring the range of expressions that makes casts unnecessar=

 in many cases. Casts are a plague not only for safe code, but also for
 generic code that wants to be scalable and change-robust. The ease with
 which C and C++ allow losing state and the drowning necessity of integral
 casts in Java or C# are both extremes that I'm happy to see D avoid.

 Final switch works with enums and forces you to handle each and every val=

 of the enum. Regular switch gets ranged cases by the syntax case a: .. ca=

 b: (I've always thought switch would be greatly helped by that).

 Static foreach might be making it too.


 Andrei

May 18 2009
prev sibling next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, May 18, 2009 at 3:29 PM, Robert Fraser
<fraserofthenight gmail.com> wrote:
 Jarrett Billingsley wrote:
 it'd be an alternative to CTFE (shudder)

Why shudder? CTFE has familiar syntax (the syntax of the runtime language) and, I've found, less bugs in general.

It's extremely difficult to make CTFE functions that work. The compiler often coughs on seemingly-legal code, sometimes due to bugs. The biggest issue with developing CTFE functions is that if something does go wrong during CTFE, all you get is a message along the lines of "function X can't be evaluated at compile time", with no indication as to _why_ it couldn't, no stack trace etc. There's also no means of outputting debugging statements during CTFE. At least with templates I have pragma(msg). CTFE is also mainly useful for building up string mixins, but since everything inside a CTFE function has to be code that can be executed at runtime as well, you forgo some really useful metaprogramming features that are native to templates, like pattern matching. So it ends up being convenient in simple cases (i.e. given a list of names, generate a bunch of almost-identical declarations for them), but not in more complex ones. Not to mention it's much slower than template instantiation and eats memory for lunch.
May 18 2009
parent BCS <ao pathlink.com> writes:
Reply to Jarrett,

 Not to mention it's much slower than template instantiation and eats
 memory for lunch
 

Template instantiation eats memory for breakfast lunch and dinner, plus a few snack in between (it adds a symbol table entry of anything you do) and is not much, if any, faster.
May 18 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, May 18, 2009 at 1:57 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:

 of the enum. Regular switch gets ranged cases by the syntax case a: ..
 case
 b: (I've always thought switch would be greatly helped by that).

Kind of an odd syntax. =A0Why not "case a .. b:"? =A0Parsing issues?

It's consistency. Everywhere in the language a .. b implies b is excluded=

 In a switch you want to include b. So I reflected that in the syntax. In
 fact, I confess I'm more proud than I should be about that little detail.

Well after all this discussion, I think I like your syntax after all :P In fact, I might be inclined to use it in MiniD. It already has ranged cases of the form "case a .. b:" but the inconsistency between it being inclusive and slices being inclusive has never sat well with me.
May 18 2009