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=



 'this' pointer, we'd have a 'with' pointer so that the meaning of  =



 'this' in a class wouldn't be shadowed:


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: # Just a demo class. class Demo attr_reader :shown attr_reader :focused end # Yet another demo class. class AnotherDemo attr_reader :title end # A globe function to be called with 'with' keyword. def some_global_function( obj ) p obj end # This is implementation of 'with'. def with( obj, &blk ) # 1: introduce a new method 'with' into object 'obj'. class <<obj def with; self; end end # 2: run the specified block on 'obj' context. # Because now 'obj' has method 'with' it can be # called from block body. begin obj.instance_eval &blk ensure # 3: method 'with' no more needed. class <<obj remove_method( :with ) end end obj end # This is usage of 'with' d =3D with( Demo.new ) { shown =3D false focused =3D true # Content of new object of class Demo must be shown here. some_global_function( with ) } a =3D with( AnotherDemo.new ) { title =3D 'Hello, World' # Content of new object of class AnotherDemo must be shown here. some_global_function( with ) } # Simple debug output. puts "d: shown: #{d.shown}, focused: #{d.focused}" puts "a: title: #{a.title}" That program prints: #<Demo:0x2c7d448 shown=3Dfalse, focused=3Dtrue> #<AnotherDemo:0x2c7d3f8 title=3D"Hello, World"> 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 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


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

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


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

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


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


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