Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
May 03, 2006 mixin extension | ||||
---|---|---|---|---|
| ||||
Here's an idea to extend mixins in a manner that would allow you to mix code around a block in D. If you had: template Trace(f:char[]) { printf("Entering %s", f); } { printf("Exiting %s", f); } Note the two blocks associated with a single template declaration. You might mix code around a third block with: void test() { mixin Trace!("test") { do_something(); more_here(); } } resulting in the equivalent of: void test() { printf("Entering %s", f); do_something(); more_here(); printf("Exiting %s", f); } Ideally, such a construct could be used in conjunction with a conditional version statement: void test() { version (Log) mixin Trace!("test") { do_something(); more_here(); } } which when logging is disabled would evaluate to: void test() { do_something(); more_here(); } Is this feasible? Are there better ways? Matthias |
May 04, 2006 Re: mixin extension | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Spycher | Howdy. Matthias Spycher wrote: > Here's an idea to extend mixins in a manner that would allow you to mix code around a block in D. > > If you had: > > template Trace(f:char[]) > { > printf("Entering %s", f); > } > { > printf("Exiting %s", f); > } How about this instead: template Trace(f:char[], block inner_block) { writefln("Entering %s", f); inner_block; writefln("Exiting %s", f); } That way, you can also support more complicated constructs like this: template Repeat(int times, block inner_block) { for( int i=0; i<times; i++ ) inner_block; } Of course, the problem with this is that templates only allow for declarations, not arbitrary statements. Perhaps we could then add the following, which would mix a block into the instantiating scope: template Repeat(int times, block inner_block) { block Repeat { for( int i=0; i<times; i++ ) inner_block; } } > > Note the two blocks associated with a single template declaration. You might mix code around a third block with: > > void test() > { > mixin Trace!("test") { > do_something(); > more_here(); > } > } > Personally, I'd like to be able to drop the "mixin" keyword. I realise that semantically, it makes sense since you're mixing the contents of the template in, but without it, it just looks cooler :) void test() { Trace!("test") { do_something(); more_here(); } } > resulting in the equivalent of: > > void test() > { > printf("Entering %s", f); > do_something(); > more_here(); > printf("Exiting %s", f); > } > > Ideally, such a construct could be used in conjunction with a conditional version statement: > > void test() > { > version (Log) mixin Trace!("test") { > do_something(); > more_here(); > } > } > > which when logging is disabled would evaluate to: > > void test() > { > do_something(); > more_here(); > } > > Is this feasible? Are there better ways? > > Matthias I'll steal a Pythonism, and vote +1. This would be *really* handy, and it would allow for the creation of almost arbitrary control structures! For the longest time, I've had evil thoughts of making a D preprocessor that only operated on complete, valid parse trees. It would basically be a D compiler that read in D, modified it in some way, then spat it back out. With that, you could make structures like this: fori( int i; 10 ) block; Which would be "expanded" by the preprocessor as: for( int i=0; i<10; i++ ) block; But using the above idea, you could just write this as a template: template fori(alias variable, int limit, block inner) { block fori { for( variable = 0; variable < limit; variable++ ) inner; } } Of course, this would be helped if we could drop in arbitrary symbols or declarations, but I can live without that :) -- Daniel "Must... have... meta... programming..." Keep -- v1sw5+8Yhw5ln4+5pr6OFma8u6+7Lw4Tm6+7l6+7D a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/ |
May 04, 2006 Re: mixin extension | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Passing a block of code to a template is a nice and original idea.
Overall, I like it, and it gets my vote.
Daniel Keep wrote:
> Howdy.
>
> Matthias Spycher wrote:
>
>>Here's an idea to extend mixins in a manner that would allow you to mix
>>code around a block in D.
>>
>>If you had:
>>
>>template Trace(f:char[])
>>{
>> printf("Entering %s", f);
>>}
>>{
>> printf("Exiting %s", f);
>>}
>
>
> How about this instead:
>
> template Trace(f:char[], block inner_block)
> {
> writefln("Entering %s", f);
> inner_block;
> writefln("Exiting %s", f);
> }
>
> That way, you can also support more complicated constructs like this:
>
> template Repeat(int times, block inner_block)
> {
> for( int i=0; i<times; i++ )
> inner_block;
> }
>
> Of course, the problem with this is that templates only allow for
> declarations, not arbitrary statements. Perhaps we could then add the
> following, which would mix a block into the instantiating scope:
>
> template Repeat(int times, block inner_block)
> {
> block Repeat
> {
> for( int i=0; i<times; i++ )
> inner_block;
> }
> }
>
>
>>Note the two blocks associated with a single template declaration. You
>>might mix code around a third block with:
>>
>>void test()
>>{
>> mixin Trace!("test") {
>> do_something();
>> more_here();
>> }
>>}
>>
>
>
> Personally, I'd like to be able to drop the "mixin" keyword. I realise
> that semantically, it makes sense since you're mixing the contents of
> the template in, but without it, it just looks cooler :)
>
> void test()
> {
> Trace!("test")
> {
> do_something();
> more_here();
> }
> }
>
>
>>resulting in the equivalent of:
>>
>>void test()
>>{
>> printf("Entering %s", f);
>> do_something();
>> more_here();
>> printf("Exiting %s", f);
>>}
>>
>>Ideally, such a construct could be used in conjunction with a
>>conditional version statement:
>>
>>void test()
>>{
>> version (Log) mixin Trace!("test") {
>> do_something();
>> more_here();
>> }
>>}
>>
>>which when logging is disabled would evaluate to:
>>
>>void test()
>>{
>> do_something();
>> more_here();
>>}
>>
>>Is this feasible? Are there better ways?
>>
>>Matthias
>
>
> I'll steal a Pythonism, and vote +1. This would be *really* handy, and
> it would allow for the creation of almost arbitrary control structures!
>
> For the longest time, I've had evil thoughts of making a D preprocessor
> that only operated on complete, valid parse trees. It would basically
> be a D compiler that read in D, modified it in some way, then spat it
> back out. With that, you could make structures like this:
>
> fori( int i; 10 )
> block;
>
> Which would be "expanded" by the preprocessor as:
>
> for( int i=0; i<10; i++ )
> block;
>
> But using the above idea, you could just write this as a template:
>
> template fori(alias variable, int limit, block inner)
> {
> block fori
> {
> for( variable = 0; variable < limit; variable++ )
> inner;
> }
> }
>
> Of course, this would be helped if we could drop in arbitrary symbols or
> declarations, but I can live without that :)
>
> -- Daniel "Must... have... meta... programming..." Keep
>
|
May 04, 2006 Re: mixin extension | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthias Spycher | Matthias Spycher wrote: > Here's an idea to extend mixins in a manner that would allow you to mix code around a block in D. > > If you had: > > template Trace(f:char[]) > { > printf("Entering %s", f); > } > { > printf("Exiting %s", f); > } > > Note the two blocks associated with a single template declaration. You might mix code around a third block with: <snip> A template in D is a collection of declarations. The idea of overloading them like this doesn't really make sense to me. Besides, I can imagine it being difficult to parse, possibly even ambiguous, if you have to worry about whether each template has one or two bodies. But the concept of reusable in/out blocks isn't a bad one. We could have it, but we should think a bit about the notation. Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:-@ C++@ a->--- UB@ P+ L E@ W++@ N+++ o K-@ w++@ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit. |
May 04, 2006 Re: mixin extension | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Hi Daniel,
I thought about passing blocks into templates as well, but I think we'd be getting too close to lisp doing this sort of thing. No doubt it's a very powerful construct. I was thinking about code weaving and aspect-oriented programming, etc., and I find that conditionally mixing in code around some block is a rather frequent pattern.
Matthias
Daniel Keep wrote:
> Howdy.
>
> Matthias Spycher wrote:
>> Here's an idea to extend mixins in a manner that would allow you to mix
>> code around a block in D.
>>
>> If you had:
>>
>> template Trace(f:char[])
>> {
>> printf("Entering %s", f);
>> }
>> {
>> printf("Exiting %s", f);
>> }
>
> How about this instead:
>
> template Trace(f:char[], block inner_block)
> {
> writefln("Entering %s", f);
> inner_block;
> writefln("Exiting %s", f);
> }
>
> That way, you can also support more complicated constructs like this:
>
> template Repeat(int times, block inner_block)
> {
> for( int i=0; i<times; i++ )
> inner_block;
> }
>
> Of course, the problem with this is that templates only allow for
> declarations, not arbitrary statements. Perhaps we could then add the
> following, which would mix a block into the instantiating scope:
>
> template Repeat(int times, block inner_block)
> {
> block Repeat
> {
> for( int i=0; i<times; i++ )
> inner_block;
> }
> }
>
>> Note the two blocks associated with a single template declaration. You
>> might mix code around a third block with:
>>
>> void test()
>> {
>> mixin Trace!("test") {
>> do_something();
>> more_here();
>> }
>> }
>>
>
> Personally, I'd like to be able to drop the "mixin" keyword. I realise
> that semantically, it makes sense since you're mixing the contents of
> the template in, but without it, it just looks cooler :)
>
> void test()
> {
> Trace!("test")
> {
> do_something();
> more_here();
> }
> }
>
>> resulting in the equivalent of:
>>
>> void test()
>> {
>> printf("Entering %s", f);
>> do_something();
>> more_here();
>> printf("Exiting %s", f);
>> }
>>
>> Ideally, such a construct could be used in conjunction with a
>> conditional version statement:
>>
>> void test()
>> {
>> version (Log) mixin Trace!("test") {
>> do_something();
>> more_here();
>> }
>> }
>>
>> which when logging is disabled would evaluate to:
>>
>> void test()
>> {
>> do_something();
>> more_here();
>> }
>>
>> Is this feasible? Are there better ways?
>>
>> Matthias
>
> I'll steal a Pythonism, and vote +1. This would be *really* handy, and
> it would allow for the creation of almost arbitrary control structures!
>
> For the longest time, I've had evil thoughts of making a D preprocessor
> that only operated on complete, valid parse trees. It would basically
> be a D compiler that read in D, modified it in some way, then spat it
> back out. With that, you could make structures like this:
>
> fori( int i; 10 )
> block;
>
> Which would be "expanded" by the preprocessor as:
>
> for( int i=0; i<10; i++ )
> block;
>
> But using the above idea, you could just write this as a template:
>
> template fori(alias variable, int limit, block inner)
> {
> block fori
> {
> for( variable = 0; variable < limit; variable++ )
> inner;
> }
> }
>
> Of course, this would be helped if we could drop in arbitrary symbols or
> declarations, but I can live without that :)
>
> -- Daniel "Must... have... meta... programming..." Keep
>
|
May 05, 2006 Re: mixin extension | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Daniel Keep wrote: > Howdy. > > Matthias Spycher wrote: >> Here's an idea to extend mixins in a manner that would allow you to mix >> code around a block in D. >> >> If you had: >> >> template Trace(f:char[]) >> { >> printf("Entering %s", f); >> } >> { >> printf("Exiting %s", f); >> } > > How about this instead: > > template Trace(f:char[], block inner_block) > { > writefln("Entering %s", f); > inner_block; > writefln("Exiting %s", f); > } > > That way, you can also support more complicated constructs like this: > > template Repeat(int times, block inner_block) > { > for( int i=0; i<times; i++ ) > inner_block; > } > > Of course, the problem with this is that templates only allow for > declarations, not arbitrary statements. Perhaps we could then add the > following, which would mix a block into the instantiating scope: > > template Repeat(int times, block inner_block) > { > block Repeat > { > for( int i=0; i<times; i++ ) > inner_block; > } > } > >> Note the two blocks associated with a single template declaration. You >> might mix code around a third block with: >> >> void test() >> { >> mixin Trace!("test") { >> do_something(); >> more_here(); >> } >> } >> > > Personally, I'd like to be able to drop the "mixin" keyword. I realise > that semantically, it makes sense since you're mixing the contents of > the template in, but without it, it just looks cooler :) > > void test() > { > Trace!("test") > { > do_something(); > more_here(); > } > } > >> resulting in the equivalent of: >> >> void test() >> { >> printf("Entering %s", f); >> do_something(); >> more_here(); >> printf("Exiting %s", f); >> } >> >> Ideally, such a construct could be used in conjunction with a >> conditional version statement: >> >> void test() >> { >> version (Log) mixin Trace!("test") { >> do_something(); >> more_here(); >> } >> } >> >> which when logging is disabled would evaluate to: >> >> void test() >> { >> do_something(); >> more_here(); >> } >> >> Is this feasible? Are there better ways? >> >> Matthias > > I'll steal a Pythonism, and vote +1. This would be *really* handy, and > it would allow for the creation of almost arbitrary control structures! > > For the longest time, I've had evil thoughts of making a D preprocessor > that only operated on complete, valid parse trees. It would basically > be a D compiler that read in D, modified it in some way, then spat it > back out. With that, you could make structures like this: > > fori( int i; 10 ) > block; > > Which would be "expanded" by the preprocessor as: > > for( int i=0; i<10; i++ ) > block; > > But using the above idea, you could just write this as a template: > > template fori(alias variable, int limit, block inner) > { > block fori > { > for( variable = 0; variable < limit; variable++ ) > inner; > } > } > > Of course, this would be helped if we could drop in arbitrary symbols or > declarations, but I can live without that :) > > -- Daniel "Must... have... meta... programming..." Keep > I have proposed this before: http://www.digitalmars.com/d/archives/digitalmars/D/24770.html Shot down. :( -DavidM |
Copyright © 1999-2021 by the D Language Foundation