www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Neat trick - 'with' and unnamed objects + 'with' proposals

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
I just discovered this little trick that I think is way cool.
You can use 'with' in combination with an anonymous object to set 
attributes on that object without having to bother giving it a name or a 
variable.


with(new someGUIWidget(myParent)) {
    shown = true;
    focusable = false;
}

That's really nifty for GUI code.

This could be even more useful if there were some kind of 'this' for 
'with' blocks.  Then you could also call non-member functions.

with(new someGUIWidget(myParent)) {
    shown = true;
    focusable = false;
    some_global_function(this);
}

Or perhaps analogous to how constructors are called 'this()' and have a 
'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
in a class wouldn't be shadowed:

with(new someGUIWidget(myParent)) {
    some_global_function(with);
}

And even cooler would be if you could have a 'with-expression' that just 
evaluates to the thing in the parens:

auto obj = with(new someGUIWidget(myParent))
{
    shown = true;
    focusable = false;
    some_global_function(this);
};


Sometimes I've seen people try to make APIs in C++ where all the 
attribute setters return the object so that property setting can be 
chained, like:

      myObject.set_focusable(true).set_shown(true);

Presumably the objective is to avoid repeating the name of the object a 
lot.  But that never works out too well, because making every mutator 
return a pointer to 'this' is just not so practical in the end, and 
forcing every property setting operation to use function call syntax is 
also not so great.

--bb
Apr 23 2007
next sibling parent reply "Denis Golovan" <denis remove.me.azovprom.com> writes:
 Or perhaps analogous to how constructors are called 'this()' and have a
 'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
 in a class wouldn't be shadowed:
+1. That feature is useful sometimes.
 --bb 
Apr 24 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Denis Golovan wrote:
 Or perhaps analogous to how constructors are called 'this()' and have a
 'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
 in a class wouldn't be shadowed:
+1. That feature is useful sometimes.
You say "is" as if it exists in some other language that you've used? Does it? And if so what's the syntax? --bb
Apr 24 2007
next sibling parent Max Samukha <samukha voliacable.com> writes:
On Tue, 24 Apr 2007 22:03:07 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

Denis Golovan wrote:
 Or perhaps analogous to how constructors are called 'this()' and have a
 'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
 in a class wouldn't be shadowed:
+1. That feature is useful sometimes.
You say "is" as if it exists in some other language that you've used? Does it? And if so what's the syntax? --bb
don't provide a way to call global (and local, I guess) functions with 'this'. http://community.bartdesmet.net/blogs/bart/archive/2006/12/04/C_2300_-3.0-Feature-Focus-_2D00_-Part-2-_2D00_-Object-Initializers.aspx
Apr 24 2007
prev sibling parent eao197 <eao197 intervale.ru> writes:
On Tue, 24 Apr 2007 17:03:07 +0400, Bill Baxter  =

<dnewsgroup billbaxter.com> wrote:

 Denis Golovan wrote:
 Or perhaps analogous to how constructors are called 'this()' and hav=
e a
 'this' pointer, we'd have a 'with' pointer so that the meaning of  =
 'this' in a class wouldn't be shadowed:
+1. That feature is useful sometimes.
You say "is" as if it exists in some other language that you've used? =
=
 Does it? And if so what's the syntax?
Such behaviour can easily be implemented in Ruby. This is very simple = demonstration: class Demo attr_reader :shown attr_reader :focused end class AnotherDemo attr_reader :title end def some_global_function( obj ) p obj end def with( obj, &blk ) class <<obj def with; self; end end begin obj.instance_eval &blk ensure class <<obj remove_method( :with ) end end obj end d =3D with( Demo.new ) { shown =3D false focused =3D true some_global_function( with ) } a =3D with( AnotherDemo.new ) { title =3D 'Hello, World' some_global_function( with ) } That program prints: d: shown: false, focused: true a: title: Hello, World Such implementation of 'with' assumes that obj hasn't method 'with'. But= = this limitation can be removed via aliasing. -- = Regards, Yauheni Akhotnikau
Apr 24 2007
prev sibling next sibling parent reply Dan <murpsoft hotmail.com> writes:
Bill Baxter Wrote:

 I just discovered this little trick that I think is way cool.
 You can use 'with' in combination with an anonymous object to set 
 attributes on that object without having to bother giving it a name or a 
 variable.
 
 
 with(new someGUIWidget(myParent)) {
     shown = true;
     focusable = false;
 }
In JavaScript they've had this "feature" for a very long time. I never, ever use it. Why? x = 3; myFunc = function(){ x = 2; this.x = 1; bla bla bla ginger with(x){ bla bla bla bla ginger bla bla bla bla bla x += 3; bla bla } x -= 2; } That in itself isn't so bad. But in real code, it looks godawful and makes a guy concentrate on scoping it for a second; distracting him from the algorithm.
 That's really nifty for GUI code.
 
 This could be even more useful if there were some kind of 'this' for 
 'with' blocks.  Then you could also call non-member functions.
