www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - useful mixin

reply David Medlock <noone nowhere.com> writes:
This is no doubt been posted but I thought I would post it anyhow.

Often you have a class which basically adds functionality over a map or 
array.  These two mixins implement the opApply/opIndex functions for you.

//// THE CODE ==================

template applyThis( V, alias var )
{
   public int opApply( int delegate( inout V val ) dg )
   {
     int n = 0;
     foreach( V val; var ) { n = dg(val); if (n) break; }
     return n;
   }
   public int opApply( int delegate( inout int index, inout V val ) dg )
   {
     int n = 0;
     foreach( int index, V val; var ) { n = dg(index,val); if (n) break; }
     return n;
   }
   public V opIndex( int index )
   {
     if ( index<=var.length ) return V.init;
     return var[index];
   }
   public V opIndexAssign( V val, int index )
   {
     if ( var.length<=index ) var.length = index+1;
     return var[index] = val;
   }
}

template applyThis( K, V, alias var )
{
   public int opApply( int delegate( inout K key, inout V val ) dg )
   {
     int n = 0;
     foreach( K key, V val; var ) { n = dg(key,val); if (n) break; }
     return n;
   }

   public V opIndex( K key )
   {
     V* ptr = (key in var);
     if ( ptr is null ) return V.init;
     else return ptr[0];
   }

   public V opIndexAssign( V val, K key )
   {
     return var[key] = val;
   }
}



///  Example: ==================
class MyWidgets
{
   Widget[]		widgets;
   Widget[char[]]	lookup;

   //... other useful stuff
   mixin applyThis!( Widget, widgets );
   mixin applyThis!( char[], Widget, lookup );
}

-DavidM
Aug 31 2005
parent Carlos Santander <csantander619 gmail.com> writes:
David Medlock escribió:
 This is no doubt been posted but I thought I would post it anyhow.
 
 Often you have a class which basically adds functionality over a map or 
 array.  These two mixins implement the opApply/opIndex functions for you.
 
 //// THE CODE ==================
 
 template applyThis( V, alias var )
 {
   public int opApply( int delegate( inout V val ) dg )
   {
     int n = 0;
     foreach( V val; var ) { n = dg(val); if (n) break; }
     return n;
   }
   public int opApply( int delegate( inout int index, inout V val ) dg )
   {
     int n = 0;
     foreach( int index, V val; var ) { n = dg(index,val); if (n) break; }
     return n;
   }
   public V opIndex( int index )
   {
     if ( index<=var.length ) return V.init;
     return var[index];
   }
   public V opIndexAssign( V val, int index )
   {
     if ( var.length<=index ) var.length = index+1;
     return var[index] = val;
   }
 }
 
 template applyThis( K, V, alias var )
 {
   public int opApply( int delegate( inout K key, inout V val ) dg )
   {
     int n = 0;
     foreach( K key, V val; var ) { n = dg(key,val); if (n) break; }
     return n;
   }
 
   public V opIndex( K key )
   {
     V* ptr = (key in var);
     if ( ptr is null ) return V.init;
     else return ptr[0];
   }
 
   public V opIndexAssign( V val, K key )
   {
     return var[key] = val;
   }
 }
 
 
 
 ///  Example: ==================
 class MyWidgets
 {
   Widget[]        widgets;
   Widget[char[]]    lookup;
 
   //... other useful stuff
   mixin applyThis!( Widget, widgets );
   mixin applyThis!( char[], Widget, lookup );
 }
 
 -DavidM
Funny: I defined a couple of similar mixins for my project, except that I didn't define opIndex nor opIndexAssign. This solution has a problem when you need opApply for more than one collection. Eg: class MyWidgets { Widget[] widgets; Widget[char[]] lookup; Property[char[]] properties; //or whatever you want //... other useful stuff mixin applyThis!( Widget, widgets ); mixin applyThis!( char[], Widget, lookup ); mixin applyThis!( char[], Property, properties ); } The compiler won't let you do that, so you have to do: mixin applyThis!( Widget, widgets ) foo1; mixin applyThis!( char[], Widget, lookup ) foo2; mixin applyThis!( char[], Property, properties ) foo3; alias foo1.opApply opApply; alias foo2.opApply opApply; ... It's the only downside. -- Carlos Santander Bernal
Aug 31 2005