www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - dual with statement

reply "Jay Norwood" <jayn prismnet.com> writes:
I was playing around with use of the dual WITH statement.   I 
like the idea, since it makes the code within the with cleaner.   
Also, I got the impression from one of the conference 
presentations ... maybe the one on the ARM debug ... that there 
are some additional optimizations available that the compiler 
processes the WITH statement block.

Anyway, a problem I ran into was if two structures had the same 
member names, for example struct ar.r and ar.psm in this case 
below.   In this case, there was no way for the compiler to 
determine from which structure to get the member.

void calc_per_sec_met(ref All ar){

        with (ar.r) with(ar.psm) {
               double per_sec = proc_cyc/ref_clock;
               d = (a+c)*per_sec;
               e = (c==0)?0:(a+b)/c;
        }
}

ok, so I guess I could make all the member names unique in the 
different structures, but that's kind of ugly.

Also, what happens if using two structs of the same type in a 
WITH statement.
Seems like something like this would help, which I believe I've 
seen used in database queries ...

  with (ar.r1 as r1) with (ar.r2 as r2){
    auto sum = r1.a + r2.a;
  }
Jul 24 2014
next sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 24 July 2014 at 17:19:36 UTC, Jay Norwood wrote:
 I was playing around with use of the dual WITH statement.   I 
 like the idea, since it makes the code within the with cleaner.
   Also, I got the impression from one of the conference 
 presentations ... maybe the one on the ARM debug ... that there 
 are some additional optimizations available that the compiler 
 processes the WITH statement block.

 Anyway, a problem I ran into was if two structures had the same 
 member names, for example struct ar.r and ar.psm in this case 
 below.   In this case, there was no way for the compiler to 
 determine from which structure to get the member.

 void calc_per_sec_met(ref All ar){

        with (ar.r) with(ar.psm) {
               double per_sec = proc_cyc/ref_clock;
               d = (a+c)*per_sec;
               e = (c==0)?0:(a+b)/c;
        }
 }

 ok, so I guess I could make all the member names unique in the 
 different structures, but that's kind of ugly.

 Also, what happens if using two structs of the same type in a 
 WITH statement.
 Seems like something like this would help, which I believe I've 
 seen used in database queries ...

  with (ar.r1 as r1) with (ar.r2 as r2){
    auto sum = r1.a + r2.a;
  }
Just because "with" makes it that you don't have to be explicit, doesn't mean you can't: struct S { int i; int k; } struct T { int j; int k; } void main() { S s; T t; int sum; with (s) with (t) { sum = i + j + s.k + t.k; } } Or did I miss something?
Jul 24 2014
parent reply "Jay Norwood" <jayn prismnet.com> writes:
On Thursday, 24 July 2014 at 20:16:53 UTC, monarch_dodra wrote:
 Or did I miss something?