Lions and tigers and bears, oh my. Can't you just: alias supercalafragilisticexpialadocious.bob.mom.mom.niece.daughter d; d.shown = true; d.focusable = false; etc.?
 with(new someGUIWidget(myParent)) {
     shown = true;
     focusable = false;
     some_global_function(this);
 }
 
 Or perhaps analogous to how constructors are called 'this()' and have a 
 'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
 in a class wouldn't be shadowed:
 
 with(new someGUIWidget(myParent)) {
     some_global_function(with);
 }
Eww... ambiguity and context sensitivity.
 And even cooler would be if you could have a 'with-expression' that just 
 evaluates to the thing in the parens:
 
 auto obj = with(new someGUIWidget(myParent))
 {
     shown = true;
     focusable = false;
     some_global_function(this);
 };
auto obj = new someGuiWidget(myParent){ shown = true; focusable = false; }; some_global_function(obj); <- can't execute in a class declaration. Try in the constructor?
 
 Sometimes I've seen people try to make APIs in C++ where all the 
 attribute setters return the object so that property setting can be 
 chained, like:
 
       myObject.set_focusable(true).set_shown(true);
I did that back in the day too, but not for setting properties, it was for performing more complex algorithms with the DOM, such as making an object move in circles, or fall using a gravity formula.
 Presumably the objective is to avoid repeating the name of the object a 
 lot.  But that never works out too well, because making every mutator 
 return a pointer to 'this' is just not so practical in the end, and 
 forcing every property setting operation to use function call syntax is 
 also not so great.
Property setting operations? Totally agree. Returning a this* isn't so bad unless you have something else to return. I only did it with subroutines. The real reason it's bad is because you're masturbating the stack doing calls like that just to avoid doing something in source code. Such a thing is forgiveable in web scripts where filesize matters, it's not in programming.
Apr 24 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Dan wrote:
 Bill Baxter Wrote:
 
 I just discovered this little trick that I think is way cool.
 You can use 'with' in combination with an anonymous object to set 
 attributes on that object without having to bother giving it a name or a 
 variable.


 with(new someGUIWidget(myParent)) {
     shown = true;
     focusable = false;
 }
In JavaScript they've had this "feature" for a very long time. I never, ever use it. Why? x = 3; myFunc = function(){ x = 2; this.x = 1; bla bla bla ginger with(x){ bla bla bla bla ginger bla bla bla bla bla x += 3; bla bla } x -= 2; } That in itself isn't so bad. But in real code, it looks godawful and makes a guy concentrate on scoping it for a second; distracting him from the algorithm.
You seem to be harping on 'with' in general, not with what I was actually talking about which is using it on unnamed variables. 'with' itself has been in D as long as I've known D, I just didn't realize you could use it with anonymous objects. Anyway, you certainly don't have to like it or use it. But I find it useful in moderation. --bb
Apr 24 2007
prev sibling parent reply BCS <BCS pathlink.com> writes:
Bill Baxter wrote:
 I just discovered this little trick that I think is way cool.
 You can use 'with' in combination with an anonymous object to set 
 attributes on that object without having to bother giving it a name or a 
 variable.
 
 
 with(new someGUIWidget(myParent)) {
    shown = true;
    focusable = false;
 }
 
 That's really nifty for GUI code.
 
 This could be even more useful if there were some kind of 'this' for 
 'with' blocks.  Then you could also call non-member functions.
 
 with(new someGUIWidget(myParent)) {
    shown = true;
    focusable = false;
    some_global_function(this);
 }
 
 Or perhaps analogous to how constructors are called 'this()' and have a 
 'this' pointer, we'd have a 'with' pointer so that the meaning of 'this' 
 in a class wouldn't be shadowed:
 
 with(new someGUIWidget(myParent)) {
    some_global_function(with);
 }
 
 And even cooler would be if you could have a 'with-expression' that just 
 evaluates to the thing in the parens:
 
 auto obj = with(new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(this);
 };
 
 
 Sometimes I've seen people try to make APIs in C++ where all the 
 attribute setters return the object so that property setting can be 
 chained, like:
 
      myObject.set_focusable(true).set_shown(true);
 
 Presumably the objective is to avoid repeating the name of the object a 
 lot.  But that never works out too well, because making every mutator 
 return a pointer to 'this' is just not so practical in the end, and 
 forcing every property setting operation to use function call syntax is 
 also not so great.
 
 --bb
how about take a trick from "if" with(auto name = new someGUIWidget(myParent)) { shown = true; focusable = false; some_global_function(name); }
Apr 24 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
BCS wrote:
 Bill Baxter wrote:
 how about take a trick from "if"
 
 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Apr 24 2007
parent reply BCS <BCS pathlink.com> writes:
Bill Baxter wrote:
 BCS wrote:
 
 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
Apr 24 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
Apr 24 2007
next sibling parent reply Max Samukha <samukha voliacable.com> writes:
On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
Apr 24 2007
next sibling parent reply Max Samukha <samukha voliacable.com> writes:
On Tue, 24 Apr 2007 20:18:24 +0300, Max Samukha
<samukha voliacable.com> wrote:

