View mode: basic / threaded / horizontal-split · Log in · Help
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
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
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
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
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
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
Top | Discussion index | About this forum | D home