Yes, sorry, I should have pasted a full example previously. The code at the end is with the Raw_met members renamed (they were originally a and b but clashed). So, if Raw_met members were still a and b ... with(ar.r as v) with (ar.rm as res){ res.a = v.a + v.c; res.b = (v.c==0)? 0: (v.a + v.b)/ v.c; I don't recall the exact use case for the database expressions, but I believe they were substituting a simple symbol for the fully qualified object. So they would have done something analogous to this ... with (ar.rm.a as d) with (ar.rm.b as e) with (ar.r.a as a) with (ar.r.b as b) with (ar.r.c as c){ d = a + c; e = (c==0)?0:(a+b)/c; } So, the expressions are simpler to read, and I've fully qualified the members only a single time. ---- this is the code for one of the metric experiments, with the members renamed to avoid the clashes. I like that the expressions can be so simple. double ref_clock=1_600_000_000.0; struct Raw_met {long d; double e;} struct Per_sec_met {double d; double e; } struct Per_cyc_met {double d; double e; } struct Raw {long proc_cyc; long a; long b; long c; } struct Per_sec {double proc_cyc; double a; double b; double c; } struct Per_cyc {double proc_cyc; double a; double b; double c; } struct All { Raw r; Per_sec ps; Per_cyc pc; Raw_met rm; Per_sec_met psm; Per_cyc_met pcm;} void calc_raw_met(ref All ar){ with(ar.r) with(ar.rm){ d = a+c; e = (c==0)?0:(a+b)/c; } }
Jul 24 2014
next sibling parent "Jay Norwood" <jayn prismnet.com> writes:
On Friday, 25 July 2014 at 01:54:53 UTC, Jay Norwood wrote:
 I don't recall the exact use case for the database expressions, 
 but I believe they were substituting a simple symbol for the 
 fully qualified object.
The sql with clause is quite a bit different than I remembered. For one thing, I have the order reversed, so it would have been with (a as something.x.y). It looks more like they are more like creating a temporary tuple from some more complicated selection. It isn't clear what the implementation is, but just the that it might be a more concise way of stating things so that the expressions inside the body can be simple So, my prior example with (ar.rm.a as d) with (ar.rm.b as e) with (ar.r.a as a) with (ar.r.b as b) with (ar.r.c as c){ d = a + c; e = (c==0)?0:(a+b)/c; } would reduce to something maybe simpler to read. The sql seems to be using this as a foreach type operation, but I was just interested in the name substitution so that the expressions inside the with block could be simpler, as well as get rid of the struct member name clashes. with ( (d,e,a,b,c) as (ar.rm.a, ar.rm.b, ar.r.a, ar.r.b, ar.r.c)){ d = a + c; e = (c==0)?0:(a+b)/c; }
Jul 25 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 25 July 2014 at 01:54:53 UTC, Jay Norwood wrote:
 On Thursday, 24 July 2014 at 20:16:53 UTC, monarch_dodra wrote:
 Or did I miss something?
Yes, sorry, I should have pasted a full example previously. The code at the end is with the Raw_met members renamed (they were originally a and b but clashed). So, if Raw_met members were still a and b ... with(ar.r as v) with (ar.rm as res){ res.a = v.a + v.c; res.b = (v.c==0)? 0: (v.a + v.b)/ v.c; I don't recall the exact use case for the database expressions, but I believe they were substituting a simple symbol for the fully qualified object. So they would have done something analogous to this ...
Isn't: with(foo.bar as baz) { ... } Functionally nothing more than an alias? EG: { alias baz = foo.bar; ... } Or mix of both. I don't see a need for "as".
Jul 25 2014
parent "Jay Norwood" <jayn prismnet.com> writes:
On Friday, 25 July 2014 at 21:10:56 UTC, monarch_dodra wrote:
 Functionally nothing more than an alias? EG:
 {
     alias baz = foo.bar;
     ...
 }
Yes, it is all just alias. So with ( (d,e,a,b,c) as (ar.rm.a, ar.rm.b, ar.r.a, ar.r.b, ar.r.c)){ d = a + c; e = (c==0)?0:(a+b)/c; } could be instead { alias d = ar.rm.a; alias e = ar.rm.b; alias a = ar.r.a; alias b = ar.r.b; alias c = ar.r.c; d = a + c; e = (c==0)?0:(a+b)/c; } I guess this means I don't need WITH.
Jul 26 2014
prev sibling parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 24 July 2014 at 17:19:36 UTC, Jay Norwood wrote:
 Anyway, a problem I ran into was if two structures had the same 
 member names, for example struct ar.r and ar.psm in this case 
 below.   In this case, there was no way for the compiler to 
 determine from which structure to get the member.
From what I can observe, the compiler resolves the ambiguity by chosing the first match in terms of scope. Eg, there's shadowing. From my previous code: with (t) { writeln(k); //prints t.k with(s) { writeln(k); //prints s.k: it is now shadowing t.k
Jul 24 2014
parent "bearophile" <bearophileHUGS lycos.com> writes:
monarch_dodra:

 From what I can observe, the compiler resolves the ambiguity by 
 chosing the first match in terms of scope. Eg, there's 
 shadowing. From my previous code:



 with (t)
 {
     writeln(k); //prints t.k
     with(s)
     {
         writeln(k); //prints s.k: it is now shadowing t.k
A reduced test case: void main() { static struct S { int k = 1; } static struct T { int k = 2; } S s; T t; with (t) { assert(k == 2); with(s) { assert(k == 1); } } } Is this a failure (a bug) of the anti-hijacking mechanism of with()? Bye, bearophile
Jul 24 2014