On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
BTW, there is a bug void main(char[][] f) { int x = 1; if (auto x = 2) { writefln(x); } writefln(x); } x in if() shadows the outer x and it shouldn't according to the specs
Apr 24 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Max Samukha wrote:
 On Tue, 24 Apr 2007 20:18:24 +0300, Max Samukha
 <samukha voliacable.com> wrote:
 
 On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
 <dnewsgroup billbaxter.com> wrote:

 BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
BTW, there is a bug void main(char[][] f) { int x = 1; if (auto x = 2) { writefln(x); } writefln(x); } x in if() shadows the outer x and it shouldn't according to the specs
You mean it should be an error according to the specs, right? --bb
Apr 24 2007
parent Max Samukha <samukha voliacable.com> writes:
On Wed, 25 Apr 2007 02:38:26 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

Max Samukha wrote:
 On Tue, 24 Apr 2007 20:18:24 +0300, Max Samukha
 <samukha voliacable.com> wrote:
 
 On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
 <dnewsgroup billbaxter.com> wrote:

 BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
BTW, there is a bug void main(char[][] f) { int x = 1; if (auto x = 2) { writefln(x); } writefln(x); } x in if() shadows the outer x and it shouldn't according to the specs
You mean it should be an error according to the specs, right? --bb
Yes
Apr 24 2007
prev sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Max Samukha wrote:
 On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
 <dnewsgroup billbaxter.com> wrote:
 
 BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
No that's not what I meant. Note the extra block scope _outside_ the while. That would be silently introduced by the transformation. The scope added is a scope that you have no way of interacting with or introducing code into, so effectively it *is* limiting the var scope to the scope of the while(). Of course there are no "scopes" anyway after everything gets compiled down to ASM, so its all just pleasant fictions to help us poor humans understand what's going on. --bb
Apr 24 2007
parent Max Samukha <samukha voliacable.com> writes:
On Wed, 25 Apr 2007 02:35:02 +0900, Bill Baxter
<dnewsgroup billbaxter.com> wrote:

Max Samukha wrote:
 On Wed, 25 Apr 2007 01:53:56 +0900, Bill Baxter
 <dnewsgroup billbaxter.com> wrote:
 
 BCS wrote:
 Bill Baxter wrote:
 BCS wrote:

 Bill Baxter wrote:
 how about take a trick from "if"

 with(auto name = new someGUIWidget(myParent))
 {
    shown = true;
    focusable = false;
    some_global_function(name);
 }
Yeh, I was actually just thinking that myself, and was disappointed to find out it doesn't work. :-( Looking at the spec it seems that's special to 'if'. It could be useful for switch(), with() and synchronized(), but it seems it hasn't been added. --bb
Ohhh. That would be nice in switch ... and while...
I was thinking 'while' would have issues, because the condition is evaluated multiple times. So I left it off the list. Maybe it's not a problem though. Just make it equiv to { typeof(condition()) x; while(x = condition()) { // do stuff } } --bb
This would be inconsistent with if(), which declares the variable to be local to if's scope. BTW, it'd be nice to have the variable declared outside the if block as you proposed for 'with'. I remember a case or two when I wanted that.
No that's not what I meant. Note the extra block scope _outside_ the while. That would be silently introduced by the transformation. The scope added is a scope that you have no way of interacting with or introducing code into, so effectively it *is* limiting the var scope to the scope of the while(). Of course there are no "scopes" anyway after everything gets compiled down to ASM, so its all just pleasant fictions to help us poor humans understand what's going on. --bb
I understand now. But in your second proposal you want the object to be accessible outside the 'with' block, so would it better to declare the variable outside the scope in the first place? with(auto name = new someGUIWidget(myParent)) { shown = true; focusable = false; some_global_function(name); } name.shown = false;
Apr 24 2007
prev sibling parent reply Dan <murpsoft hotmail.com> writes:
Bill Baxter Wrote:
     typeof(condition()) x;
     while(x = condition()) {
         // do stuff
     }
 }
Which is frighteningly different semantically, while being almost identical syntactically to: while(x == condition()) { Which is probably why Walter didn't want it to work. It concerns me a little that if(x = 3) works. Honestly, D is syntactically abstracted away enough that while(something something) wouldn't have to compile down to evaluating it repeatedly.
Apr 24 2007
parent BCS <BCS pathlink.com> writes:
Dan wrote:
 Bill Baxter Wrote:
 
    typeof(condition()) x;
    while(x = condition()) {
        // do stuff
    }
}
Which is frighteningly different semantically, while being almost identical syntactically to: while(x == condition()) { Which is probably why Walter didn't want it to work. It concerns me a little that if(x = 3) works. Honestly, D is syntactically abstracted away enough that while(something something) wouldn't have to compile down to evaluating it repeatedly.
if(x = 3) doesn't compile. For the If case the syntax requiters that the type specifier be used: if(auto x = 3) // works if(x == 3) // works if(x = 3) // fails OTOH with 'wile' the third case is totally legitimate char x; while(x = getc()) // scan for null and use non null in loop; actually the proposed addition would make that error less likely, in fact the direct assignment could be banned in a while statement. char x; while(auto c = getc()) { x=c; // if last c needed; break; }
Apr 24 2007