Getting started - D meta-program question

Justin Johansson no at spam.com
Sun Oct 4 10:49:13 PDT 2009


downs Wrote:

> Justin Johansson wrote:
> > Daniel Keep Wrote:
> > 
> > Just now I've written a bit of CS101 play around code (shown below) for constructing a
> > singly-linked list of numbers (Conslist idiom).  As the code seems to work, it looks like
> > I've cut my first teeth on "D meta programming".
> > 
> > I'm sure there's lots to learn though .. especially looking though some of that std.functional
> > stuff.
> > 
> > If you have any comments / suggestions for improvement about this code, I'd graciously accept the same.
> > It's just a tutorial exercise for learning the D way of doing things.
> > 
> > 
> > class List
> > {
> >    List next;
> >    int data;
> > 
> >    this( int data) {
> >       this.next = null;
> >       this.data = data;
> >    }
> > 
> >    static List opCall() {
> >       return cast(List) null;
> >    }
> > 
> >    static List opCall( int data) {
> >       return new List( data);
> >    }
> > 
> >    static List cons( int data, List list) {
> >       auto newList = List( data);
> >       newList.next = list;
> >       return newList;
> >    }
> > 
> >    int opApply( int delegate( ref int data) dg) {
> >       auto result = 0;
> >       auto list = this;
> > 
> >       while ( list !is null) {
> >          if ((result = dg( list.data)) != 0)
> >             break;
> > 
> >          list = list.next;
> >       }
> > 
> >       return result;
> >    }
> > 
> > }
> > 
> > 
> > void printdata( int data) {
> >    writef( " %d", data);
> > }
> > 
> > 
> > void print( List list) {
> >    writef( "(");
> > 
> >    if (list !is null) {
> >       foreach ( x; list) {
> >          printdata( x);
> >       }
> >    }
> > 
> >    writef( ")");
> > }
> > 
> > 
> > void println( List list) {
> >    print( list);
> >    writefln();
> > }
> > 
> > 
> > List list(A...)( A args) {
> >    static if (A.length == 0) {
> >       return List();
> >    }
> > 
> >    else {
> >       return List.cons( args[0], list( args[1..$]));
> >    }
> > }
> > 
> > 
> > void main() {
> >    auto l0 = list();
> >    println( l0);
> >    
> >    auto l1 = list( 10);
> >    println( l1);
> >    
> >    auto l2 = list( 10, 20);
> >    println( l2);
> >    
> >    auto l3 = list( 10, 20, 30);
> >    println( l3);
> >    
> > }
> > 
> > 
> > Outputs:
> > 
> > ()
> > ( 10)
> > ( 10 20)
> > ( 10 20 30)
> > 
> > Thanks again, Justin
> > 
> 
> I really recommend using a struct. There's rarely need to subclass List nodes dynamically, and structs would allow you to define allocators externally, for instance, for implementing freelists.
> 
> Also, I generally think of a list node as a value, not an object :)
> 
> In that sense ..
> module test;
> 
> import std.string;
> struct List(T)
> {
>   List* next;
>   T data;
> 
>   static List* opCall(T data, List* next) {
>     auto res = new List;
>     res.next = next;
>     res.data = data;
>     return res;
>   }
>   static List* opCall(T[] data...) {
>     if (!data.length) return null;
>     else if (data.length == 1) return opCall(data[0], null);
>     else return opCall(data[0], opCall(data[1..$]));
>   }
>   List* cons(T data) { return List(data, this); }
> 
>   int opApply( int delegate( ref int data) dg) {
>     auto current = this;
> 
>     do {
>       if (auto res = dg(current.data)) return res;
>       current = current.next;
>     } while (current);
> 
>     return 0;
>   }
>   string toString() {
>     string res = "(";
>     bool first = true;
>     foreach (value; *this) {
>       if (first) first = false;
>       else res ~= ", ";
>       res ~= format(value);
>     }
>     return res ~ ")";
>   }
> }
> 
> void print(T)(T what) {
>   if (!what) writefln("(nil)");
>   else writefln(what.toString());
> }
> 
> import std.stdio;
> void main() {
>   auto l0 = List!(int)();
>   print(l0);
> 
>   auto l1 = List!(int)(10);
>   print(l1);
> 
>   auto l2 = List!(int)(10, 20);
>   print(l2);
> 
>   auto l3 = List!(int)(10, 20, 30);
>   print(l3);
> }


Great, this question was well worth asking :-)

My code above was true to C style.

Your code as below, using auto to declare a temporary var in an if statement, ahh, nice,
didn't know that.

         if (auto res = dg(current.data))
            return res;

What other statement types can you generalized use of auto like this to?

> I really recommend using a struct. There's rarely need to subclass List nodes dynamically, and structs would allow you to define allocators externally, for instance, for implementing freelists.

I think with the overhead of at least 8 bytes for a PODO, your suggestion certainly makes sense;
struct is a lot greener than class in this case, though going by some of the posts on the main discussion
list, you get the feeling that structs are frowned these days upon by some of the language pundits.

Thank you for taking the time downs,

-- Justin


More information about the Digitalmars-d-learn mailing list